+ Start a Discussion
John AthitakisJohn Athitakis 

Prevent Trigger from Firing due to rollups updating

Situation: I have batch apex running every night at 1 am on Opportunity Lin Items.

I also have @ future code on my opportunity. It seems once I introduced the later, that my batches are failing because at my Opportunity level, I have roll ups which the batch is causing to save, leading to a the Batch failing due to the @future.

I believe an easy solution to this is convert my code to queueable--and while I recently learned about that, the code is pretty lengthy and I don't know a good way of doing that conversion (if thats the only answer, so be it).
 

However, is there a way I could tell my trigger instigating the @future method to not fire due to a save occuring from rollups without necessarily naming each rollup? Currently my call looks like this:

trigger OpportunityReferenceUpdate on Opportunity (after insert, after update) {

       
 if( !System.isFuture() ) {    
    OpportunityReferenceUpdateClass.processOpportunityReferences(Trigger.newMap.keySet());
}
   
}

Sadly, my 'isFuture' flag does not seem to be catching the edge case from the Batch update. 

I can imagine something like this as a temporary fix. 

trigger OpportunityReferenceUpdate on Opportunity (after insert, after update) {
//Used to update text fields within the Opportunity to reduce the amount of references due to SFDC Limits
//Author: John Athitakis
//Relates to BIZOPS-4428
//
 // create a set of all the unique ownerIds
 // 
 // 
 boolean Change=False;
 
   for (Opportunity sa : Trigger.new){
     if(Trigger.IsUpdate){
       Opportunity saOld = Trigger.oldMap.get(sa.Id);
        
      if( (sa.Rollup1 == saOld.rollup1) && (sa.Rollup2==sa.Rollup2) ){
    Change=True;
      }
     }
   }
    
    
    
 if( !System.isFuture() && nodechange== False) {    
    OpportunityReferenceUpdateClass.processOpportunityReferences(Trigger.newMap.keySet());
}
 

Is there a better way?

Best Answer chosen by John Athitakis
Mahesh DMahesh D
Hi John,

Please check the below code:
 
if (system.isBatch() || system.isFuture())
            {  
                CaseHandler.syncUpdateCaseStatus(caseIdSet, woCaseMapForClose, woCaseMapForNew, Trigger.isInsert);   
            }
            else
            {
                CaseHandler.updateCaseStatus(caseIdSet, woCaseMapForClose, woCaseMapForNew, Trigger.isInsert);   
            }

In the above example if the call is from Batch or any other Future then it will call the Sync method else it will call the future method.

In the similar way you can change your method and conditions.

Know more about isBatch:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_system.htm#apex_System_System_isBatch

Please do let me know if it helps you.

Regards,
Mahesh

All Answers

John AthitakisJohn Athitakis
note--that inner if is obviously wrong. Should be != and ||'s instead of == and &&'s
John AthitakisJohn Athitakis
Alright testing this is sandbox seemed to have failed. Is the only solution to move to queueable? 
Mahesh DMahesh D
Hi John,

Please check the below code:
 
if (system.isBatch() || system.isFuture())
            {  
                CaseHandler.syncUpdateCaseStatus(caseIdSet, woCaseMapForClose, woCaseMapForNew, Trigger.isInsert);   
            }
            else
            {
                CaseHandler.updateCaseStatus(caseIdSet, woCaseMapForClose, woCaseMapForNew, Trigger.isInsert);   
            }

In the above example if the call is from Batch or any other Future then it will call the Sync method else it will call the future method.

In the similar way you can change your method and conditions.

Know more about isBatch:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_system.htm#apex_System_System_isBatch

Please do let me know if it helps you.

Regards,
Mahesh
This was selected as the best answer
John AthitakisJohn Athitakis
Thank you!