0

I want to update the opportunity product servicedate , while updating the list it shows error

the error is

Production_date: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 0065Y00001WEm61QAD; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Production_date: maximum trigger depth exceeded Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate Opportunity trigger event AfterUpdate: [] Trigger.Production_date: line 61, column 1

trigger Production_date on Opportunity (after Insert,after Update) 
{
    Set<Id> pbeIds = new Set<Id>();
    
        if(trigger.isInsert )
        {
            for(Opportunity opli : Trigger.new) 
            {
                pbeIds.add(opli.Id);
            }
        }
        if(trigger.isUpdate)
        {
            for (Opportunity opli1 : Trigger.old) 
            {
                if(opli1.Id != null )
                {
                    pbeIds.add(opli1.Id);
         
                }
            }
        }
        List <Opportunity> opp = [SELECT id , Production_Date__c,
                                       (SELECT id, ServiceDate,Product2Id 
                                        FROM OpportunityLineItems)
                                        FROM Opportunity 
                                        WHERE id in :pbeIds];
       List<Product2> prd = [SELECT id
                             FROM Product2]; 
                                  
        for(Opportunity oppr: opp)
        {
            for(OpportunityLineItem o:oppr.OpportunityLineItems)
            {  
            for(Product2 p :prd)
            {
              if(p.id == o.Product2Id)
              {
                    Date oldOppr = Trigger.oldMap.get(oppr.Id).Production_Date__c;
                    system.debug('oldOppr===='+oldOppr);
                    Date newOppr = oppr.Production_Date__c;
                    system.debug('newOppr===='+newOppr);
                     
                    Integer noOfDays =  oldOppr.daysBetween(newOppr);
                    system.debug('noOfDays===='+noOfDays);
                 
                    system.debug('ServiceDate===='+o.ServiceDate);
    
                    date addedservicedate2 = o.ServiceDate+(noOfDays);
                    system.debug('addedservicedate2===='+addedservicedate2);
                    o.ServiceDate = addedservicedate2 ;
                    system.debug(' o.ServiceDate===='+ o.ServiceDate);
                }
             
              }
              
            }    
       }
        If(opp!=null && opp.size()>0)
        {
            update opp;
        }
}

1 Answer 1

2

Your update of Opportunity at the end of the trigger causes the Opportunity trigger to run again, resulting in a never ending loop.

But it looks like you are modifying OpportunityLineItem and so should be adding those to a list and updating that list. That change is likely to fix the problem.

In general, only doing an update when the data actually changes avoids these sort of cycles being created in the future when more triggers are added. So in this case:

OpportunityLineItem[] updates = new OpportunityLineItem[] {};
for (Opportunity oppr: opp)
{
    ...
        if (o.ServiceDate != addedservicedate2) {
            o.ServiceDate = addedservicedate2;
            updates.add(o);
        }
    ...
}
update updates;

Also note that this sort of query, with no limiting where clause, is dangerous as you could/will end up querying a huge number of rows wasting time and eventually hitting a governor limit:

List<Product2> prd = [SELECT id
                      FROM Product2]; 

Then looping to match inside another loop is an exponential performance problem too, normally addressed by using a Map. But from what I can see, the Product2 query isn't needed and this:

        for(Product2 p :prd)
        {
          if(p.id == o.Product2Id)
          {

can be replaced with:

        if (o.Product2Id != null)
        {
2
  • thanks Keith C , It worked Mar 23, 2021 at 10:44
  • Hi @chittukala that's great.
    – Keith C
    Mar 23, 2021 at 10:57

You must log in to answer this question.

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