function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
jaysree Ajaysree A 

How to achieve rollup functionality in lookup relationship

Best Answer chosen by jaysree A
JyothsnaJyothsna (Salesforce Developers) 
Hi Jaysree,

Using triggers, you can achieve rollup functionality with lookup relationship.
 For example, Display a number of contacts in each account. Create a custom field "number_of_contacts" in Account object and write a trigger on contact object.

Please check the below sample code.

trigger ContactCount on Contact (after insert, after update, after delete) {
    Map<Id, List<Contact>> AcctContactList = new Map<Id, List<Contact>>();
    Set<Id> AcctIds = new Set<Id>();    
    List<Account> AcctList = new List<Account>();
    List<Contact> ConList = new List<Contact>();
    
    if(trigger.isInsert || trigger.isUPdate) {
        for(Contact Con : trigger.New) {
            if(String.isNotBlank(Con.AccountId)){
                AcctIds.add(Con.AccountId);  
            }   
        }  
    }
    
    if(trigger.isDelete || trigger.isUPdate) {
        for(Contact Con : trigger.Old) {
            AcctIds.add(Con.AccountId);     
        }  
    }           
    
    if(AcctIds.size() > 0){
        ConList = [SELECT Id, AccountId FROM Contact WHERE AccountId IN : AcctIds];
        
        for(Contact Con : ConList) {
            if(!AcctContactList.containsKey(Con.AccountId)){
                AcctContactList.put(Con.AccountId, new List<Contact>());
            }
            AcctContactList.get(Con.AccountId).add(Con);      
        }                           
        
        System.debug('Account Id and Contact List Map is ' + AcctContactList);
            
        AcctList = [SELECT No_of_contacts__c FROM Account WHERE Id IN : AcctIds];
        
        for(Account Acc : AcctList) {
            List<Contact> ContList = new List<Contact>();
            ContList = AcctContactList.get(Acc.Id);
            Acc.No_of_contacts__c= ContList.size();
        }    
        
        System.debug('Account List is ' + AcctList);
        update AcctList;    
    }

}

Hope this helps you!
Best Regards,
Jyothsna

All Answers

Mahesh DMahesh D
Hi JayaSree,

Please follow the below information:

You can do the same with Process builder. Please check below post i hope that will help you
Option 1:- Process builder
1) https://developer.salesforce.com/forums/?id=906F0000000BHvJIAW
2) https://developer.salesforce.com/forums/?id=906F0000000B2C0IAK  --- This may not be exact match.

Option 2:- Trigger
1) http://blog.jeffdouglas.com/2011/08/23/salesforce-trigger-when-rollups-summaries-not-possible/
2) https://success.salesforce.com/answers?id=90630000000h3mNAAQ
3) https://developer.salesforce.com/forums/?id=906F00000008yWuIAI
4) https://github.com/abhinavguptas/Salesforce-Lookup-Rollup-Summaries
5) http://www.iterativelogic.com/developing-custom-apex-rollup-summary-field-logic/

Also look into the below explanation:

To calculate Rollup Summary using the Trigger, you need to follow below:

Need to consider all DML operations like insert, update, delete and undelete of child records.

Insert of Child record:
     --> Need to write an after insert trigger to update the Parent record with calculated sum value.
Update of Child record:
     --> Make sure that the Parent information got changed.
     --> Need to write an after update trigger and get both old and new Parent information and perform the re-calculation of sum.
Delete of Child record:
     --> Need to write an after delete trigger to update the Parent record with re-calculated sum value.
Undelete of Child record:
     --> Need to write an after undelete trigger to update the Parent record with re-calculated sum value.

Also check the below code:
 
trigger PrimaryContactCount on Contact (after insert, after delete, after undelete,after update) {
    set<Id> accIds = new set<Id>();
    
    if(trigger.isinsert || trigger.isUpdate || trigger.Isundelete){
        for(Contact con: Trigger.new){
			if(Trigger.isInsert || Trigger.isUndelete || (con.Primary_Contact_del__c != Trigger.oldMap.get(con.Id).Primary_Contact_del__c))
				accIds.add(con.AccountId);            
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){
            if(Trigger.isDelete || (con.Primary_Contact_del__c != Trigger.oldMap.get(con.Id).Primary_Contact_del__c))
				accIds.add(con.AccountId);
        }
    }    
    
    List<Account> accList = [select id, Number_of_Primary_Contacts__c, (Select Id, Primary_Contact_del__c from Contacts) from Account Where ID IN: accIds];
    
    for(Account acc : accList){
        system.debug('Contacts--->'+acc.contacts.size());
        acc.Number_of_Primary_Contacts__c = 0;
        for(Contact con : acc.Contacts) {
			if(con.Primary_Contact_del__c)
				acc.Number_of_Primary_Contacts__c++;
        }
    }
    update accList;
}

Please do let me know if it helps you.

Regards,
Mahesh
JyothsnaJyothsna (Salesforce Developers) 
Hi Jaysree,

Using triggers, you can achieve rollup functionality with lookup relationship.
 For example, Display a number of contacts in each account. Create a custom field "number_of_contacts" in Account object and write a trigger on contact object.

Please check the below sample code.

trigger ContactCount on Contact (after insert, after update, after delete) {
    Map<Id, List<Contact>> AcctContactList = new Map<Id, List<Contact>>();
    Set<Id> AcctIds = new Set<Id>();    
    List<Account> AcctList = new List<Account>();
    List<Contact> ConList = new List<Contact>();
    
    if(trigger.isInsert || trigger.isUPdate) {
        for(Contact Con : trigger.New) {
            if(String.isNotBlank(Con.AccountId)){
                AcctIds.add(Con.AccountId);  
            }   
        }  
    }
    
    if(trigger.isDelete || trigger.isUPdate) {
        for(Contact Con : trigger.Old) {
            AcctIds.add(Con.AccountId);     
        }  
    }           
    
    if(AcctIds.size() > 0){
        ConList = [SELECT Id, AccountId FROM Contact WHERE AccountId IN : AcctIds];
        
        for(Contact Con : ConList) {
            if(!AcctContactList.containsKey(Con.AccountId)){
                AcctContactList.put(Con.AccountId, new List<Contact>());
            }
            AcctContactList.get(Con.AccountId).add(Con);      
        }                           
        
        System.debug('Account Id and Contact List Map is ' + AcctContactList);
            
        AcctList = [SELECT No_of_contacts__c FROM Account WHERE Id IN : AcctIds];
        
        for(Account Acc : AcctList) {
            List<Contact> ContList = new List<Contact>();
            ContList = AcctContactList.get(Acc.Id);
            Acc.No_of_contacts__c= ContList.size();
        }    
        
        System.debug('Account List is ' + AcctList);
        update AcctList;    
    }

}

Hope this helps you!
Best Regards,
Jyothsna
This was selected as the best answer
Mahesh DMahesh D
Hi Jayasree,

I would like to ask you a question here,

Did you get a chance to review the example which I posted because the solution which Jyothsna provided:

(1) will not handle undelete operation.If the user deletes the Contact and do undelete the count will not display properly.
(2) We don't need to do the calculation of Rollup Summary for every modification of Contact, only if Account change happened then only we have to do it.

For your information, I am posting you another example here:
//
// ContactCount trigger to handle the roll up summary on Account
//
trigger ContactCountNew on Contact (after insert, after delete, after undelete, after update) {
    set<Id> accIdSet = new set<Id>();
    
    if(trigger.isinsert || trigger.isUpdate || trigger.Isundelete){
        for(Contact con: Trigger.new){
            if(Trigger.isInsert || Trigger.isUndelete || (con.AccountId != Trigger.oldMap.get(con.Id).AccountId))
                accIdSet.add(con.AccountId);
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){
            if(Trigger.isDelete || (con.AccountId != Trigger.newMap.get(con.Id).AccountId))
                accIdSet.add(con.AccountId);
        }
    }    
    
    if(!accIdSet.isEmpty()) {
        List<Account> accList = [select Id, Count__c, (Select Id from Contacts) from Account Where ID IN: accIdSet];
        
        for(Account acc : accList){
            System.debug('Contacts--->'+acc.Contacts.size());
            acc.Count__c = acc.Contacts.size();
        }
        update accList;
    }
}

Please look into it and let me know if it helps you.

Regards,
Mahesh