Trigger 3 - Roll up Summary Trigger
Trigger to count the number of Contacts associated with an Account and display the Contacts count on the Account's custom field.
trigger ContactTrigger on Contact (after insert, after update, after delete, after undelete) {
if (Trigger.isAfter) {
if (Trigger.isInsert || Trigger.isUndelete) {
ContactTriggerHandler.countContacts(Trigger.new, null);
}
else if (Trigger.isUpdate) {
ContactTriggerHandler.countContacts(Trigger.new, Trigger.oldMap);
}
else if (Trigger.isDelete) {
ContactTriggerHandler.countContacts(null, Trigger.oldMap);
}
}
}
public class ContactTriggerHandler {
public static void countContacts(List<Contact> newContacts, Map<Id, Contact> oldContactMap) {
Set<Id> accountIds = new Set<Id>();
// 1. Capture Account IDs from New or Undeleted Contacts
if (newContacts != null) {
for (Contact con : newContacts) {
if (con.AccountId != null) {
accountIds.add(con.AccountId);
}
// Handle reparenting: capture the old account ID if the account changed
if (oldContactMap != null && oldContactMap.containsKey(con.Id)) {
Id oldAccountId = oldContactMap.get(con.Id).AccountId;
if (oldAccountId != null && oldAccountId != con.AccountId) {
accountIds.add(oldAccountId);
}
}
}
}
// 2. Capture Account IDs from Deleted Contacts
if (newContacts == null && oldContactMap != null) {
for (Contact con : oldContactMap.values()) {
if (con.AccountId != null) {
accountIds.add(con.AccountId);
}
}
}
// 3. Process calculations if we have affected Accounts
if (!accountIds.isEmpty()) {
List<Account> accountsToUpdate = new List<Account>();
// Initialize all targeted accounts with 0 to clear count if all contacts are deleted/moved
for (Id accId : accountIds) {
accountsToUpdate.add(new Account(Id = accId, Number_of_Contacts__c = 0));
}
// Query current counts using SOQL Aggregate
List<AggregateResult> results = [
SELECT AccountId, COUNT(Id) totalContacts
FROM Contact
WHERE AccountId IN :accountIds
GROUP BY AccountId
];
// Map the active aggregated counts to a map structure
Map<Id, Integer> accountCountMap = new Map<Id, Integer>();
for (AggregateResult ar : results) {
Id accId = (Id) ar.get('AccountId');
Integer count = (Integer) ar.get('totalContacts');
accountCountMap.put(accId, count);
}
// Populate the specific counted values back into our update array
for (Account acc : accountsToUpdate) {
if (accountCountMap.containsKey(acc.Id)) {
acc.Number_of_Contacts__c = accountCountMap.get(acc.Id);
}
}
// Commit changes to the database
if (!accountsToUpdate.isEmpty()) {
update accountsToUpdate;
}
}
}
}
Comments
Post a Comment