+ Start a Discussion
sonali  vermasonali verma 

Count Contacts

Hi friends

I need to count the number of contacts for each account. so I created a custom field (Number_of_Contacts_c) on the account object.
For new accounts I have written code and its working fine. Also when I delete a contact in detail page of account  its workign fine.
There will be old accounts with no contacts records in detail page prior to this code.  I am stuck here as how to update this accounts and show the number of contacts records

apex class code:
public class CountContacts_InAccount
{
      public void CountContacts()
      {
          list<Account> noofcontacts = [select Id,Number_of_contacts__c from Account];
          list<Contact> conforcontacts = [select ID,AccountID from Contact];
          
          for (Account acct : noofcontacts ) 
          {
              list<ID> conIds = new list<ID>();

              for (Contact con : conforcontacts )
              {
                    if (con.AccountId == acct.Id)
                    {
                       conIds.add(con.Id);
                       acct.Number_of_contacts__c= conIds.size();
                     }
              }
         }
          Database.Update(noofcontacts);   
     }
}

trigger code:
trigger trg_CountContacts on Contact (after Insert,after Update,after Delete,after Undelete)
{
     CountContacts  obj = new CountContacts();
     
     if ((Trigger.IsInsert) || (Trigger.IsUndelete))
     {
         obj.CountContacts(Trigger.New);
     }
     
     if (Trigger.IsDelete)
     {
         obj.CountContacts(Trigger.Old);
     }
}

Can any one psl elt me know:?

Regards
sonali verma
Best Answer chosen by sonali verma
sfdc Beginnersfdc Beginner
Hi Sonali,

Try with below trigger your functionality will be achieved.
 
trigger ContactsonAccount on Contact (after insert,after update,after delete,after undelete) {

    set<Id> aid = new set<Id>();
    
    // Adding Contacts when Inserted or Undeleted
    
    if(Trigger.isInsert || Trigger.isUndelete){
        for(Contact con : Trigger.new){
            aid.add(con.AccountId);
        }
        
        List<Account> acc = [SELECT Id,Number_of_Contacts__c FROM Account WHERE Id IN :aid];
        
        List<Contact> con = [SELECT Id FROM Contact WHERE AccountId IN :aid];
        
        for(Account a : acc){
            a.Number_of_Contacts__c = con.size();
        }
        
        update acc;
        
        
    }
    
    
    // Substracting Contacts When deleted.
    
    if(Trigger.isDelete){
        for(Contact con : Trigger.old){
            aid.add(con.AccountId);
        }
        
        List<Account> acc = [SELECT Id,Number_of_Contacts__c FROM Account WHERE Id IN :aid];
        
        List<Contact> con = [SELECT Id FROM Contact WHERE AccountId IN :aid];
        
        for(Account a : acc){
            a.Number_of_Contacts__c = con.size();
        }
        
        update acc;
        
        
    }
    
    
    if(Trigger.isUpdate){
    
        set<Id> oldaid = new Set<Id>();
        
        for(Contact con : Trigger.new){
        
            if(con.AccountId != Trigger.oldMap.get(con.id).AccountId){
                aid.add(con.Accountid);
                oldaid.add(Trigger.oldMap.get(con.id).AccountId);
            }
        
        }
        
        if(!aid.isEmpty()){
            // for New Accounts
            List<Account> acc = [SELECT Id,Number_of_Contacts__c FROM Account WHERE Id IN :aid];
            // For New Account Contacts
            List<Contact> Con = [SELECT Id FROM Contact WHERE AccountId IN :aid];
            
          
         /* This is for Old Contacts Count */
         
         
           // for old Accounts
            List<Account> oldacc = [SELECT Id,Number_of_Contacts__c FROM Account WHERE Id IN :oldaid];
            // For old Account Contacts
            List<Contact> oldCon = [SELECT Id FROM Contact WHERE AccountId IN :oldaid];
            
            
            // For New Accounts
            
            for(Account a : acc){
                a.Number_of_Contacts__c = con.size();
            }
            
            update acc;
            
            
            // For Old Accounts
            
            for(Account a : oldacc){
                a.Number_of_Contacts__c = oldcon.size();
            }
            
            update oldacc;
            
            
        }
        
        
        
    }
    
}


If this solves your Problem, Mark it as the Best Answer.


Thanks,
SFDC Beginner.






 

All Answers

ManojjenaManojjena
Hi Sonali ,

Try with below code it will help !
 
trigger ContactCount  on Contact ( after insert, after update,after delete,after undelete) {
     Set<Id> accountIdSet=new Set<Id>();
     List<Account> accListToUpdate=new List<Account>();
    if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete){
        for(Contact con : Trigger.new){
            if(con.AccountId != null)
                accountIdSet.add(con.AccountId);     
        }
    }If(Trigger.isDelete){
       for(Contact con : Trigger.old){
            if(con.AccountId != null)
                accountIdSet.add(con.AccountId);     
        }
    }
   for(AggregateResult res : [SELECT count(Id)can,AccountId FROM Contact WHERE AccountId IN :accountIdSet group by AccountId]) {
          accListToUpdate.add(new Account(Id=(Id)res.get('AccountId'),Number_of_contacts__c=(Integer)res.get('can')));
    }
    try{
      update accListToUpdate;
    }catch(DmlException de){
      System.debug(de);
    }
}

Let me know if it helps!

Thanks 
Manoj
Thiyagarajan Selvaraj (SFDC Developer)Thiyagarajan Selvaraj (SFDC Developer)
Hi Sonali, 

Go to developer console and execute the code below and should update the number of contacts field on the account
List<Account> accsList = [SELECT Id, Number_of_Contacts_c, (SELECT Id FROM Contacts) FROM Account];
for(Account acc : accsList){
	acc.Number_of_Contacts_c = acc.Contacts.size();
}	
update accsList;



 
doravmondoravmon
Since you didn't modified those old contact, the trigger will not fire. So you can go to developer console, and press ctrl+E  
In the new window, you can enter the code: 

List<Account> list = [select Id, Number_of_Contacts__c, (select Id from Contacts) from Account];
for(Account a:list)
   a.Number_of_Contacts_c = a.Contacts..size();
update list;

After this, all the old account will updated. Then the trigger will fire for all the new stuffs.
 
sfdc Beginnersfdc Beginner
Hi Sonali,

Try with below trigger your functionality will be achieved.
 
trigger ContactsonAccount on Contact (after insert,after update,after delete,after undelete) {

    set<Id> aid = new set<Id>();
    
    // Adding Contacts when Inserted or Undeleted
    
    if(Trigger.isInsert || Trigger.isUndelete){
        for(Contact con : Trigger.new){
            aid.add(con.AccountId);
        }
        
        List<Account> acc = [SELECT Id,Number_of_Contacts__c FROM Account WHERE Id IN :aid];
        
        List<Contact> con = [SELECT Id FROM Contact WHERE AccountId IN :aid];
        
        for(Account a : acc){
            a.Number_of_Contacts__c = con.size();
        }
        
        update acc;
        
        
    }
    
    
    // Substracting Contacts When deleted.
    
    if(Trigger.isDelete){
        for(Contact con : Trigger.old){
            aid.add(con.AccountId);
        }
        
        List<Account> acc = [SELECT Id,Number_of_Contacts__c FROM Account WHERE Id IN :aid];
        
        List<Contact> con = [SELECT Id FROM Contact WHERE AccountId IN :aid];
        
        for(Account a : acc){
            a.Number_of_Contacts__c = con.size();
        }
        
        update acc;
        
        
    }
    
    
    if(Trigger.isUpdate){
    
        set<Id> oldaid = new Set<Id>();
        
        for(Contact con : Trigger.new){
        
            if(con.AccountId != Trigger.oldMap.get(con.id).AccountId){
                aid.add(con.Accountid);
                oldaid.add(Trigger.oldMap.get(con.id).AccountId);
            }
        
        }
        
        if(!aid.isEmpty()){
            // for New Accounts
            List<Account> acc = [SELECT Id,Number_of_Contacts__c FROM Account WHERE Id IN :aid];
            // For New Account Contacts
            List<Contact> Con = [SELECT Id FROM Contact WHERE AccountId IN :aid];
            
          
         /* This is for Old Contacts Count */
         
         
           // for old Accounts
            List<Account> oldacc = [SELECT Id,Number_of_Contacts__c FROM Account WHERE Id IN :oldaid];
            // For old Account Contacts
            List<Contact> oldCon = [SELECT Id FROM Contact WHERE AccountId IN :oldaid];
            
            
            // For New Accounts
            
            for(Account a : acc){
                a.Number_of_Contacts__c = con.size();
            }
            
            update acc;
            
            
            // For Old Accounts
            
            for(Account a : oldacc){
                a.Number_of_Contacts__c = oldcon.size();
            }
            
            update oldacc;
            
            
        }
        
        
        
    }
    
}


If this solves your Problem, Mark it as the Best Answer.


Thanks,
SFDC Beginner.






 
This was selected as the best answer
sonali  vermasonali verma
Hi SFDC Beginner

I modified your code. It works.
Pls let me know in real time , should we have a single method which performs all operations or we can go for two different methods in apex class:?

apex class code:
public class CountContacts
{
     public void CountContacts(list<Contact> conID)
    {
         //INSERT. New contacts only
         Set<ID> aID = new Set<ID>();
                  
         for(Contact con:conID)
         {
             aID.add(con.AccountID);
         }
         
         list<Account> acc = [select Id,Number_of_contacts__c from Account where ID IN :aID];
         list<Contact> con = [select ID from Contact where AccountID IN :aID];
         
         for(Account acn:acc)
         {
             acn.Number_of_contacts__c=con.Size();
         }
         
         Database.Update(acc);
               
       // Substracting Contacts When deleted.
    
          for(Contact con1:conID)
         {
             aID.add(con1.AccountID);
         }         

         list<Account> a1 = [select Id,Number_of_contacts__c from Account where ID IN :aID];
         list<Contact> con_1 = [select ID from Contact where AccountID IN :aID];
         
         for(Account a:a1)
         {
             a.Number_of_contacts__c=con_1.Size();
         }
         
         Database.Update(a1);
          
       }  //method ends here
     
      public void CountContacts(list<Contact> conID,Map<ID,Contact> conmapIds)
      {
            //first parameter is Trigger.New  &   second parameter is  Trigger.OldMap
             Set<ID> aId = new SET<ID>(); //for New AccountIDs
             
             Set<ID> OldAId = new Set<ID>(); //for Old AccountIDs
             
             //Map<ID,Contact> cmapid = [select AccountID from Contact where ID IN :conmapIds];
             
             for(Contact opp : conID)
             {
             
                 if (opp.AccountId != conmapIds.get(opp.id).AccountId)
                {
                             aId.add(opp.AccountId);
                             
                             OldAId.add(conmapIds.get(opp.id).AccountId);
                }
            }
            
           if (!aId.isEmpty())
           {
                  //for new Accounts
                  List<Account> acc = [select id,Number_of_contacts__c from Account where Id in:aId];
                  
                  //For New Account Contacts
                  List<Contact> con = [select id from contact where AccountId in :aId];

                  /*  This is For Old Contacts Count */

                  //for Old Accounts
                  List<Account> Oldacc = [select id,Number_of_contacts__c from Account where Id in:OldAId];

                 //For Old Account Contacts
                  List<Contact> OldCon=[select id from contact where AccountId in :OldAId];

                //For New Accounts
                 for(Account a : acc)
                 {
                    a.Number_of_contacts__c=con.size();
                 }
              
                 Database.Update(acc);

                //For Old Accounts
                for(Account a : Oldacc)
               {
                 a.Number_of_contacts__c=OldCon.size();
               }

               Database.Update(Oldacc);
         }
      
      }//end of method
   
 } // end of class


Trigger Code:

trigger trg_CountContacts on Contact (after Insert,after Update,after Delete,after Undelete)
{
     CountContacts  obj = new CountContacts();
     
     if ((Trigger.IsInsert) || (Trigger.IsUndelete))
     {
         obj.CountContacts(Trigger.New);
     }
     
      if (Trigger.IsDelete)
     {
         obj.CountContacts(Trigger.Old);
     }
     
      if (Trigger.IsUpdate)
     {
         obj.CountContacts(Trigger.New,Trigger.OldMap);
     }
}


Test Class:

@istest(SeeAllData=false)
private class CountContacts_Test
{
    private static testmethod void validatetest()
    {
         Profile p = [SELECT Id FROM Profile WHERE Name='System Administrator']; 
         User u = new User(Alias = 'sample', Email='standarduser@testorg.com', 
         EmailEncodingKey='UTF-8', LastName='sampleLname', LanguageLocaleKey='en_US', 
         LocaleSidKey='en_US', ProfileId = p.Id, 
         TimeZoneSidKey='America/Los_Angeles', UserName='testnamesss@testorg.com');
         system.runAs(u)
         {
         
              Account  acn = new Account();
              acn.Name='test1';
                            
              Database.Insert(acn);
                                        
              Contact con = new Contact();
              con.AccountID=acn.ID;     
              con.LastName='test3';
                       
              Database.Insert(con); 
                           
              Contact oldcon=[select AccountID from Contact where ID=:con.ID];
              
              Database.Delete(oldcon); 
              
              Database.Update(acn);
        
         }
       }
   }

The code coveage is around  85%.

Thanks
Sonali verma