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
Gary Singh (BlackBeltHelp)Gary Singh (BlackBeltHelp) 

Find opened and closed cases using map

I am new to apex and am trying to use Maps to figure out total Open and Closed cases for a Contact record. 

The following is not working, please suggest what is wrong. 
// Trigger should update contact with total tickets : closed and Opened

trigger Prac_caseUtil on Case (after insert, after delete, after update) {
map<id,List<case>> caseMap = new map<id,list<case>>();
    for(case caseObject : trigger.new){
        if(caseObject.accountid !=NULL && caseMap.get(caseObject.accountid)==NULL){
            caseMap.put(caseObject.accountid,new LIST<case>());            
            caseMap.get(caseObject.AccountId).add(caseObject); 
        }
    }
    // SOQL 
    LIST<contact> conListToUpdateOpen = [SELECT Id,Total_Open_Tickets__c,Total_Closed_Tickets__c,(SELECT ID FROM Cases WHERE IsClosed=FALSE) 
                                     FROM CONTACT 
                                     WHERE ID IN:caseMap.keySet()];
    
   LIST<contact> conListToUpdateClosed = [SELECT Id,Total_Open_Tickets__c,Total_Closed_Tickets__c,(SELECT ID FROM Cases WHERE IsClosed=TRUE) 
                                     FROM CONTACT 
                                     WHERE ID IN:caseMap.keySet()];
    
    for(contact c:conListToUpdateOpen){
        c.Total_Open_Tickets__c = caseMap.get(c.id).size();
        system.debug('###### open tickets' + caseMap.get(c.id).size());
    }

    for(contact c:conListToUpdateClosed){
        c.Total_Closed_Tickets__c = caseMap.get(c.id).size();
        system.debug('###### closed tickets' + caseMap.get(c.id).size());
    }
    update conListToUpdateOpen;
    update conListToUpdateClosed;
}

 
Best Answer chosen by Gary Singh (BlackBeltHelp)
Abdul KhatriAbdul Khatri
HI Gary,

I hope this code will help.

I made few changes to work in the followng scenarios

When New Case Inserted
When All the Cases Deleted
When Case Updated and only Status value change
 
trigger Prac_caseUtil on Case (after insert, after update, after delete) { 
    
    Set<Id> idContactSet = new Set<Id>();
	List<Case> newList = trigger.isDelete ? trigger.old : trigger.new;
    List<Contact> contactListToUpdate = new List<Contact>();
    
    for(case caseObject : newList){
        if((trigger.oldMap == null || trigger.new == null || (trigger.oldMap != null && caseObject.Status != trigger.oldMap.get(caseObject.Id).Status))
           	&& !String.isBlank(caseObject.ContactId))
			idContactSet.add(caseObject.ContactId);        
    }
    
    // SOQL 
    Map<Id, contact> conMapToUpdateOpen = new  Map<Id, contact>([SELECT Id,Total_Open_Tickets__c,Total_Closed_Tickets__c,(SELECT ID FROM Cases WHERE IsClosed=FALSE) 
                                     FROM CONTACT 
                                     WHERE ID IN:idContactSet]);
    
    Map<Id, contact> conMapToUpdateClosed = new Map<Id, contact>([SELECT Id,Total_Open_Tickets__c,Total_Closed_Tickets__c,(SELECT ID FROM Cases WHERE IsClosed=TRUE) 
                                     FROM CONTACT 
                                     WHERE ID IN:idContactSet]);
    

    for(Id id : idContactSet){
     
        Contact contactRec = new Contact(Id = id);
        contactRec.Total_Open_Tickets__c = 0;
        contactRec.Total_Closed_Tickets__c = 0;
        
        if(conMapToUpdateOpen.get(id).Cases != null && conMapToUpdateOpen.get(id).Cases.size() > 0)
            contactRec.Total_Open_Tickets__c = conMapToUpdateOpen.get(id).Cases.size();
        
        if(conMapToUpdateClosed.get(id).Cases != null && conMapToUpdateClosed.get(id).Cases.size() > 0)
            contactRec.Total_Closed_Tickets__c = conMapToUpdateClosed.get(id).Cases.size();
        
        contactListToUpdate.add(contactRec);
    }
    
    Database.update(contactListToUpdate);
}

 

All Answers

Abdul KhatriAbdul Khatri
HI Gary,

I hope this code will help.

I made few changes to work in the followng scenarios

When New Case Inserted
When All the Cases Deleted
When Case Updated and only Status value change
 
trigger Prac_caseUtil on Case (after insert, after update, after delete) { 
    
    Set<Id> idContactSet = new Set<Id>();
	List<Case> newList = trigger.isDelete ? trigger.old : trigger.new;
    List<Contact> contactListToUpdate = new List<Contact>();
    
    for(case caseObject : newList){
        if((trigger.oldMap == null || trigger.new == null || (trigger.oldMap != null && caseObject.Status != trigger.oldMap.get(caseObject.Id).Status))
           	&& !String.isBlank(caseObject.ContactId))
			idContactSet.add(caseObject.ContactId);        
    }
    
    // SOQL 
    Map<Id, contact> conMapToUpdateOpen = new  Map<Id, contact>([SELECT Id,Total_Open_Tickets__c,Total_Closed_Tickets__c,(SELECT ID FROM Cases WHERE IsClosed=FALSE) 
                                     FROM CONTACT 
                                     WHERE ID IN:idContactSet]);
    
    Map<Id, contact> conMapToUpdateClosed = new Map<Id, contact>([SELECT Id,Total_Open_Tickets__c,Total_Closed_Tickets__c,(SELECT ID FROM Cases WHERE IsClosed=TRUE) 
                                     FROM CONTACT 
                                     WHERE ID IN:idContactSet]);
    

    for(Id id : idContactSet){
     
        Contact contactRec = new Contact(Id = id);
        contactRec.Total_Open_Tickets__c = 0;
        contactRec.Total_Closed_Tickets__c = 0;
        
        if(conMapToUpdateOpen.get(id).Cases != null && conMapToUpdateOpen.get(id).Cases.size() > 0)
            contactRec.Total_Open_Tickets__c = conMapToUpdateOpen.get(id).Cases.size();
        
        if(conMapToUpdateClosed.get(id).Cases != null && conMapToUpdateClosed.get(id).Cases.size() > 0)
            contactRec.Total_Closed_Tickets__c = conMapToUpdateClosed.get(id).Cases.size();
        
        contactListToUpdate.add(contactRec);
    }
    
    Database.update(contactListToUpdate);
}

 
This was selected as the best answer
Gary Singh (BlackBeltHelp)Gary Singh (BlackBeltHelp)
Hi Abdul, 

Thanks, it works like a charm! , being new to APEX I see this as a new pattern of writing apex with MAP.  The one I was writing vs the one you shared I wonder if it can be used for other use cases. 

Off the topic: 
Tutorials in general,  are very basic and generally do not touch real word examples or are shared in very abstract form. Screnarios of how a business problem can be automated with and without maps, those are limited. 

I have started picking small automation scenarios where an admin can pick either a screen flow / Workflow rules / Proces Builder / Record trigger flows in general and see if those could be converted to APEX. 

Is it the best way to get into learning apex?

- Gary
Abdul KhatriAbdul Khatri
I would appreciate if you can mark that a best answer as it will mark it resolved and help others.

You are correct, Tutorials only teaches you the language how to use it, they really don't go into the nitty gritty of real work scenarios which comes either with experience or working with experience professionals. 

To learn apex or any language, I would recommend to read blogs, books etc. that helps a lot.

I really do not have any specific ones to direct you as I just randomly read things on the internet and being in this field for the long time, carries a lot of self experience things. but you will definitely find blogs of lots of MVPs

Let me know if you need any help.