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
WikWik 

Trigger to Prevent Duplicate Contact on Accounts

Hi ,

I have written a piece of trigger , trying to prevent duplicate contacts on an Account:

trigger PreventDuplicateContact on Contact (before insert, before update){

Set<id> accid = new Set<id>();
for (Contact c : Trigger.new)
accid.add(c.Accountid);

Map<Id,list<contact>> AccEmails = new Map<Id,list<contact>>();
Map<Id, Contact> cont = new Map<Id, Contact> ([Select Email from Contact where Id in:accid]);

for (Contact c : Trigger.new){
if ((contact.Email !=null) && (System.Trigger.isInsert ||(contact.Email != System.Trigger.oldMap.get(contact.Id).Email))){
if ( cont.containsKey(contact.Email)){
Contact co = cont.get(contact.Email);
if(co.accountid==contact.accountid){
contact.Email.addError('Another new contact has the '+'same email address.');
            }else{
                cont.put(contact.Email,c);
     }}
       }
    }
    for (Contact c : [SELECT Email FROM Contact WHERE Email IN :cont.KeySet()]){
        Contact newContact = cont.get(c.Email);
        newContact.Email.addError('A Contact with this email '+'address already exists.');
   }
}

But this is not working as expected. Please help me get it modified
Vatsal KothariVatsal Kothari
Hi,

Please replace contact with c inside for each loop i.e (for (Contact c : Trigger.new){ ..... }) replace all "contact" with "c".

If this solves your problem, kindly mark it as the best answer.

Thanks,
Vatsal

Vatsal KothariVatsal Kothari
Replace your query 

Map<Id, Contact> cont = new Map<Id, Contact> ([Select Email from Contact where Id in:accid]);

with below query

Map<Id, Contact> cont = new Map<Id, Contact> ([Select Email from Contact where AccountId in:accid]);


Vatsal KothariVatsal Kothari
Hey Wik,

Here is the updated Code:

trigger PreventDuplicateContact on Contact (before insert,before update) {
    if(trigger.isInsert || trigger.isUpdate)
    {
        Map<String, Contact> emailMap = new Map<String, Contact>();
        
        for (Contact c : System.Trigger.new) 
        {
            if ((c.Email != null) && (System.Trigger.isInsert || (c.Email != System.Trigger.oldMap.get(c.Id).Email))) {
                if(emailMap.containsKey(c.Email)) {
                    c.Email.addError('Contact has the same Email address');
                }
                else {
                    emailMap.put(c.Email, c);
                }
            }            
            
        }
    
        for (Contact c : [SELECT Email FROM Contact WHERE Email IN :emailMap.KeySet()]) {
            Contact c1 = emailMap.get(c.Email);            
            c1.Email.addError('Contact with this email address already exists');
        }
    
    }
   
}
If this solves your problem, kindly mark it as the best answer.

Thanks,
Vatsal

WikWik

The code that you have provided works on an org wide basis, i am looking to restrict duplicate Contacts on Account basis.

If the Account is not same then in that case the duplicates should be allowed.

Any suggestions for this?

David "w00t!" LiuDavid "w00t!" Liu
You can restrict dupes (within an account or org wide) without any code as well:
  1. Create a "Duplicate Check" text field and make it unique case sensitive
  2. Have a workflow populate the above field with either AccountId + Email or simply Email if you want org wide dupe prevention
Should take no more than 5 minutes!
Vatsal KothariVatsal Kothari
Hi,

Here is the updated code:

trigger PreventDuplicateContact on Contact (before insert,before update) {
    
    if(trigger.isInsert || trigger.isUpdate)
    {
        Map<Id,List<Contact>> accMap = new Map<Id,List<Contact>>();
        List<Contact> contactList;
        
        for(Contact c: [Select Id,Email,accountId from Contact]){
            if(accMap.containsKey(c.accountId)){   
                accMap.get(c.accountId).add(c);
            }
            else{
                contactList = new List<Contact>();
                contactList.add(c);
                accMap.put(c.accountId,contactList);
            }       
        }
        
        for (Contact c : Trigger.new) 
        {
            if(accMap.containsKey(c.accountId)){
                for(Contact con : accMap.get(c.accountId)){
                    if(c.Email == con.Email){
                        c.Email.addError('Contact with this email address already exists');
                    }
                }
            }
        }
    }
}
If this solves your problem, kindly mark it as the best answer.

Thanks,
Vatsal

WikWik
David: Your solution works perfect but I wanted to add the Error message of my own choice is it possible?
Nitin SharmaNitin Sharma
trigger RestrictContacts on Contact (before insert) {
List <Account> acclist = new List<Account>([SELECT Id, Name from Account]);
 List <Contact> conlist = new List<Contact>([SELECT Email,AccountId from Contact Where AccountId IN :acclist]);
    for(Contact con: Trigger.new){
        for(Contact c: conlist){
            if(con.Email == c.Email){
                con.Email.addError('Contact with this email address already exists');
            }
        
        }
    }  
}
Tripti LakharaTripti Lakhara
Please help me to solve this trigger.
1. Create field isDuplicate on Contact
2. Mark this flag as duplicate on insert/update if any other existing contact has same website.
3. Mobile cannot be duplicate for same account. Create trigger based validation.
Shubham Gupta 298Shubham Gupta 298
Hello Vatsal,

could you please tell me the meaning of this line(line no. 10) in your code - "accMap.get(c.accountId).add(c);".
Your code is perfectly working but, i am new in development so please tell me or write this line in another way(without shortform) so that i can understand.