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
Oliver Jones RajkumarOliver Jones Rajkumar 

Help on apex triggers for Bulk insert

Hi All,

I have the following code that checks duplicate for email and phone for contact records. For instance, R1 contact record can have phone, email as "123","a@abc.com" and R2 contact record can have "123","b@abc.com". Error thrown only when BOTH EMAIL, PHONE matches existing records.
This works for single record insert/update, but when bulk insert through data import wizard if I insert 10 records with same email,phone values, 9 records are inserted with duplicate values, with error on the 10th record. 

Need help.
Thanks.

-----------------------------

trigger ContactTrigger_AT on Contact (before insert, before update)
{
    Set<String> setEmail = new set<String>();
    Set<String> setPhone = new set<String>();
    Set<String> setExistingEmail = new set<String>();
    Set<String> setExistingPhone = new set<String>();
    
    for(Contact con : Trigger.new)
    {
        setEmail.add(con.email);
        setPhone.add(con.Phone);
    }
    for(Contact con : [SELECT Phone,Email FROM contact WHERE email in : setEmail AND phone in : setPhone])
    {
        setExistingEmail.add(con.email);
        setExistingPhone.add(con.Phone);
    }
       if(Trigger.isInsert||Trigger.isUpdate)
    for(Contact a:trigger.new)
     {
        if(setExistingEmail.contains(a.email) && setExistingPhone.contains(a.Phone))
        {
            a.adderror('This Phone and email already exists');
        }
    }

}
Best Answer chosen by Oliver Jones Rajkumar
Oliver Jones RajkumarOliver Jones Rajkumar
Here is the working code
----------------------------------------------------------------


trigger ContactTrigger_AT on Contact (before insert, before update)
{
    List<Contact> allcon = [SELECT Email,Phone FROM Contact];
    Map<String, Contact> emlMap = new Map<String, Contact>();
    Map<String, Contact> phnMap = new Map<String, Contact>();
    for (Contact thiscon : System.Trigger.new)
    {
        if (Trigger.isInsert || (thiscon.Email != Trigger.oldMap.get(thiscon.Id).Email && thiscon.Phone != Trigger.oldMap.get(thiscon.Id).Phone))
        {
            if (emlMap.containsKey(thiscon.Email) && phnMap.containsKey(thiscon.Phone))
            {
                thiscon.addError('Another new Contact has the same email address with the same phone number.');
            }else
            {
                emlMap.put(thiscon.Email, thiscon);
                phnMap.put(thiscon.Phone, thiscon);
            }
           }
    }
    for (Contact eachcon : [SELECT Phone,Email FROM Contact WHERE Email IN :emlMap.KeySet() AND Phone IN :phnMap.KeySet()])
    {
        for(Integer i=0; i<allcon.size();i++)
        {
            if(eachcon.Phone == allcon[i].Phone && eachcon.Email == allcon[i].Email )
            eachcon.addError('A Contact with this email and Phone already exists.');
        }
    }
}

All Answers

Shobit GuptaShobit Gupta
Please write the last If as 
if(setExistingEmail.contains(a.email) || setExistingPhone.contains(a.Phone))

Let me know if it works.

-Shobit
Karthi XaviKarthi Xavi
Hello Oliver,
You have missed to Open and close curly braces on If condition Block, if you dont specify them it checks for the very next line alone, since it is bulk process you have to add the braces, Use the below code.
trigger ContactTrigger_AT on Contact (before insert, before update)
{
    Set<String> setEmail = new set<String>();
    Set<String> setPhone = new set<String>();
    Set<String> setExistingEmail = new set<String>();
    Set<String> setExistingPhone = new set<String>();
    
    for(Contact con : Trigger.new)
    {
        setEmail.add(con.email);
        setPhone.add(con.Phone);
    }
    for(Contact con : [SELECT Phone,Email FROM contact WHERE email in : setEmail AND phone in : setPhone])
    {
        setExistingEmail.add(con.email);
        setExistingPhone.add(con.Phone);
    }
    if(Trigger.isInsert||Trigger.isUpdate) {
    for(Contact a:trigger.new)
     {
        if(setExistingEmail.contains(a.email) && setExistingPhone.contains(a.Phone))
        {
            a.adderror('This Phone and email already exists');
        }
    }
 }
}



Thanks.
Shiva RajendranShiva Rajendran
Hello Oliver,
I understood from your question that on contact records combination of email and phone should be unique . If so ,use this code . Contain is checking in the whole ,your logic doesnt check only the unique combination
Use this code for correct logic
List<String> allListExistingEmail = new List<String>();
​allListExistingEmail .addAll(setExistingEmail);
List<String> allListExistingPhone = new List<String>();
allListExistingPhone .addAll(setExistingPhone);
 
  if(Trigger.isInsert||Trigger.isUpdate)
{
   for(Contact a:trigger.new)
     {
        if(allListExistingEmail .indexOf(a.email) !=-1 || allListExistingPhone .indexOf(a.phone) !=-1)
        {
               Integer location=-1;
               location=allListExistingPhone.indexOf(a.email);
               if(location!=-1)
             {
                       if( allListExistingPhone .get(location)==a.phone)
                        {
                           a.adderror('This Phone and email already exists');

                        }
                     else
                       {
                           

                       }
              }
          }
      }
  }
 
brahmaji tammanabrahmaji tammana
Hi Oliver,

I don't think your code will throw any error on 10th record.
Basically your code is verifying the import data with existing data in Saleforce. If the same record is found, it will throw an error/it will not be imported. 

But if your import data contains duplicates, your current code will not handle it. You need to cleanse the data before you import.

Hope it helps. !!

Thanks
Brahma

 
Oliver Jones RajkumarOliver Jones Rajkumar
Hi Shobit Gupta, as per my requirement, I have to check the uniqueness of combination of Email and Phone. 
Thanks.
Oliver Jones RajkumarOliver Jones Rajkumar
Hi Karthikeyan, even if use the CURLY BRACES, I'm still getting the same error.
User-added image
User-added image
Thanks.
Oliver Jones RajkumarOliver Jones Rajkumar
Hi Shiva, I tried your code, but I'm getting an error as "Method does not exist or incorrect signature: [List<String>].indexOf(String)" where indexOf() function is used.
hanks.
Shiva RajendranShiva Rajendran
Hi Oliver , 
Just now verified that there is no indexOf field in salesforce List.It is available only in string.
So what i advice you is create a custom function


int indexOf(List<String> oo,String ob)
{
      int myindex=-1;
     for(Integer i=0;i<oo.size();i++)
    {
         if(oo.get(i).equals(ob))
                 {

                      myindex=i;
                     break;
              }
    }
   return myindex;

}


replace allListExistingEmail .indexOf(a.email) with  indexOf(allListExistingEmail ,a.email)

Thanks and Regards,
Shiva RV
Oliver Jones RajkumarOliver Jones Rajkumar
Here is the working code
----------------------------------------------------------------


trigger ContactTrigger_AT on Contact (before insert, before update)
{
    List<Contact> allcon = [SELECT Email,Phone FROM Contact];
    Map<String, Contact> emlMap = new Map<String, Contact>();
    Map<String, Contact> phnMap = new Map<String, Contact>();
    for (Contact thiscon : System.Trigger.new)
    {
        if (Trigger.isInsert || (thiscon.Email != Trigger.oldMap.get(thiscon.Id).Email && thiscon.Phone != Trigger.oldMap.get(thiscon.Id).Phone))
        {
            if (emlMap.containsKey(thiscon.Email) && phnMap.containsKey(thiscon.Phone))
            {
                thiscon.addError('Another new Contact has the same email address with the same phone number.');
            }else
            {
                emlMap.put(thiscon.Email, thiscon);
                phnMap.put(thiscon.Phone, thiscon);
            }
           }
    }
    for (Contact eachcon : [SELECT Phone,Email FROM Contact WHERE Email IN :emlMap.KeySet() AND Phone IN :phnMap.KeySet()])
    {
        for(Integer i=0; i<allcon.size();i++)
        {
            if(eachcon.Phone == allcon[i].Phone && eachcon.Email == allcon[i].Email )
            eachcon.addError('A Contact with this email and Phone already exists.');
        }
    }
}
This was selected as the best answer