Create A Trigger To Tally The Quantity Of Associated Child Records linked To The Parent Object.

Create a trigger that calculates the count of child records related to parent records. Implement a custom rollup summary field using an Apex trigger. Establish a rollup summary on a lookup relationship using a trigger.

To illustrate the issue, let’s consider an example. We have a lookup relationship between Accounts and Contacts, and we need to determine the number of child records associated with each account.


Before crafting a trigger to count the number of child records, it’s important to take into account several scenarios.
  1. When any new child record is inserted, we need to update the rollup summary field on the parent record. (After Insert)
  2. When the parent id is updated on the child record, we need to update the rollup summary field on the parent record. (After Update)
  3. For any child record deleted, we need to update the rollup summary field on the parent record. (Before Delete)
  4. For any child record undeleted, we need to update the rollup summary field on the parent record. (After Undelete)
Please make a note of the following:
  • Always follow salesforce best practices while writing code. (Apex Trigger and Apex Class(Trigger Helper class )
  • For after update always query both old and new parent records to update the count. We generally query only new parent records.
  • Write a trigger to count the number of related child records on parent records.

Apex Trigger
trigger RollUpCountTrigger on Contact (after insert, after update, after delete, after undelete) {
    //when child record inserted and undeleted
    if(trigger.isAfter && (trigger.isInsert || trigger.isUndelete)){
        RollUpCountTrigger.countContact(trigger.new);
    }
    else if(trigger.isAfter && trigger.isDelete){ // when child record deleted
        RollUpCountTrigger.countContact(trigger.old);
    }
    if(trigger.isAfter && trigger.isUpdate){ //when parent id updated on child records
        RollUpCountTrigger.countContactUpdate(trigger.new,trigger.oldMap);
    }
}
Trigger Helper Class (Apex Class)
public class RollUpCountTrigger {
     
    public static void countContact(List<Contact> newList){ //for insert, undelete and undelete
        Set<id> accountIds = new Set<id>();
        List<Account> listOfAccounts = new List<Account>();
         
        For(Contact con : newList){   
            if(con.AccountId != null){
                accountIds.add(con.accountId);  //new parent id         
            }     
        }            
        if(!accountIds.isEmpty()){
            List<Account> listAccount = [SELECT Id, Name, Number_of_Contacts__c, (SELECT Id FROM Contacts) FROM Account WHERE Id IN :accountIds];
            For(Account acc : listAccount){
                if(acc.Contacts.size()>0)
                    acc.Number_of_Contacts__c = acc.Contacts.size(); // count of child records
                listOfAccounts.add(acc);
            }
            if(listOfAccounts.size()>0)
                update listOfAccounts; //update parent records
        }
         
    }
     
    public static void countContactUpdate(List<Contact> newList,Map<Id,Contact> oldMap){  //for update
        Set<id> accountIds = new Set<id>();
        List<Account> listOfAccounts = new List<Account>();
         
        For(Contact con : newList){   
            if(con.AccountId != null){
                accountIds.add(con.accountId); // new parent id           
            }
            if(con.AccountId != oldMap.get(con.Id).AccountId){
                accountIds.add(oldMap.get(con.Id).AccountId);  // old parent id 
            }   
        }            
        if(!accountIds.isEmpty()){
            List<Account> listAccount = [SELECT Id, Name, Number_of_Contacts__c, (SELECT Id FROM Contacts) FROM Account WHERE Id IN :accountIds];
            For(Account acc : listAccount){
                if(acc.Contacts.size()>0)
                    acc.Number_of_Contacts__c = acc.Contacts.size(); // count of child records
                listOfAccounts.add(acc);
            }
            if(listOfAccounts.size()>0)
                update listOfAccounts; // update parent records
        }  
    }
}

For any Queries/doubts comment below and for quick responses on LinkedIn and Twitter.