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.
- When any new child record is inserted, we need to update the rollup summary field on the parent record. (After Insert)
- When the parent id is updated on the child record, we need to update the rollup summary field on the parent record. (After Update)
- For any child record deleted, we need to update the rollup summary field on the parent record. (Before Delete)
- 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.
