Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dhruv-soft/82ab41d78a897183bd5f44787d66e8a7 to your computer and use it in GitHub Desktop.
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
/**
* 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