-1

I am new to apex. Getting this error

System.DmlException: Upsert failed. First exception on row 0 with id aBfn000000062BMCAY; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, OP_DeferralTrigger: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.OP_DeferralTrigger: line 42, column 1: []

Error Comes at Line 42 of Trigger i.e if(string.isNotEmpty(objPDCN.T179_BRAND__c) && objPDCN.T179_BRAND__c.toLowerCase().contains('stella') && objForecast.Wholesaler_Forecast__c != null && objForecast.Wholesaler_Forecast__c < 150)

Why do I get this error? How can I fix it?

Trigger :-

trigger OP_DeferralTrigger on Forcast__c (before Update) {

    Set<string> setGenericPDCNNo = new Set<string>();
    Set<Double> setWholesaler = new Set<Double>();
    Set<Date> setWeekDate = new Set<Date>();

    Map<string, PDCN__c> mapPDCN = new Map<string, PDCN__c>();
    List<Sales_History__c> lstSalesHistory = new List<Sales_History__c>();
    List<String> lstStringWholesaler = new List<String>();

    for(Forcast__c objForecast : trigger.new){
        setGenericPDCNNo.add(objForecast.Generic_PDCN__c);
        setWholesaler.add(objForecast.Wholesaler_Number__c);
        setWeekDate.add(objForecast.Forecast_Week_StartDate__c);
    }

    for(Double dblWholesaler : setWholesaler){
        lstStringWholesaler.add(string.valueOf(dblWholesaler));
    }

    //Get PDCN Data
    for(PDCN__c objPDCN : [SELECT Id, Brand_Standard_Name__c, Brand_Trademark_Name2__c, Generic_PDCN__c, T179_BRAND__c,
                           Brand_Trademark_Name__c FROM PDCN__c WHERE Generic_PDCN__c IN :setGenericPDCNNo]){
                               mapPDCN.put(objPDCN.Generic_PDCN__c, objPDCN);
                           }

    //Get SalesHistory
    lstSalesHistory = [SELECT Generic_PDCN__c, Wholesaler_Number__c, Actual_Sales__c 
                       FROM Sales_History__c WHERE Generic_PDCN__c IN :setGenericPDCNNo 
                       AND Wholesaler_Number__c IN :setWholesaler];

    //Get Inventory
    List<Inventory_Weekly__c> lstInventory = [SELECT Generic_PDCN__c, Wholesaler_Id__c, Week_Date__c, Stock_Qty_1__c 
                                              FROM Inventory_Weekly__c];    /* WHERE Generic_PDCN__c IN :setGenericPDCNNo 
                                              AND Wholesaler_Id__c IN :lstStringWholesaler AND Week_Date__c IN :setWeekDate*/

    For (Forcast__c objForecast : trigger.new){
        List<String> lstDeferralRules = new List<String>();    
        System.debug(LoggingLevel.Error, 'Entereed in trigger');
        //Brand Increase/Decrease
        PDCN__c objPDCN = mapPDCN.get(objForecast.Generic_PDCN__c);        
        if(string.isNotEmpty(objPDCN.T179_BRAND__c) && objPDCN.T179_BRAND__c.toLowerCase().contains('stella') 
           && objForecast.Wholesaler_Forecast__c != null && objForecast.Wholesaler_Forecast__c < 150){
               lstDeferralRules.add('Brand Increase/Decrease');      
               System.debug(LoggingLevel.Error, 'Brand Increase/Decrease');
           }  

        //New Product Greater than Inventory
        Inventory_Weekly__c objInventory = getInventoryData(objForecast.Generic_PDCN__c, string.valueOf(objForecast.Wholesaler_Number__c), objForecast.Forecast_Week_StartDate__c);
        boolean isExists = isSalesHistoryExists(objForecast.Generic_PDCN__c, objForecast.Wholesaler_Number__c);
        System.debug(LoggingLevel.Error, 'isExists--'+isExists);
        System.debug(LoggingLevel.Error, 'objInventory.Stock_Qty_1__c---'+objInventory.Stock_Qty_1__c);
        System.debug(LoggingLevel.Error, 'objForecast.Wholesaler_Forecast__c---'+objForecast.Wholesaler_Forecast__c);
        if(!isExists && objInventory != null && objForecast.Wholesaler_Forecast__c != null && objInventory.Stock_Qty_1__c < objForecast.Wholesaler_Forecast__c){
            lstDeferralRules.add('New Product Greater than Inventory');
            System.debug(LoggingLevel.Error, 'New Product Greater than Inventory');
        }

        //104 Week Max/Min
        decimal minSale = minSalesHistoryExists(objForecast.Generic_PDCN__c, objForecast.Wholesaler_Number__c);
        decimal maxSale = maxSalesHistoryExists(objForecast.Generic_PDCN__c, objForecast.Wholesaler_Number__c);
        if(objForecast.Wholesaler_Forecast__c != null 
           && ((minSale > 0 && objForecast.Wholesaler_Forecast__c < minSale) || 
           (maxSale > 0 && objForecast.Wholesaler_Forecast__c > maxSale))){
               lstDeferralRules.add('104 Week Max/Min');
               System.debug(LoggingLevel.Error, '104 Week Max/Min');
           }


        //Variance Exceeded
        System.debug('objForecast.Wholesaler_Forecast__c -- '+objForecast.Wholesaler_Forecast__c);
        System.debug('objForecast.Operational_Forecast__c -- '+objForecast.Operational_Forecast__c);
        decimal variance = 0;
        if(objForecast.Wholesaler_Forecast__c != null)
            variance = ((objForecast.Wholesaler_Forecast__c - objForecast.Operational_Forecast__c)/objForecast.Operational_Forecast__c) * 100;
        System.debug('variance -- '+variance);
        if(variance > 6){
            lstDeferralRules.add('Variance Exceeded');
            System.debug(LoggingLevel.Error, 'Variance Exceeded');
        }


        //New Product 1000 Unit (100%) Change
        if(!isExists && variance > 100){
            lstDeferralRules.add('New Product 1000 Unit (100%) Change');
            System.debug(LoggingLevel.Error, 'New Product 1000 Unit (100%) Change');
        }

        //Week 0 Greater Than Inventory
        if(objForecast.Forecast_Week_Indicator__c == 0 && objInventory != null && objForecast.Wholesaler_Forecast__c != null 
           && objInventory.Stock_Qty_1__c < objForecast.Wholesaler_Forecast__c){
            lstDeferralRules.add('Week 0 Greater Than Inventory');
            System.debug(LoggingLevel.Error, 'Week 0 Greater Than Inventory');
        }

        //Week 0 Less than Actual Sales
        if(objForecast.Forecast_Week_Indicator__c == 0 && objForecast.Wholesaler_Forecast__c != null 
           && objForecast.Wholesaler_Forecast__c < objForecast.Operational_Forecast__c){
            lstDeferralRules.add('Week 0 Less than Actual Sales');   
            System.debug(LoggingLevel.Error, 'Week 0 Less than Actual Sales');
        }

        if(lstDeferralRules != null && lstDeferralRules.size() > 0)
            objForecast.Deferral_Reason__c = JSON.serialize(lstDeferralRules);
    }

    public Inventory_Weekly__c getInventoryData(string pdcnNo, string wholesalerNo, date weekDate){
        Inventory_Weekly__c objInventory = new Inventory_Weekly__c();
        if(lstInventory != null){
            for(Inventory_Weekly__c obj : lstInventory){
                if(obj.Generic_PDCN__c == pdcnNo  && obj.Week_Date__c == weekDate)//&& obj.Wholesaler_Id__c == wholesalerNo
                    objInventory = obj;
            }
        }
        return objInventory;
    }    

    public boolean isSalesHistoryExists(string pdcnNo, decimal wholesalerNo){
        boolean isExists = false;
        if(lstSalesHistory != null){
            for(Sales_History__c objSales : lstSalesHistory){
                if(objSales.Generic_PDCN__c == pdcnNo && objSales.Wholesaler_Number__c == wholesalerNo){
                    isExists = true;
                }
            }
        }
        return isExists;
    }

    public decimal minSalesHistoryExists(string pdcnNo, decimal wholesalerNo){
        decimal minSales = 0;
        if(lstSalesHistory != null){
            for(Sales_History__c objSales : lstSalesHistory){
                if(objSales.Generic_PDCN__c == pdcnNo && objSales.Wholesaler_Number__c == wholesalerNo 
                   && minSales > objSales.Actual_Sales__c){
                       minSales = objSales.Actual_Sales__c;
                   }
            }
        }
        return minSales;
    }  

    public decimal maxSalesHistoryExists(string pdcnNo, decimal wholesalerNo){
        decimal maxSales = 0;
        if(lstSalesHistory != null){
            for(Sales_History__c objSales : lstSalesHistory){
                if(objSales.Generic_PDCN__c == pdcnNo && objSales.Wholesaler_Number__c == wholesalerNo 
                   && maxSales < objSales.Actual_Sales__c){
                       maxSales = objSales.Actual_Sales__c;
                   }
            }
        }
        return maxSales;
    }
}

Test Class :-

@IsTest
Public class OP_DeferralTriggerTest {
    @testSetup static void setup() {
        Forcast__c fct = new Forcast__c();
        fct.Generic_PDCN__c = '1235487';
        fct.Wholesaler_Number__c = 1234567 ;
        fct.Forecast_Week_StartDate__c = date.today();
        fct.Wholesaler_Forecast__c = 50;


       insert fct;
       system.debug('@@@@ForeCast@@@@'+fct);

        PDCN__c pdcninst = new PDCN__c();
        pdcninst.Brand_Standard_Name__c = 'abcdTest';
        pdcninst.Brand_Trademark_Name2__c = 'TestData';
        pdcninst.Generic_PDCN__c = fct.Generic_PDCN__c;
        pdcninst.T179_BRAND__c = 'stella';

        insert pdcninst;

        PDCN__c pdcninst2 = new PDCN__c();
        pdcninst2.Brand_Standard_Name__c = 'abcdest';
        pdcninst2.Brand_Trademark_Name2__c = 'TesData';
        pdcninst2.Generic_PDCN__c = '465465';
        pdcninst2.T179_BRAND__c = 'TestData1234';

        insert pdcninst2;

        Sales_History__c shis = new Sales_History__c();
        shis.Actual_Sales__c = 100;
        shis.Generic_PDCN__c = fct.Generic_PDCN__c;
        shis.Wholesaler_Number__c = fct.Wholesaler_Number__c ;

        insert shis;  

        Sales_History__c shis2 = new Sales_History__c();
        shis2.Actual_Sales__c = 150;
        shis2.Generic_PDCN__c = fct.Generic_PDCN__c;
        shis2.Wholesaler_Number__c = fct.Wholesaler_Number__c ;

        insert shis2; 

        Inventory_Weekly__c Invt = new Inventory_Weekly__c();
        Invt.Generic_PDCN__c = fct.Generic_PDCN__c;
        Invt.Wholesaler_Id__c = string.valueof(fct.Wholesaler_Number__c);
        Invt.Week_Date__c = date.today();
        Invt.Stock_Qty_1__c = 13245;

        insert Invt;

        Inventory_Weekly__c Invt1 = new Inventory_Weekly__c();
        Invt1.Generic_PDCN__c = fct.Generic_PDCN__c;
        Invt1.Wholesaler_Id__c = string.valueof(fct.Wholesaler_Number__c);
        Invt1.Week_Date__c = date.today().adddays(10);
        Invt1.Stock_Qty_1__c = 12345;

        insert Invt1;


    }

    public static testMethod void methodForSingleRecord(){

        List<Forcast__c> forect1 = [Select id,Generic_PDCN__c, Wholesaler_Number__c, Forecast_Week_StartDate__c from Forcast__c ];
        List<PDCN__c>   pdcnlst = [Select id,Brand_Standard_Name__c, Brand_Trademark_Name2__c, Generic_PDCN__c, T179_BRAND__c  from PDCN__c];
        List<Sales_History__c>   saleslist = [Select id,Generic_PDCN__c, Actual_Sales__c, Wholesaler_Number__c  from Sales_History__c];
        List<Inventory_Weekly__c>   invtLst = [Select id,Generic_PDCN__c, Wholesaler_Id__c, Week_Date__c, Stock_Qty_1__c  from Inventory_Weekly__c];

        /*Forcast__c fct = new Forcast__c();
        fct = [Select id,Generic_PDCN__c, Wholesaler_Number__c, Forecast_Week_StartDate__c from Forcast__c Where Wholesaler_Number__c = 1234567 ];
        fct.Wholesaler_Number__c = 1234567;
        fct.Name = 'testData';
        fct.Generic_PDCN__c = '1235997';
        fct.Wholesaler_Number__c = 1234567 ;
        fct.Forecast_Week_StartDate__c = date.today();*/
        Forcast__c fct = new Forcast__c();
        fct.Generic_PDCN__c = forect1[0].Generic_PDCN__c;
        fct.Wholesaler_Number__c = 1235467 ;
        fct.Forecast_Week_StartDate__c = date.today();
        fct.Wholesaler_Forecast__c = 50;

        test.startTest();
        update fct ;
        test.stopTest();
    }
} 
  • 6
    On which line is this error thrown? – David Reed Aug 10 '18 at 18:54
  • 2
    Please edit your post with any clarifications. Providing clarification is not what comments are for and is not an effective way to improve your question. – Adrian Larson Aug 10 '18 at 19:27
  • apologies @AdrianLarson I didn't knew If I could edit the post after publishing It. – Thomas Pete Aug 10 '18 at 19:30
7

NullPointerException is almost always something you can troubleshoot by tracing your own data. It's caused 99% of the time by a very simple error: you access a property of, or call a method on, an object that is null.

if(string.isNotEmpty(objPDCN.T179_BRAND__c) && objPDCN.T179_BRAND__c.toLowerCase().contains('stella') && objForecast.Wholesaler_Forecast__c != null && objForecast.Wholesaler_Forecast__c < 150)

This line attempts to guard against the NullPointerException wisely by checking the contents of objPDCN.T179_BRAND__c to see if that value is null before calling toLowerCase() on it.

But there's still two ways to throw this error: if objPDCN itself is null, or if objForecast is null, since you access a property of each without doing a check, you risk the NullPointerException.

So, like I said, you troubleshoot this error by tracing: where did this data get populated? How did a null slip in?

We can eliminate objForecast as a candidate, because it's the loop variable for a loop over Trigger.new. The system will not provide a null value in that context variable.

Suspect #2, objPDCN, is populated here:

    PDCN__c objPDCN = mapPDCN.get(objForecast.Generic_PDCN__c);        

This suggests that the probable cause is that your have a value of objForecast.Generic_PDCN__c which doesn't have a corresponding PDCN__c.

So trace it back another step: where's the Map come from?

//Get PDCN Data
for(PDCN__c objPDCN : [SELECT Id, Brand_Standard_Name__c, Brand_Trademark_Name2__c, Generic_PDCN__c, T179_BRAND__c,
                       Brand_Trademark_Name__c FROM PDCN__c WHERE Generic_PDCN__c IN :setGenericPDCNNo]){
                           mapPDCN.put(objPDCN.Generic_PDCN__c, objPDCN);
                       }

It's populated based on a query, and we query objects matching setGenericPDCNNo. Where's that Set come from?

for(Forcast__c objForecast : trigger.new){
    setGenericPDCNNo.add(objForecast.Generic_PDCN__c);
}

It's populated (correctly) from the incoming Forcast__c objects.

So what's the problem? Your code properly accumulates a Set of desired values and queries for them the right way, using bulkified SOQL. What you don't do is check to ensure that each Forcast__c's Generic_PDCN__c actually corresponds to an extant PDCN__c.

Hence, you get back a null value from mapPDCN.get(), and you then dereference that value, getting you a NullPointerException.

Your test class needs to ensure that this mapping is present and correct in your test data. You should only see this error if you uncomment out the commented lines in your test class, where you change the Generic_PDCN__c to a value that doesn't have a corresponding PDCN__c record from your test setup method.

As currently written, the test class will not execute the trigger at all because you're attempting to update a record without an Id:

    Forcast__c fct = new Forcast__c();
    fct.Generic_PDCN__c = forect1[0].Generic_PDCN__c;
    // snipped...

    update fct;

You cannot perform an update DML operation on a record that has no value in its Id field. You'll get an exception thrown at that line. Your previous version did execute the trigger because it queried an existing object (which brings in the Id), modified it, and then performed an update.

In addition to fixing your test class, your code should use a check to determine if this is the situation and handle it appropriately, since it's clearly possible to produce this with real data. You should then write another test case to duplicate this situation and make assertions to validate that your trigger handles it correctly.

  • For future Reference How did you broke the trigger and test code into separate blocks? – Thomas Pete Aug 10 '18 at 21:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.