Created
August 20, 2018 12:10
-
-
Save dhruv-soft/82ab41d78a897183bd5f44787d66e8a7 to your computer and use it in GitHub Desktop.
Count the total number of contacts at the account level in salesforce
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 1: | |
* TriggerHandler | |
* This class is the primary class to centralize all Trigger logic | |
* This class is the virtual class, that you must extend for each of the class where you implement actual trigger logic | |
* public class ContactTriggerHandler extends TriggerHandler{ | |
* } | |
* This class provides default and empty implementation for each of the trigger event, and processTrigger() method | |
which will call actual Trigger event methods that is developed in Handler class like ContactTriggerHandler | |
* Created by: contact (at) dhruvsoft.com | |
*/ | |
public virtual class TriggerHandler { | |
public virtual void beforeInsert(){ | |
} | |
public virtual void afterInsert(){ | |
} | |
public virtual void beforeUpdate(){ | |
} | |
public virtual void afterUpdate(){ | |
} | |
public virtual void beforeDelete(){ | |
} | |
public virtual void afterDelete(){ | |
} | |
public virtual void afterUnDelete(){ | |
} | |
public void processTrigger(){ | |
if(Trigger.isBefore){ | |
//entered before event | |
if(Trigger.isInsert){ | |
beforeInsert(); | |
}else if(Trigger.isUpdate){ | |
beforeUpdate(); | |
}else if(Trigger.isDelete){ | |
beforeDelete(); | |
} | |
}else{ | |
//entered after event | |
if(Trigger.isInsert){ | |
afterInsert(); | |
}else if(Trigger.isUpdate){ | |
afterUpdate(); | |
}else if(Trigger.isDelete){ | |
afterDelete(); | |
}else if(Trigger.isUndelete){ | |
afterUnDelete(); | |
} | |
} | |
} | |
} | |
/** | |
* Step 2: | |
* ContactTriggerHandler | |
* This class contains all the trigger logic w.r.t Contact object. | |
* In Future if you want to add one more trigger/ Trigger logic, then keep consideration of this class and do implementation of related event logic in related methods | |
* Eg., If you want to add logic realted to after insert trigger in future, then add logic inside afterInsert() method. so we can keep track of all trigger code at one place specific to trigger event based in respective methods. | |
* Created by: contact (at) dhruvsoft.com | |
*/ | |
public class ContactTriggerHandler extends TriggerHandler{ | |
//Method: afterInsert | |
//Usage: this method is invoked in the context of "Trigger.isAfter && Trigger.isInsert" , so all the logic w.r.t after insert trigger context will be implemented here. | |
public override void afterInsert(){ | |
list<Contact> triggerNew = Trigger.New; | |
set<ID> accountIdSet=new set<ID>(); | |
for(Contact newContact: triggerNew){ | |
//check if contct is related to Account or not | |
if(newContact.AccountId!=null){ | |
//Yes, Contact is realted to Account. Then add accountId to accountIdSet. | |
accountIdSet.add(newContact.AccountId); | |
} | |
} | |
if(!accountIdSet.isEmpty()){ | |
calculateCountOnAccount(accountIdSet); | |
} | |
} | |
//Method: afterUpdate | |
//Usage: this method is invoked in the context of "Trigger.isAfter && Trigger.isUpdate" , so all the logic w.r.t after update trigger context will be implemented here. | |
public override void afterUpdate(){ | |
list<Contact> triggerNew = Trigger.New; | |
Map<Id, Contact> triggerOldMap = (Map<Id, Contact>)Trigger.oldMap; | |
set<ID> accountIdSet=new set<ID>(); | |
for(Contact newContact: triggerNew){ | |
Contact oldContact = triggerOldMap.get(newContact.Id); | |
//check contact account is changed or not and Contact is realted to Account. | |
if(newContact.AccountId !=null ){ | |
if(newContact.AccountId!=oldContact.AccountId){ | |
//Yes, Contact is realted to Account. Then add accountId to accountIdSet. | |
accountIdSet.add(newContact.AccountId); | |
} | |
}else if(newContact.AccountId == null && oldContact.AccountId!=null){ | |
accountIdSet.add(oldContact.AccountId); | |
} | |
} | |
if(!accountIdSet.isEmpty()){ | |
calculateCountOnAccount(accountIdSet); | |
} | |
} | |
//Method: afterDelete | |
//Usage: this method is invoked in the context of "Trigger.isAfter && Trigger.isdelete" , so all the logic w.r.t after delete trigger context will be implemented here. | |
public override void afterDelete(){ | |
list<Contact> triggerOld = Trigger.Old; | |
set<ID> accountIdSet=new set<ID>(); | |
for(Contact oldContact: triggerOld){ | |
if(oldContact.AccountId!=null){ | |
//Yes, Contact is realted to Account. Then add accountId to accountIdSet. | |
accountIdSet.add(oldContact.AccountId); | |
} | |
} | |
if(!accountIdSet.isEmpty()){ | |
calculateCountOnAccount(accountIdSet); | |
} | |
} | |
//Method: afterUnDelete | |
//Usage: this method is invoked in the context of "Trigger.isAfter && Trigger.isUndelete" , so all the logic w.r.t after undelete trigger context will be implemented here. | |
public override void afterUnDelete(){ | |
list<Contact> triggerNew = Trigger.New; | |
Map<Id, Contact> triggerOldMap = (Map<Id, Contact>)Trigger.oldMap; | |
set<ID> accountIdSet=new set<ID>(); | |
for(Contact newContact: triggerNew){ | |
if(newContact.AccountId!=null){ | |
//Yes, Contact is realted to Account. Then add accountId to accountIdSet. | |
accountIdSet.add(newContact.AccountId); | |
} | |
} | |
if(!accountIdSet.isEmpty()){ | |
calculateCountOnAccount(accountIdSet); | |
} | |
} | |
//method will calculate count of all child contacts w.r.t each Account | |
private void calculateCountOnAccount(set<Id> accountIdSet){ | |
list<Account> updateAccountList=new list<Account>(); | |
//Parent to child query : Getting Accounts and their related Contacts | |
for(Account account: [Select Id, Number_of_contacts__c, (SELECT Id from Contacts) FROM Account WHERE ID in: accountIdSet]){ | |
Integer contactCount = 0; | |
for(Contact contact: account.Contacts){ | |
contactCount++; | |
} | |
account.Number_of_Contacts__c = contactCount; | |
updateAccountList.add(account); | |
} | |
if(!updateAccountList.isEmpty()){ | |
update updateAccountList; | |
} | |
} | |
} | |
/** | |
* Step 3: | |
* TriggerHandlerFactory | |
* This class is developed using Factory Method pattern | |
* The main responsibility of this class is to instantiate the actual implementation, and return instance variable (Eg., handler variable in this class). | |
* handler = new ContactTriggerHandler(); | |
* return handler; | |
* Created by: contact (at) dhruvsoft.com | |
*/ | |
public class TriggerHandlerFactory{ | |
public static TriggerHandler createTriggerHandler(Schema.SObjectType sObjType){ | |
TriggerHandler handler; | |
if(sObjType == Contact.sObjectType){ | |
handler = new ContactTriggerHandler(); | |
} | |
if (handler == null){ | |
throw new TriggerException('No Trigger Handler registered for Object Type: ' + sObjType); | |
} | |
return handler; | |
} | |
public class TriggerException extends Exception{ | |
} | |
} | |
/** | |
* Step 4: | |
* ContactTrigger | |
* You should not allowed to write/implement logic in this trigger. | |
* Please implement/add your trigger logic inside of ContactTriggerHandler class, for more details please check ContactTriggerHandler class. | |
* Created by: contact (at) dhruvsoft.com | |
*/ | |
trigger ContactTrigger on Contact(after delete, after insert, after undelete, after update,before delete, before insert, before update){ | |
TriggerHandler handler = TriggerHandlerFactory.createTriggerHandler(Contact.sObjectType); | |
handler.processTrigger(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment