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!
