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
Muthu SamyMuthu Samy 

Need help with case trigger

Hey guys,

I got requirement to have automation on case object. This particular requirement is just update all child cases status to same as parent case when it is updated.

I tried with process builder but it cannot handle if case has 500+ childs. So I'm trying with trigger.

trigger caseStatusSync on Case (before update) {

Set<Id> casesToProcess = new Set<Id>();

for(case c : Trigger.new){
    if( 
         (Trigger.newmap.get(c.id).status != Trigger.oldmap.get(c.id).status) 
       &&(
            trigger.newmap.get(c.id).status.containsIgnoreCase('Escalated')
         || trigger.newmap.get(c.id).status.containsIgnoreCase('Resolved')
         )
       )
    {
        casesToProcess.add(c.id);
    }
}

list<case> childcases = [select id,status,parentid from case where parentid in :casesToProcess ];
list<case> childCasesToUpdate = new list<case>();
    for(case cs:trigger.new){
    for(case c:childcases){
        c.status= trigger.newmap.get(cs.id).status;
        childCasesToUpdate.add(c);
    }
    }
    update childCasesToUpdate;
}

I think nested for loops are not recommended, so the problem here is, how to get rid of nested for loops ?  

Any other advice/change to the above code will be greatly helpful for me thanks.
Best Answer chosen by Muthu Samy
thatheraherethatherahere
Hi Muthu,

You can use map collection here to avoid nested loops. Learn about it here (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_collections_maps.htm" target="_blank).
 
trigger caseStatusSync on Case (before update) {

    Map<Id, Case> mapCaseToProcess = new Map<Id, Case>();

    for(case c : Trigger.new){
        
        if( (c.status != Trigger.oldmap.get(c.id).status) 
           &&( c.status.containsIgnoreCase('Escalated') || c.status.containsIgnoreCase('Resolved') )
        ){
            mapCaseToProcess.put( c.id, c );
        }
    }

    if( !mapCaseToProcess.values().isEmpty() ){
        list<case> childCasesToUpdate = new list<case>();
        for(case c: [select id,status,parentid from case where parentid in :mapCaseToProcess.keySet() ] ){
            c.status= mapCaseToProcess.get( cs.parentid ).status;
            childCasesToUpdate.add(c);
        }
        if( !childCasesToUpdate.isEmpty() )
            update childCasesToUpdate;
    }
}

Let me know if you face any issue with this. 


- thatherahere
 

All Answers

thatheraherethatherahere
Hi Muthu,

You can use map collection here to avoid nested loops. Learn about it here (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_collections_maps.htm" target="_blank).
 
trigger caseStatusSync on Case (before update) {

    Map<Id, Case> mapCaseToProcess = new Map<Id, Case>();

    for(case c : Trigger.new){
        
        if( (c.status != Trigger.oldmap.get(c.id).status) 
           &&( c.status.containsIgnoreCase('Escalated') || c.status.containsIgnoreCase('Resolved') )
        ){
            mapCaseToProcess.put( c.id, c );
        }
    }

    if( !mapCaseToProcess.values().isEmpty() ){
        list<case> childCasesToUpdate = new list<case>();
        for(case c: [select id,status,parentid from case where parentid in :mapCaseToProcess.keySet() ] ){
            c.status= mapCaseToProcess.get( cs.parentid ).status;
            childCasesToUpdate.add(c);
        }
        if( !childCasesToUpdate.isEmpty() )
            update childCasesToUpdate;
    }
}

Let me know if you face any issue with this. 


- thatherahere
 
This was selected as the best answer
Muthu SamyMuthu Samy
Hi thatherahere,

Thanks for the response, it works great. However, my concern is, updating 500+ records in synchronous mode!! Is it right way to do it ? 
Should I use 'For Update' lock if I handle it via trigger or @future method ?