Create a Rollup-Summary trigger in Salesforce?

on

|

views

and

comments

Table of Contents

Prerequisite

Create a Custom Field on the Account Object “Number of Contacts” with a Number Data Type that does not have any decimal point in it.

Introduction to Apex Trigger Scenario

Requirement (Roll-up Summary Trigger)
Develop a Solution that will count the related contact related to the Account and store the information in the “Number of Contacts” field.

Note:- The contact can be created/deleted/undeleted and updated from the Account Record. So please keep that in mind

Questions to be asked

Question?

  • Which Object
    • Contact
  • Events
    • after insert, after delete, after undelete, after update
  • Functionality
    • Develop a Solution that will count the related contact related to the Account and store the information in the “Number of Contacts” field.

Hands-On

Apex Trigger

				
					trigger ContactTrigger on Contact (after insert, after update, after delete, after undelete) {
    ContactTriggerDispatcher.dispatch(Trigger.OperationType);
}
				
			

Dispatcher Class

				
					public class ContactTriggerDispatcher {
    public static void dispatch(System.TriggerOperation operationType){
        switch on operationType{
            WHEN AFTER_INSERT{
                ContactTriggerHandler.handleAfterInsert((Map<Id, Contact>)Trigger.newMap); // Map<Id, sObject>
            }
            WHEN AFTER_UPDATE{
                ContactTriggerHandler.handleAfterUpdate((Map<Id, Contact>)Trigger.newMap, (Map<Id, Contact>)Trigger.oldMap);
            }
            WHEN AFTER_DELETE{
                ContactTriggerHandler.handleAfterDelete((Map<Id, Contact>)Trigger.oldMap);
            }
            WHEN AFTER_UNDELETE{
                ContactTriggerHandler.handleAfterUndelete((Map<Id, Contact>)Trigger.newMap); // Map<Id, sObject>
            }
        }
    }
}
				
			

Handler Class

				
					public class ContactTriggerHandler {

    public static void handleAfterInsert(Map<Id, Contact> newRecordsMap){
        ContactTriggerHelper.countContact(newRecordsMap);
    }
    public static void handleAfterUndelete(Map<Id, Contact> newRecordsMap){
        ContactTriggerHelper.countContact(newRecordsMap);
    }
    public static void handleAfterDelete(Map<Id, Contact> oldRecordsMap){
        ContactTriggerHelper.countContact(oldRecordsMap);
    }
    public static void handleAfterUpdate(Map<Id, Contact> newRecordsMap, Map<Id, Contact> oldRecordsMap){
        Set<Id> accountIdsSet = new Set<Id>();
        for(Contact newRecord : newRecordsMap.values() ){
            Contact oldRecord = oldRecordsMap.get(newRecord.Id);
            if(oldRecord.AccountId <> newRecord.AccountId){
                accountIdsSet.add(oldRecord.AccountId); // ABC
                accountIdsSet.add(newRecord.AccountId); // XYZ
            }
        }
        List<AggregateResult> aggregateList = [SELECT count(Id), AccountId
                                               FROM Contact
                                               WHERE AccountId IN:accountIdsSet 
                                               Group By AccountId];
        
        List<Account> accountListToUpdate = new List<Account>();
        for(AggregateResult ag : aggregateList){
            String accountId = (String)ag.get('AccountId'); // Object
            Integer totalContact = (Integer)ag.get('expr0'); // Object
            Account accountRecord = new Account();
            accountRecord.Id = accountId;
            accountRecord.Number_of_Contacts__c = totalContact;
            accountListToUpdate.add(accountRecord);
        }
        update accountListToUpdate;
    }
}
				
			

Helper Class

				
					public class ContactTriggerHelper {

    public static void countContact(Map<Id, Contact> newRecordsMap){
        // key - RecordId
        // value - Record
        // keySet() - Set<Key> - Set<Id>
        // values() - List<Value> - List<Account>
        
        /* Step1 - Get Account Ids */
        Set<Id> accountIdsSet = new Set<Id>();
        for(Contact con: newRecordsMap.values() ){
            if(con.AccountId <> null){ // check if contact is related to account
                accountIdsSet.add(con.AccountId);
            }
        }
        
        /* Solution #1 - Inner Query 
        List<Account> accountList = new List<Account>();
        accountList = [SELECT Id, (SELECT Id FROM CONTACTS) FROM Account WHERE Id IN: accountIdsSet]; //50K
        for(Account acc : accountList){
            List<CONTACT> contList = acc.CONTACTS; // List of Contact
            if(contList != null){
                Integer size = contList.size();
                acc.Number_of_Contacts__c = size;
            }
        }
        update accountList;
        */
        
        /* Solution #1 will fail in case of Bulk Recods */
        
        /* Solution #2 - Aggregate Query (Recomended) - SUM, COUNT, MIN, MAX, AVG */
        /* Aggregate Query - LIMIT 2000 */
        List<AggregateResult> aggregateList = [SELECT count(Id), AccountId
                                               FROM Contact
                                               WHERE AccountId IN:accountIdsSet 
                                               Group By AccountId];
        //(AggregateResult:{expr0=3, AccountId=0012w00001Pz63SAAR})
        //(AggregateResult:{totalContact=3, AccountId=0012w00001Pz63SAAR})
        System.debug(aggregateList);
        List<Account> accountListToUpdate = new List<Account>();
        for(AggregateResult ag : aggregateList){
            String accountId = (String)ag.get('AccountId'); // Object
            Integer totalContact = (Integer)ag.get('expr0'); // Object
            Account accountRecord = new Account();
            accountRecord.Id = accountId;
            accountRecord.Number_of_Contacts__c = totalContact;
            accountListToUpdate.add(accountRecord);
        }
        update accountListToUpdate;
    }
}
				
			

Watch Complete Video

Assignments

→ Apex Trigger 10

Prerequisite
Create the Custom Fields on the Account Object “Sum of Closed Opportunity Amount” & “Sum of Open Opportunity Amount” with a Currency Data Type with 2 Decimal Points.

Requirement (Rollup Summary Trigger)
Develop an Apex trigger to SUM the Opportunity Amount of the Closed Opportunity and Open Opportunities. The closed opportunities are the ones with the Status equal to “Closed Won” OR “Closed Lost”. And store the result in the “Sum of Closed Opportunity Amount” & “Sum of Open Opportunity Amount” fields respectively in the related Account for the opportunity.

Note:- The Opportunity can be created/deleted/undeleted and updated from the Account Record. So please keep that in mind

Scenarios for Update DML

  • The account has been changed
  • The amount has been changed

Resources

Amit Singh
Amit Singhhttps://www.pantherschools.com/
Amit Singh aka @sfdcpanther/pantherschools, a Salesforce Technical Architect, Consultant with over 8+ years of experience in Salesforce technology. 21x Certified. Blogger, Speaker, and Instructor. DevSecOps Champion
Share this

Leave a review

Excellent

SUBSCRIBE-US

Book a 1:1 Call

Must-read

How to Utilize Salesforce CLI sf (v2)

The Salesforce CLI is not just a tool; it’s the cornerstone of development on the Salesforce Platform. It’s your go-to for building, testing, deploying, and more. As one of the most important development tools in our ecosystem

Save the day of a Developer with Apex Log Analyzer

Table of Contents What is Apex Log Analyzer? Apex Log Analyzer, a tool designed with Salesforce developers in mind, is here to simplify and accelerate your...

Salesforce PodCast

Introduction Hey Everyone, Welcome to my podcast, the first-ever podcast in India for Salesforce professionals. Achievement We are happy to announce that we have been selected as Top...

Recent articles

More like this

LEAVE A REPLY

Please enter your comment!
Please enter your name here

5/5

Stuck in coding limbo?

Our courses unlock your tech potential