The requirement is to create a field on the Account object that displays the count of associated contact records for that specific Account, essentially implementing Roll-Up Summary functionality between Account and Contact.
This scenario is often encountered in interviews, and let’s break down the key points:
- Creation of Field:
- A new field needs to be created on the Account object.
- This field will represent the count of contact records related to the specific Account.
- Roll-Up Summary Logic:
- When a new contact record is created, the count field on the parent Account should be updated.
- If a contact is updated and its AccountId is modified to another Account, the count field on the original Account needs to be updated.
- When a contact is deleted, the count field on the parent Account should be decremented.
- If a deleted contact is undeleted, the count field on the parent Account should be incremented.
- Trigger Implementation:
- The trigger is designed using the Trigger handler pattern.
- The Trigger itself remains minimal, with the handler class containing the business logic.
This setup ensures efficient handling of the specified requirements, creating a robust solution for the given scenario.
trigger ContactTrigger on Contact( after insert, after update, after delete, after undelete ) { //when the record is inserted and undeleted increment count if ( (Trigger.isAfter && Trigger.isInsert) || (Trigger.isAfter && Trigger.isUndelete) ) { ContactHandler.incrementCount(Trigger.new); } //when updated and the parent is changed decrement it if ((Trigger.isAfter && Trigger.isUpdate)) { ContactHandler.decrementCount(Trigger.oldMap, Trigger.newMap); } //when deleted dercement it if (Trigger.isAfter && Trigger.isDelete) { ContactHandler.decrementDeleteCount(Trigger.oldMap); } }
public with sharing class ContactHandler { public ContactHandler() { } public static void incrementCount(List<Contact> contactsList) { List<Account> tobeUpdatedAccountsMap = new List<Account>(); List<Id> accountIds = new List<Id>(); for (Contact c : contactsList) { accountIds.add(c.AccountId); } Map<Id, Account> accountsMap = new Map<Id, Account>( [SELECT Count__c FROM Account WHERE Id IN :accountIds] ); for (Contact c : contactsList) { if (accountsMap.get(c.AccountId) != null) { Account a = new Account(); a.Id = c.AccountId; System.debug(' 🚀 ' + c.Account.Count__c); a.count__c = accountsMap.get(c.AccountId).Count__c + 1; tobeUpdatedAccountsMap.add(a); } } update tobeUpdatedAccountsMap; } public static void decrementCount( Map<Id, Contact> oldContactsMap, Map<Id, Contact> newContactsMap ) { List<Id> accountIds = new List<Id>(); for (Contact c : oldContactsMap.values()) { accountIds.add(c.AccountId); } for (Contact c : newContactsMap.values()) { accountIds.add(c.AccountId); } Map<Id, Account> accountsMap = new Map<Id, Account>( [SELECT Count__c FROM Account WHERE Id IN :accountIds] ); List<Account> tobeUpdatedAccountsMap = new List<Account>(); for (Contact c : newContactsMap.values()) { Id oldAccountId = oldContactsMap.get(c.Id).AccountId; Id newAccountId = newContactsMap.get(c.Id).AccountId; if ( (oldAccountId != null && newAccountId != null) && (oldAccountId != newAccountId) ) { Account a = new Account(); a.Id = c.AccountId; a.count__c = accountsMap.get(c.AccountId).Count__c + 1; tobeUpdatedAccountsMap.add(a); } } for (Contact c : oldContactsMap.values()) { Id oldAccountId = oldContactsMap.get(c.Id).AccountId; Id newAccountId = newContactsMap.get(c.Id).AccountId; if ( (oldAccountId != null && newAccountId != null) && (oldAccountId != newAccountId) ) { Account a = new Account(); a.Id = c.AccountId; a.count__c = accountsMap.get(c.AccountId).Count__c - 1; tobeUpdatedAccountsMap.add(a); } } update tobeUpdatedAccountsMap; } public static void decrementDeleteCount(Map<Id, Contact> oldContactsMap) { List<Id> accountIds = new List<Id>(); for (Contact c : oldContactsMap.values()) { accountIds.add(c.AccountId); } Map<Id, Account> accountsMap = new Map<Id, Account>( [SELECT Count__c FROM Account WHERE Id IN :accountIds] ); Map<Id, Account> tobeUpdatedAccountsMap = new Map<Id, Account>(); for (Contact c : oldContactsMap.values()) { Id oldAccountId = oldContactsMap.get(c.Id).AccountId; if ((oldAccountId != null)) { Account a = new Account(); a.Id = c.AccountId; a.count__c = accountsMap.get(c.AccountId).Count__c + 1; tobeUpdatedAccountsMap.put(a.Id, a); } } for (Contact c : oldContactsMap.values()) { Id oldAccountId = oldContactsMap.get(c.Id).AccountId; if ((oldAccountId != null)) { Account a = new Account(); a.Id = c.AccountId; a.count__c = accountsMap.get(c.AccountId).Count__c - 1; tobeUpdatedAccountsMap.put(a.Id, a); } } update tobeUpdatedAccountsMap.values(); } }
Let me know if you have an improved or refactored approach for accomplishing this task!