function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Heather_HansonHeather_Hanson 

Trigger - Auto-Add Opportunity Products based on value of initial product selected

My case is:
When a user selects a product, I want my trigger to look at the add_for__c value on that product and if it equals 0 then it should look for all products where the add_for__c field value is equal to the lsrv_pk__c value of the initial product selected.

I'm still very new to writing triggers and only just starting the databese and SQL portion of my education, but need this trigger for work ASAP so any help would be appreciated!

I found some sample code through my research on this need and have attempted to re-work it to my need and managed to get the trigger to save, but when I test it, I'm getting this error: 

Product_Auto_Add: execution of BeforeInsert
caused by: System.NullPointerException: Attempt to de-reference a null object
Trigger.Product_Auto_Add: line 40, column 1


I'm looking for help resolving this issue and also to ensure I've created my trigger to execute what I need it to.  I have no loops in there...do I need a loop to ensure it gets ALL products that have the matching value I mentioned above?

Here's the trigger:
 
trigger Product_Auto_Add on OpportunityLineItem (before insert) {
    
    List<OpportunityLineItem> oliList = new List<OpportunityLineItem>(); 
    
    List<String> lstProduct = new List<String>();
    
    for(OpportunityLineItem optLineItem: Trigger.new)
    {
        if(optLineItem.add_for__c == '0')
        {
            lstProduct.add(optLineItem.add_for__c);
        }
    }
    
    //retrieve values of Product Selected
    List<OpportunityLineItem> lstOpptyLineItems = [SELECT OpportunityId, Name, PricebookEntryId, Quantity, add_for__c, lsrv_pk__c, UnitPrice
                                                   FROM    OpportunityLineItem
                                                   WHERE   Id = :Trigger.new 
                                                   AND add_for__c IN:lstProduct];
    
    //create a map which contains Product Name and OpportunityLineItem
    Map<String, OpportunityLineItem> mapOpptyLineItem = new Map<String, OpportunityLineItem>();
    for(OpportunityLineItem item:lstOpptyLineItems)
    {
        mapOpptyLineItem.put(item.lsrv_pk__c, item);
    }
    
    //retrieve PriceBookEntry of the Product B, this is most important
    PricebookEntry pbeProduct2 = [SELECT Id, Pricebook2Id, UnitPrice, Name, add_for__c
                                  FROM PricebookEntry 
                                  WHERE Pricebook2Id IN 
                                  (SELECT Id FROM PriceBook2 
                                   WHERE Name = 'Selectcom Telecom Pricing') 
                                  LIMIT 1];
    
    
    //retrieve Product A item from the map.         
    OpportunityLineItem itemProductA = mapOpptyLineItem.get('Product A');
    
    if(itemProductA.lsrv_pk__c == pbeProduct2.add_for__c){
        
        
        oliList.add(new OpportunityLineItem(
            OpportunityId = itemProductA.OpportunityId, 
            PricebookEntryId = pbeProduct2.Id,
        	Quantity = itemProductA.Quantity,
        	UnitPrice = pbeProduct2.UnitPrice)
                   );
        
        insert oliList;
    }
}

FYI Line 40 is:
if(itemProductA.lsrv_pk__c == pbeProduct2.add_for__c){

Thank you!
AnudeepAnudeep (Salesforce Developers) 
Whether or not itemProductA and pbeProduct2 has results, you are missing a null/size check before using them

Please see the example in the documentation
PricebookEntry pbeProduct2 = [SELECT Id, Pricebook2Id, UnitPrice, Name, add_for__c
                                  FROM PricebookEntry 
                                  WHERE Pricebook2Id IN 
                                  (SELECT Id FROM PriceBook2 
                                   WHERE Name = 'Selectcom Telecom Pricing') 
                                  LIMIT 1];
    
    
    //retrieve Product A item from the map.         
    OpportunityLineItem itemProductA = mapOpptyLineItem.get('Product A');


if (itemProductA != null && pbeProduct2.size()>0)  {
//execute code here
}
Heather_HansonHeather_Hanson
Thanks for responding!

So I did the following but I'm getting Method does not exist or incorrect signature: void size() from the type PricebookEntry for the null/size check line.  Is my syntax wrong?
 
OpportunityLineItem itemProductA = mapOpptyLineItem.get('Product A');
    
    if (itemProductA != null && pbeProduct2.size()>0)  
    
    
    if(itemProductA.lsrv_pk__c == pbeProduct2.add_for__c){
        
        
        oliList.add(new OpportunityLineItem(
            OpportunityId = itemProductA.OpportunityId, 
            PricebookEntryId = pbeProduct2.Id,
        	Quantity = itemProductA.Quantity,
        	UnitPrice = pbeProduct2.UnitPrice)
                   );
        
        insert oliList;
    }

 
AnudeepAnudeep (Salesforce Developers) 
Because it is not a list, it should be 

if (itemProductA != null && pbeProduct2!=null)

Size checks can be done on lists
Heather_HansonHeather_Hanson
Right!  That makes sense!

OK so I was able to save the trigger and did a test, but it didn't work as needed.  I selected a product that I know should have had 4 other products added automatically but that didn't happen. 

What I need the trigger to do is look at the "lsrv_pk__c" of the product selected and compare to the "add_for__c" of all the pbeProduct2 and if there is a match insert those products.

I have the If statement for that at the bottom, but I'm wondering if further up I'm not retrieveing and storing the values properly?