I have Active_Contacts__c Decimal field in Account and Active__c checkbox in Contact, also created ContactTrigger and ContactTrigger handler. I have already created logic for after update event and it works properly, but after delete event is not firing and nothing happens, though same code is working in anonymous.
Code below:
trigger ContactTrigger on Contact (after insert, after update, after delete, after undelete) {
switch on Trigger.operationType {
when AFTER_INSERT {
//
}
when AFTER_UPDATE {
ContactTriggerHandler.afterUpdate(Trigger.newMap, Trigger.oldMap);
}
when AFTER_DELETE {
ContactTriggerHandler.afterDelete(Trigger.oldMap);
}
when AFTER_UNDELETE {
//
}
}
}
___________________________________________________________________________________
public with sharing class ContactTriggerHandler {
public static void afterUpdate(Map<Id, SObject> newMap, Map<Id, SObject> oldMap) {
Contact temp1;
Contact temp2;
List<Contact> updatedContact = new List<Contact>();
for (Id contId : newMap.keySet()) {
temp1 = (Contact) newMap.get(contId);
temp2 = (Contact) oldMap.get(contId);
if (temp1.Active__c != temp2.Active__c) {
updatedContact.add(temp1);
}
}
if (updatedContact != null) {
countContactsRelatedToAccsIfUpdate(updatedContact);
}
}
public static void afterDelete(Map<Id, SObject> oldMap) {
countContactsRelatedToAccsIfDel(oldMap);
}
private static void countContactsRelatedToAccsIfUpdate(List<Contact> contacts) {
Set<Id> ids = new Set<Id>();
for (Contact cont : contacts){
ids.add(cont.AccountId);
}
List<Account> accounts = [SELECT Id, Active_Contacts__c, (SELECT Active__c FROM Contacts) FROM Account WHERE Id IN :ids ];
for(Account acc : accounts){
for(Contact cont: contacts){
if(cont.AccountId == acc.Id){
if (cont.Active__c == true) {
acc.Active_Contacts__c += 1;
} else if (cont.Active__c == false) {
acc.Active_Contacts__c -= 1;
}
}
}
}
update accounts;
}
private static void countContactsRelatedToAccsIfDel(Map<Id, SObject> oldContactsMap) {
Set<Id> contactsIds = oldContactsMap.keySet();
for (Contact cont : [SELECT Id FROM Contact]){
if (contactsIds.contains(cont.Id)){
contactsIds.remove(cont.Id);
}
}
List<Contact> contacts = [SELECT AccountId, Active__c FROM Contact WHERE Id = :contactsIds];
List<Account> accounts = [SELECT Active_Contacts__c FROM Account WHERE Id IN (SELECT AccountId FROM Contact WHERE Id = :contactsIds)];
for (Account acc : accounts){
for(Contact cont : contacts){
if(cont.AccountId == acc.Id && cont.Active__c == true){
acc.Active_Contacts__c -= 1;
}
}
}
update accounts;
}
after delete
in the trigger declaration? Is the deletion a cascade delete or an explicit DMLdelete
?for (Contact cont : [SELECT Id FROM Contact]){
will retrieve every Contact in the databaseSystem.debug
statements) or is it that it doesn't do the processing you are expecting? Why are you querying all Contacts at the start of thecountContactsRelatedToAccsIfDel
? This will go wrong if you have more than 50000 Contacts in your org and seems rather pointless too. If you want to verify that the IDs have really been deleted, use them in the query likeSELECT Id FROM Contact WHERE Id IN :contactsIds
, though this is overly defensive IMHO.