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
SFDC-SDSFDC-SD 

Help me write a better code for the below OpportunityLineItem Update

Below oli trigger works fine but I am not comfortable having Opportunity query in a for loop. Any suggestions to write this code in a better way is much appreciated. 

 

trigger StatusChange on OpportunityLineItem (after update) {

List <Shipping_Status__c> new_status = new List<Shipping_Status__c>();

for(OpportunityLineItem oli : trigger.new)
{
Opportunity opp = [SELECT StageName FROM Opportunity WHERE Id = :oli.OpportunityId];
if (opp.StageName=='Win')
{
if (trigger.isUpdate)
{
if((oli.Stage__c <> trigger.oldMap.get(oli.Id).Stage__c))
{
Shipping_Status__c priorSS = [SELECT SS_New_Stage__c, CreatedDate FROM Shipping_Status__c WHERE SS_Line_Item_Id__c = :oli.id ORDER BY CreatedDate DESC LIMIT 1];
Shipping_Status__c s = new Shipping_Status__c();
s.SS_Line_Item_Id__c = oli.id;
s.SS_Opportunity__c = oli.OpportunityId;
s.SS_Product_Name__c = oli.Product_Short_Name__c;
s.SS_Prior_Stage__c = priorSS.SS_New_Stage__c;
s.SS_New_Stage__c = oli.Stage__c;
s.SS_Previous_Stage_Date__c = priorSS.CreatedDate;
new_status.add(s);
}
}
}

}
Insert new_status;
}

Leon MorockiLeon Morocki

You can use something like:

 

trigger StatusChange on OpportunityLineItem (after update) {
    List <Shipping_Status__c> new_status = new List<Shipping_Status__c>();

    // get all line item IDs
    Set<Id> opportunityIds = new Set<Id>();
    for (OpportunityLineItem oli : trigger.new)
        opportunityIds.add(oli.OpportunityId);

    // get all related opportunities with latest shipping status
    Map<Id, Opportunity> opportunities = new Map<Id, Opportunity>([SELECT StageName, (SELECT SS_New_Stage__c, CreatedDate FROM SS_Line_Item_Id__r ORDER BY CreatedDate DESC LIMIT 1) FROM Opportunity WHERE Id in :opportunityIds]);

    Map<Id, Shipping_Status__c> shippingStatuses = new Map<Id, Shipping_Status__c>([]);

    for (OpportunityLineItem oli : trigger.new) {
        if (opportunities.get(oli.OpportunityId).Status == 'Won' && Trigger.isUpdate && oli.Stage__c <> trigger.oldMap.get(oli.Id).Stage__c) {
            Shipping_Status__c s = new Shipping_Status__c();

            // fill the record fields, using the opportunities map with child shipping status object

            new_status.add(s);
        }
    }

    insert new_status;
}

 I'm assuming that child relationship name is SS_Line_Item_Id__r, but it may be different in your case.

 

SFDC-SDSFDC-SD

    Map<Id, Shipping_Status__c> shippingStatuses = new Map<Id, Shipping_Status__c>([SELECT  SS_New_Stage__c, CreatedDate FROM Shipping_Status__c WHERE SS_Line_Item_Id__c = : oli.Id ORDER BY CreatedDate DESC LIMIT 1]);

 

Shipping_Status__c object has a column  has a custom field SS_Line_Item_Id__c which I need to check against opportunitylineitem Id.