Monday, 5 June 2017

Roll Up Summary Trigger | SUM Child Records | Aggregate Query

Roll Up Summary Trigger: SUM


Scenario:

Sum Cost field(Cost__c) values on Contact(s)(all Contacts related to an Account)and display on Account Record in field-TotalCost(Total_Cost__c).
Behaviour:
Same a SUM Roll Up Summary Field

trigger ContactTrigger on Contact (after insert) {
  ContactTriggerHandler.CalculateTotalCost(Trigger.new);
}

public class ContactTriggerHandler{
  public static void CalculateTotalCost(List<Contact> contactList){
    List<Account> accountList = new List<Account>();
Set<Id> accountIds = new Set<Id>();
for(Contact con:contactList){
 accountIds.add(con.AccountId);
}
//This Map stores Account Id as a Key and related Total Cost as Value
Map<Id,Double> AccountId_Key_TotalCost_ValueMap = new Map<Id,Double>();
//Aggregate query is used to store Sum of all related Cost Fields on Contact
for(AggregateResult con  : [SELECT AccountId,SUM(Cost__c) maxcost
   FROM Contact WHERE AccountId IN :accountIds
GROUP BY AccountId]) {
 AccountId_Key_TotalCost_ValueMap.put((Id)con.get('AccountId'),(Double)con.get('maxcost'));          
}
//Logic to update Total_Cost__c values appropriately
// based on AccountId_Key_TotalCost_ValueMap Map and put null/zero if none of the related
// Contact records exist
for(Account acc : [SELECT Total_Cost__c FROM Account WHERE Id IN : accountIds]) {
 if(AccountId_Key_TotalCost_ValueMap.ContainsKey(acc.Id)){                      
   acc.Total_Cost__c = AccountId_Key_TotalCost_ValueMap.get(acc.Id);
 }
      else{
   acc.Total_Cost__c = 0;
 }
 accountList.add(acc);                          
}
 // These variables are used to ids of Successful records and error messages
 Set<Id> successItemIds       = new Set<Id>();
 Set<String> errorItems       = new Set<String>();
if(accountList.size()>0) {
 Database.saveResult[] saveResultItems  = Database.update(accountList,false);
 for (Database.saveResult sr : saveResultItems) {
   if(sr.isSuccess()){
 successItemIds.add(sr.getId());
}
else{
 for(Database.Error err : sr.getErrors()) {
   errorItems.add(err.getMessage());
 }
}
 }
}
 // Iteration of Contact Records is done once again to make sure multiple errors 
       // are shown in case if multiple errors are thrown
       if(errorItems.size() > 0 ){
         for(Contact con: contactList) {
           if(!successItemIds.contains(con.AccountId)){
             for(String err: errorItems) {
               con.addError(err);
             }        
           }                      
        }
     }  
  }
}