0

I'm getting Null Pointer Exception from some recent code changes and I can't figure out where it's coming from.

I've put ** around the new code. Any help would be appreciated!

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, OrderItem_Trigger: execution of AfterInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Class.OrderItem_TriggerHandler.updateStartDate: line 80, column 1 Trigger.OrderItem_Trigger: line 14, column 1: []

Trigger code:

trigger OrderItem_Trigger on OrderItem (after insert, after update) {
List<Id> newOrderItemIds = new List<Id>();
List<OrderItem> updateItemStartDate = new List<OrderItem>();
Set<Product2> orderedProducts = new Set<Product2>();
if(trigger.isAfter && trigger.isInsert){
    for(OrderItem o : trigger.new){
        newOrderItemIds.add(o.Id);
        if(o.ServiceStartDate__c == null){
            updateItemStartDate.add(o);
            orderedProducts.add(o.Product2);
        }
    }
    **if(!updateItemStartDate.isEmpty() && !orderedProducts.isEmpty()){
        OrderItem_TriggerHandler.updateStartDate(updateItemStartDate, orderedProducts);
    }**
    if(!newOrderItemIds.isEmpty()){
        OrderItem_TriggerHandler.updateOpportunity(neworderItemIds);
    }
    if(!updateItemStartDate.isEmpty()){

    }
}

List<Id> updateUnitPriceList = new List<Id>();
if(trigger.isAfter && trigger.isUpdate){
    for(OrderItem o : trigger.new){
        OrderItem oldO = Trigger.oldMap.get(o.Id);
        if(o.SBQQ__QuotedListPrice__c != oldO.SBQQ__QuotedListPrice__c){
            updateUnitPriceList.add(o.Id);
        }
    }
    if(!updateUnitPriceList.isEmpty()){
        OrderItem_TriggerHandler.updateUnitPrice(updateUnitPriceList);
    }
}
}

Class:

public with sharing class OrderItem_TriggerHandler {
@future
public static void updateOpportunity(List<Id> orderItemIds){
    List<OrderItem> orderItems = [SELECT Id,SBQQ__QuoteLine__c 
                                    FROM OrderItem 
                                    WHERE Id IN: orderItemIds];
    Map<Id,Id> quoteLineOrderItemMap = new Map<Id,Id>();
    List<Id> quoteLineIds = new List<Id>();

    if(!orderItems.isEmpty()){
        
        for(OrderItem o : orderItems){
            quoteLineOrderItemMap.put(o.SBQQ__QuoteLine__c, o.Id);
            quoteLineIds.add(o.SBQQ__QuoteLine__c);
        }
    }

    List<OpportunityLineItem> oppLineItems = [SELECT Id,SBQQ__QuoteLine__c,OpportunityId 
                                                FROM OpportunityLineItem 
                                                WHERE SBQQ__QuoteLine__c IN :quoteLineIds];
    
    Set<Id> oppIds = new Set<Id>();

    if(!oppLineItems.isEmpty()){ 
        List<OpportunityLineItem> oppLinesToUpdate = new List<OpportunityLineItem>();   
        for(OpportunityLineItem opp : oppLineItems){
            opp.Order_Line_Item__c = quoteLineOrderItemMap.get(opp.SBQQ__QuoteLine__c);
            oppLinesToUpdate.add(opp);
            oppIds.add(opp.OpportunityId);
        }
        if(!oppLinesToUpdate.isEmpty()){
            Database.update(oppLinesToUpdate, False);
        }
    }

    List<SBQQ__QuoteLine__c> quoteLines = [SELECT Id,Ordered__c 
                                            FROM SBQQ__QuoteLine__c
                                            WHERE Ordered__c = False AND Id IN :quoteLineIds];
    
    if(!quoteLines.isEmpty()){
        List<SBQQ__QuoteLine__c> quoteLinesToUpdate = new List<SBQQ__QuoteLine__c>();
        for(SBQQ__QuoteLine__c q : quoteLines){
            q.Ordered__c = True;
            quoteLinesToUpdate.add(q);
        }
        if(!quoteLinesToUpdate.isEmpty()){
            Database.update(quoteLinesToUpdate, False);
        }
    }

    /*if(!oppIds.isEmpty()){
        List<Opportunity> wonOpps = [SELECT Id,StageName FROM Opportunity WHERE Id IN :oppIds AND StageName != 'Closed Won'];
        for(Opportunity o : wonOpps){
            o.StageName = 'Closed Won';
        }
    }*/

}

public static void updateUnitPrice(List<Id> updateUnitPriceList){
    List<OrderItem> orderItemsToUpdate = [SELECT Id,UnitPrice,Additional_Disc__c,SBQQ__QuotedListPrice__c 
                                            FROM OrderItem 
                                            WHERE Id IN :updateUnitPriceList];
    for(OrderItem o : orderItemsToUpdate){
        if(o.Additional_Disc__c > 0){
            o.UnitPriceForceOverride__c = (1-o.Additional_Disc__c) * o.SBQQ__QuotedListPrice__c;
        } else {
            o.UnitPriceForceOverride__c = o.SBQQ__QuotedListPrice__c;
        }
        o.UnitPrice = o.UnitPriceForceOverride__c;
    }
    Database.update(orderItemsToUpdate, False);
}

**public static void updateStartDate(List<OrderItem> itemsMissingStartDate,Set<Product2> orderedItems){
    map<Id,Decimal> itemsWithLeadTime = new map<Id,Decimal>();
    List<OrderItem> orderItemsToUpdateDate = new List<OrderItem>();
    if (!orderedItems.isEmpty() && !itemsMissingStartDate.isEmpty()) {
        for(Product2 p : orderedItems){
            Decimal leadTime;
            if(p.Lead_Time__c == null){
                leadTime = 0;
            } else {
                leadTime = p.Lead_Time__c;
            }
            itemsWithLeadTime.put(p.Id, leadTime);
        }
        for (orderItem o : itemsMissingStartDate) {
            Integer leadTimeDays = itemsWithLeadTime.get(o.Product2Id).intValue();
            
            o.ServiceStartDate__c = Date.today().addDays(leadTimeDays);
            orderItemsToUpdateDate.add(o);
        }
    }
    if(!orderItemsToUpdateDate.isEmpty()){
        Database.update(orderItemsToUpdateDate,False);
    }
}**
}

Test Class

@isTest
public with sharing class OrderTriggerHandler_Test {  
private static ID StandardAccountRecordID = [SELECT ID FROM RecordType WHERE SobjectType = 
'Account' AND Name = 'Standard Account' LIMIT 1].Id;

@isTest
private static void testOrderUpdate() {
    ERP_Company__c testERPCompany = new ERP_Company__c(Name='US-AX-01');
    testERPCompany = (ERP_Company__c)TestFactory.createSObject(testERPCompany);
    insert testERPCompany;

    Approval_Routing__c testEntity = new Approval_Routing__c(
        Name = '660',
        Management_Entity_Id__c = '660',
        Management_Entity_Name__c = 'Test Management Entity'
    );
    insert testEntity;

    List<Account> accountsToInsert = new List<Account>();
    Account testAccount = new Account(recordTypeId = StandardAccountRecordID);
    testAccount = (Account)TestFactory.createSObject(testAccount);
    testAccount.Name = 'Test';
    accountsToInsert.add(testAccount);
    insert accountsToInsert;

    
    Id testPricebookId = Test.getStandardPricebookId();
    

    Product_Hierarchy__c testHierarchy = new Product_Hierarchy__c(
        Product_Code__c = '480',
        Product_Description__c = 'PS STOPPLE Fittings',
        Family_Code__c = '1200',
        Family_Description__c = 'ISOLATION FITTINGS PROSERIES LOR',
        Sub_SBU_Code__c = '110',
        Sub_SBU_Description__c = 'HT&P Consumables - HP',
        SBU_Code__c = '00',
        SBU_Description__c = 'HT&P PRODUCTS'
    );
    insert testHierarchy;
    
    List<Product2> productsToInsert = new List<Product2>();
    Product2 testProd = new Product2(
        Global_List_Price__c = 100,
        Name = 'Test Product',
        Product_Code__c = '480',
        Part_Number__c = '0001',
        Product_Hierarchy__c = testHierarchy.Id,
        **Lead_Time__c = 5**
    );
    testProd = (Product2)TestFactory.createSObject(testProd);
    productsToInsert.add(testProd);
    insert productsToInsert;
    /*Id testProdId = testProd.Id;
    List<PricebookEntry> standardEntryList = [SELECT Id FROM PricebookEntry 
                                                WHERE Product2Id = :testProdId 
                                                AND Pricebook2Id = :testPricebook.Id 
                                                AND CurrencyIsoCode = 'USD' LIMIT 1];
    PricebookEntry standardEntry = standardEntryList[0];*/
    List<PricebookEntry> pricebookEntriesToInsert = new List<PricebookEntry>();
    PricebookEntry standardEntry = new PricebookEntry(
        Pricebook2ID = testPricebookId,
        Product2ID = testProd.ID,
        UnitPrice = 100,
        IsActive = True
    );
    standardEntry = (PricebookEntry)TestFactory.createSObject(standardEntry);
    pricebookEntriesToInsert.add(standardEntry);
    insert pricebookEntriesToInsert;
    PricebookEntry pbe = [Select Id from PricebookEntry LIMIT 1];
    
    
    List<Opportunity> oppsToInsert = new List<Opportunity>();
    Opportunity testOpp = new Opportunity(
        AccountId = testAccount.Id,
        ERP_Company__c = testERPCompany.Id,
        Management_Entity__c = testEntity.Id,
        Customer_Needed_Date__c = Date.today(),
        Pricebook2Id = testPricebookId
    );
    testOpp = (Opportunity)TestFactory.createSObject(testOpp);
    oppsToInsert.add(testOpp);
    insert oppsToInsert;

    List<OpportunityLineItem> oppItemsToInsert = new List<OpportunityLineItem>();
    OpportunityLineItem testItem = new OpportunityLineItem(
        OpportunityId = testOpp.ID,
        PricebookEntryID = pbe.ID,
        UnitPrice = 100,
        Quantity = 1
    );
    testItem = (OpportunityLineItem)TestFactory.createSObject(testItem);
    oppItemsToInsert.add(testItem);
    insert oppItemsToInsert;

    List<ERP_Account__c> erpAccountsToInsert = new List<ERP_Account__c>();
    ERP_Account__c testERPAccount = new ERP_Account__c(
        Account__c = testAccount.Id,
        ERP_Company__c = testERPCompany.Id,
        Management_Entity__c = testEntity.Id,
        Payment_Terms__c = 'Net 30',
        Total_Credit__c = 100,
        Available_Credit__c = 0
    );
    testERPAccount = (ERP_Account__c)TestFactory.createSObject(testERPAccount);
    erpAccountsToInsert.add(testERPAccount);
    insert erpAccountsToInsert;

    /*List<SBQQ__Quote__c> quotesToInsert = new List<SBQQ__Quote__c>();
    SBQQ__Quote__c testQuote = new SBQQ__Quote__c(
        SBQQ__Account__c = testAccount.Id,
        ERP_Company__c = testERPCompany.Id,
        Management_Entity__c = testEntity.Id,
        SBQQ__Opportunity2__c = testOpp.Id,
        SBQQ__Primary__c = TRUE,
        Country_of_Destination__c = 'United States',
        SBQQ__PriceBook__c = testPricebook.Id,
        ERP_Account__c = testERPAccount.Id
    );
    testQuote = (SBQQ__Quote__c)TestFactory.createSObject(testQuote);
    quotesToInsert.add(testQuote);
    insert quotesToInsert;

    SBQQ__QuoteLine__c testQuoteLine = new SBQQ__QuoteLine__c(
        SBQQ__Quote__c = testQuote.Id,
        SBQQ__Product__c = testProd.Id,
        SBQQ__PricebookEntryId__c = standardEntry.Id,
        SBQQ__Quantity__c = 1
    );
    insert testQuoteLine;*/
    
    Order testOrder = new Order(
        AccountId = testAccount.Id,
        ERP_Account__c = testERPAccount.Id,
        //SBQQ__Quote__c = testQuote.Id,
        Opportunity = testOpp,
        PoNumber='Test',
        Description__c ='Test',
        Status='Draft',
        EffectiveDate = date.today(), 
        Management_Entity__c = testEntity.Id, 
        Bill_To_Name__c = 'Test', 
        Market_Sector__c = 'Mixed', 
        Ship_To_Name__c = 'Test',
        BillingStreet = '123 Test',
        BillingCity = 'New York',
        BillingState = 'New York',
        BillingPostalCode ='10003',
        BillingCountry = 'United States',
        ShippingStreet = '123 Test',
        ShippingCity = 'New York',
        ShippingState = 'New York',
        ShippingPostalCode ='10003',
        ShippingCountry = 'United States',
        Description = 'Test',
        Type = 'Order',
        Start_Date__c = date.today(),
        Pricebook2Id = testPricebookId
    );
    insert testOrder;

    List<OrderItem> orderItemsToInsert = new List<OrderItem>();
    OrderItem testOrderLine = new OrderItem(
        //SBQQ__QuoteLine__c = testQuoteLine.Id,
        OrderId = testOrder.Id,
        Product2 = testProd,
        PricebookEntryId = pbe.Id,
        Quantity = 1,
        UnitPrice = 100,
        ServiceStartDate__c = date.today()
    );
    orderItemsToInsert.add(testOrderLine);
    **OrderItem testOrderLine2 = new OrderItem(
        //SBQQ__QuoteLine__c = testQuoteLine.Id,
        OrderId = testOrder.Id,
        Product2 = testProd,
        PricebookEntryId = pbe.Id,
        Quantity = 1,
        UnitPrice = 100
    );
    orderItemsToInsert.add(testOrderLine2);**
    insert orderItemsToInsert;

    test.startTest();
    testOrder.Ship_To_Name__c = 'Test update';
    testOrder.ShippingCountry = 'United States';
    update testOrder;

    testOrder.ShippingStreet = '124 Test';
    update testOrder;

    testOrder.ShippingCity = 'Hudson';
    update testOrder;

    testOrder.ShippingState = 'New Jersey';
    update testOrder;

    testOrder.ShippingPostalCode ='12345';
    update testOrder;
    
    testOrderLine.Status__c = 'Error';
    testOrderLine.Error_Message__c = 'Test Error Message';
    update testOrderLine;
    
    testOrder.Status = 'Error';
    update testOrder;

    test.stopTest();

    List<OrderItem> orderLine = [SELECT Ship_To_Name__c FROM OrderItem LIMIT 1];

    system.assertEquals('Test update', orderLine[0].Ship_to_Name__c);

}
}
2
  • Can you point exactly which line is throwing the error, its written line 80 but because of commented blocks not able to check which exact line. Commented Jul 20, 2021 at 5:03
  • @NagendraSingh if(p.Lead_Time__c == null){ is line 80 Commented Jul 20, 2021 at 9:20

2 Answers 2

1

Seems your problem is here:

for (orderItem o : itemsMissingStartDate) {
    Integer leadTimeDays = itemsWithLeadTime.get(o.Product2Id).intValue();
    // map may not contain key
}

Your itemsWithLeadTime.get(o.Product2Id) call can certainly return null. You can drop the .intValue() call as it serves no purpose here, but then you just move the NPE down one line.

You need to decide what to do when you do not have a lead time for given Product2Id. Either you don't touch the ServiceStartDate__c, set it to today, or clear it out. The fix will vary depending on which you choose, but if for example you choose the last, you would do:

for (orderItem o : itemsMissingStartDate) {
    Decimal leadTime = itemsWithLeadTime.get(o.Product2Id);
    if (leadTime == null) leadTime = 0;
    o.ServiceDate__c = Date.today().addDays(leadTime);
}
1
  • I updated the code (see above), but am still getting the same exception Commented Jul 20, 2021 at 2:31
0

Based on the line number you have mentioned.

There might be a null getting entered here orderedProducts.add(o.Product2);

So after this line you can write orderedProducts.remove(null);, so that it does not contain any null values.

So your code will look like this:

for(OrderItem o : trigger.new){
    newOrderItemIds.add(o.Id);
    if(o.ServiceStartDate__c == null){
        updateItemStartDate.add(o);
        orderedProducts.add(o.Product2);
    }
}
orderedProducts.remove(null);

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .