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
Sameer VitsSameer Vits 

check for existing contacts using email address

We have a requirement where we want to check if contact exists using email address custom field. If contact exists then we just want to update incoming information. If contact doesn't exists then it should create a new contact. Also, is apex a better solution or workflows?
Best Answer chosen by Sameer Vits
Abdul KhatriAbdul Khatri
Here is I can think of handling in your situation.

The concept here is, I kept the very recent record that came in and delete all the old ones keeping the perspective the recent record with latest information. Let me know if that works
 
trigger ContactManageByEmail on Contact (after insert) {

    Set<String> emailSet = new Set<String>();
    List<Contact> contactToDeleteList = new List<Contact>();
    
    for(Contact contact : trigger.new)
    {
        emailSet.add(contact.Email);
    }
        
    AggregateResult[] groupedResults = [SELECT Count(Id), Email FROM Contact WHERE Email = :emailSet GROUP BY Email HAVING COUNT(Id) > 1 ];
    
    emailSet.clear();
    for (AggregateResult ar : groupedResults)  
    {   
        emailSet.add((String)ar.get('Email'));
    } 
    
    if(emailSet.isEmpty()) return;
    
    List<Contact> contactList = [SELECT Id, Email FROM Contact WHERE Email IN :emailSet ORDER BY Email, CreatedDate DESC];   
    emailSet.clear();
    for (Contact contact : contactList) {
    
        if(!emailSet.contains(contact.Email))
        {
            emailSet.add(contact.Email);
            continue;
        }
        
        contactToDeleteList.add(contact);
    }

    if(!contactToDeleteList.isEmpty())
        delete contactToDeleteList;
}

 

All Answers

Maharajan CMaharajan C
Hi Sameer,

Apex is the better Solution it's not possible using WF.

Below trigger is used for your scenario here am using the Standard Email field so use your custom field instead std field.

trigger UpsertDuplicate on Contact (After insert) {
Set<Id> DuplicateConToDelId = new Set<Id>();
Map<String,Contact> ConMap = new Map<String,Contact>(); 
List<Contact> ContacttoUpdate = new List<Contact>();  
List<Contact> DuplicateContactestoDel = new List<Contact>();    

for(Contact con:Trigger.new)
    {
        If(con.Email != null)
        ConMap.put(con.Email,con);    
    }
    
List<Contact> ExistingContact = new List<Contact>();
ExistingContact = [Select Id,FirstName,LastName,Email,Phone,MobilePhone from Contact where Email IN : ConMap.keySet()];    
    
    if(ExistingContact.size() > 0)
    {
        for(Contact newcon : Trigger.New)
        {
            for(Contact excon : ExistingContact)
            {
                If(excon.Email == newcon.Email && ConMap.containsKey(excon.Email))
                {     
                excon.FirstName = newcon.FirstName;    
                excon.LastName = newcon.LastName;
                excon.Phone = newcon.Phone;
                excon.MobilePhone = newcon.MobilePhone;
                ContacttoUpdate.add(excon);
                DuplicateConToDelId.add(newcon.Id);    
                }
                
            }
        }
    }
    
    If(ContacttoUpdate.size() > 0)
    {
      Update ContacttoUpdate;  
    }
    
    If(DuplicateConToDelId.size() > 0)
    {
        DuplicateContactestoDel = [Select Id,Name from Contact where Id IN :  DuplicateConToDelId];
        If(DuplicateContactestoDel.size() > 0)
        Delete DuplicateContactestoDel;
    }
}

Can you please Let me know if it helps or not!!!

If it helps don't forget to mark this as a best answer!!!


Thanks,
Raj
Sameer VitsSameer Vits
@Raj - The contact was created but then it got deleted the very next second. I don't know why. 
Maharajan CMaharajan C
Did you want to keep the inserted record and also update the existing record with the same email?    If you want to keep the new inserted record then remove the below lines from code.      
    If(DuplicateConToDelId.size() > 0)
    {
        DuplicateContactestoDel = [Select Id,Name from Contact where Id IN :  DuplicateConToDelId];
        If(DuplicateContactestoDel.size() > 0)
        Delete DuplicateContactestoDel;
    }

Thanks.  
Raj
Sameer VitsSameer Vits
We want to keep new records but if they already exists in the system then instead of creating another record we just want to update existing record. It's like if there is no contact by that email then create new record. If there is a contact by that email then update contact's information.
Sameer VitsSameer Vits
@Raj - Removing those lines as you suggested creates two different records with same email. 
Abdul KhatriAbdul Khatri
The best design for your requirement is to prevent duplicate using the below trigger.
 
trigger ContactPreventDupEmail on Contact (before insert, before update) {
    
    Map<String, Contact> emailMap = new Map<String, Contact>();
        
    for(Contact contact : trigger.new) {
        
        if(trigger.isInsert) {            
            emailMap.put(contact.Email, contact);
        }
        
        if(trigger.isUpdate && trigger.oldMap.get(contact.Id).Email != contact.Email) {
            emailMap.put(contact.Email, contact);            
        }
    }
    
    if(emailMap.isEmpty()) return;

    List<Contact> existingContactList = [Select Id, Email FROM Contact Where Email IN :emailMap.keySet()];
    
    if(existingContactList == null) return;
    
    for(Contact contactRec : existingContactList) {
        emailMap.get(contactRec.Email).addError('Email already Exist');
    }

}

 
Sameer VitsSameer Vits
@Abdul The reason for to allow duplicates is because we have users doing the form on website. So if they do it multiple times there information won't come in to system because of this trigger. Does that make sense? That's why I am trying to work on a trigger where if contact doesn't exists then they get created as new contacts, and if they exists then it's just their information gets updated. (to check is using their email address)
Abdul KhatriAbdul Khatri
Great. Now the question is how thia form is interacting with Salesforce. I mean how the information is flowing inside Salesforce?
Sameer VitsSameer Vits
@Abdul - it is using Gravity Form CRM salesforce connector that creates contacts for those who do the form on the website.
Abdul KhatriAbdul Khatri
Here is I can think of handling in your situation.

The concept here is, I kept the very recent record that came in and delete all the old ones keeping the perspective the recent record with latest information. Let me know if that works
 
trigger ContactManageByEmail on Contact (after insert) {

    Set<String> emailSet = new Set<String>();
    List<Contact> contactToDeleteList = new List<Contact>();
    
    for(Contact contact : trigger.new)
    {
        emailSet.add(contact.Email);
    }
        
    AggregateResult[] groupedResults = [SELECT Count(Id), Email FROM Contact WHERE Email = :emailSet GROUP BY Email HAVING COUNT(Id) > 1 ];
    
    emailSet.clear();
    for (AggregateResult ar : groupedResults)  
    {   
        emailSet.add((String)ar.get('Email'));
    } 
    
    if(emailSet.isEmpty()) return;
    
    List<Contact> contactList = [SELECT Id, Email FROM Contact WHERE Email IN :emailSet ORDER BY Email, CreatedDate DESC];   
    emailSet.clear();
    for (Contact contact : contactList) {
    
        if(!emailSet.contains(contact.Email))
        {
            emailSet.add(contact.Email);
            continue;
        }
        
        contactToDeleteList.add(contact);
    }

    if(!contactToDeleteList.isEmpty())
        delete contactToDeleteList;
}

 
This was selected as the best answer
Sameer VitsSameer Vits
@Abdul - Thank you so much. It's working really great. 
Rahul Gupta 268Rahul Gupta 268
@Abdul: The above trigger posted by you will work for me but instead on throwing an error, I would like the old contact to be updated with new contacts Information.
David JostDavid Jost
How can I do that in rest API instead of APEX?