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
HARSHIL U PARIKHHARSHIL U PARIKH 

Counting Unique Email of Contacts On Account via Trigger. Trigger works for individual record but when Mass Updated it behaves unexpected..

Hello Developes!

I have a trigger which counts number of unique email address contacts on Account.
Trigger Code:
Trigger UniqueEmailCons on Contact(After Insert, After Update, After Delete, After Undelete){
    
    List<ID> accountIds = New List<ID>();
    
    If(Trigger.IsInsert || Trigger.IsUpdate || Trigger.IsUndelete){
        For(Contact con : Trigger.New){
            accountIds.add(con.AccountID);
        }
    }
    If(Trigger.IsDelete){
        For(Contact con : Trigger.old){
            accountIds.add(con.AccountID);
        }
    }
    
    Set<String> UniqueEmails = New Set<String>();
    List<Account> AccountListToUpdate = New List<Account>();
    
    For(Account act : [Select ID, Unique_Email_Contacts__c, (Select Id, Email FROM Contacts) FROM Account WHERE Id = :accountIds])
    {
        
        act.Unique_Email_Contacts__c = 0;
        
        For(Contact c : act.contacts)
        {
            If(C.Email != null)
            {
                UniqueEmails.add(C.Email);
            }
        }
        act.Unique_Email_Contacts__c = UniqueEmails.size();
        AccountListToUpdate.add(act);
        
    }
    try{
        update AccountListToUpdate;
    }
    Catch(Exception e){
        System.debug('Exception thrown is::: ' + e.getMessage());
    }
}
Trigger works fine for individual getting inserted, updated, deleted record etc.. but when I update all the contacts togather then all the accounts in org (let's say 18 ) of them gets updated as follow:

Account - 1 gets updated with values of Unique_Email_Contacts__c as 1
Account - 2 gets updated with values of Unique_Email_Contacts__c as 2
Account - 3 gets updated with values of Unique_Email_Contacts__c as 3 etc...


Thank you for the help!

 
Best Answer chosen by HARSHIL U PARIKH
Vivian Charlie 1208Vivian Charlie 1208

Hi Govind,

 

Try this

 

set<Id> setAccountId = new set<Id>();
for(Contact objC : trigger.new){
	if(objC.AccountId != null){
		setAccountId.add(objC.AccountId);
	}
}

list<Account> lstA = new list<Account>();
map<Id,Integer> mapAccId_Count = new map<Id,Integer>();
for(Account objA : [Select Id, CustomField__c, 
						(Select Id, Email from Contacts) 
					from Account where Id IN : setAccountId]){
	set<String> setUnique = new set<String>();
	for(Contact objC : objA.Contacts){
		setUnique.add(objC.Email);
	}
	objA.CustomField__c = setUnique.size();
	lstA.add(objA);
}
if(!lstA.isEmpty(){
	update lstA;
}


Thanks

Vivian

All Answers

Vivian Charlie 1208Vivian Charlie 1208

Hi Govind,

 

Try this

 

set<Id> setAccountId = new set<Id>();
for(Contact objC : trigger.new){
	if(objC.AccountId != null){
		setAccountId.add(objC.AccountId);
	}
}

list<Account> lstA = new list<Account>();
map<Id,Integer> mapAccId_Count = new map<Id,Integer>();
for(Account objA : [Select Id, CustomField__c, 
						(Select Id, Email from Contacts) 
					from Account where Id IN : setAccountId]){
	set<String> setUnique = new set<String>();
	for(Contact objC : objA.Contacts){
		setUnique.add(objC.Email);
	}
	objA.CustomField__c = setUnique.size();
	lstA.add(objA);
}
if(!lstA.isEmpty(){
	update lstA;
}


Thanks

Vivian

This was selected as the best answer
HARSHIL U PARIKHHARSHIL U PARIKH
So basically I need to create
Set<String> UniqueEmails = New Set<String>();
inside the for loop. This way when its time to add uniqueEmails in set then we will get fresh set with nothing in it unlike otherwise we were getting set with some pre-defined values/lements in it. Is this correct? or if you can share your ideas a little.. Thank you very much Vivan and guess what... trigger is working fine!!
 
Vivian Charlie 1208Vivian Charlie 1208
Govind, When the set is outside the for loop it will check and add the unique email addresses across the entire transaction. When the set is inside the for loop it checks for duplicate emails against individual account records so you have the actual values and the count is not carried across from one account to another.
HARSHIL U PARIKHHARSHIL U PARIKH
I think I am getting it.. Thank you!