Deduping Or Deduplication Trigger In Salesforce

Introduction

We can have duplicate records in our Salesforce org which creates an issue that needed to be solved. Like, we have a single lead with two duplicate records in the Lead object and both the records are assigned to different people, then both will contact and try to follow up with the lead twice which is irrelevant and can impact the business.

To solve this, we have built-in configuration features like Matching Rules and Duplicate Rules.

What is a deduping or Deduplication trigger?

Now to prevent duplicate records from entering our org, we can make use of trigger.

In the Deduplication trigger, we write a trigger to prevent the users from creating duplicate records in org.

For e.g. Write a trigger to prevent the creation of duplicate Account records when the Account already exists with the same name.

How to write a deduping trigger in SalesForce?

Here we will take the same example which is mentioned above.

trigger AccountDuplication on Account (before insert, before update) {
Set<String> accNames = new Set<String>();
for(Account acc : Trigger.new){
accNames.add(acc.Name);
}


List<Account> acc = [SELECT Id, Name FROM Account WHERE Name IN :accNames];


Map<String, Account> accMap = new Map<String, Account>();
for(Account acc : acc){
accMap.put(acc.Name, acc);
}
if(accMap.size() > 0){
for(Account ac : Trigger.new){
if(ac.Name != null && Trigger.isInsert || (Trigger.isUpdate && Trigger.oldMap.get(ac.Id).Name != ac.Name)){
if(accMap.containsKey(ac.Name)){
ac.Name.addError('Duplicate Name in Account');
}
}
}
}
}

 

Above is the complete code which we will try to understand by breaking it into pieces.

trigger AccountDuplication on Account (before insert, before the update)

 

We have used before insert and before update DML statements since we can insert the duplicate records or update the existing records to duplicate. We need to check for both cases.

Set<String> accNames = new Set<String>();
for(Account acc : Trigger.new){
accNames.add(acc.Name);
}

 

Now, the names of the records we are trying to insert or update get stored in the Set collection

List<Account> acc = [SELECT Id, Name FROM Account WHERE Name IN :accNames];
Map<String, Account> accMap = new Map<String, Account>();
for(Account acc : acc){
accMap.put(acc.Name, acc);
}

 

OR

Map<String, Account> accMap = new Map<String, Account>([SELECT Id, Name FROM Account WHERE Name IN :accNames]);

 

Here, we are querying those existing account records where the name has the same value as that of records entered or updated by the user and storing it into the map in which the key is Name (string) and the value is complete Account record.

if(accMap.size() > 0){
for(Account ac : Trigger.new){
if(ac.Name != null && Trigger.isInsert || (Trigger.isUpdate && Trigger.oldMap.get(ac.Id).Name != ac.Name)){
if(accMap.containsKey(ac.Name)){
ac.Name.addError('Duplicate Name in Account');
}
}
}
}

 

Here, we are checking if the size of our map is not null, then we need to do one more check for updation in which we are identifying if the name field new value is the same as that of old. When this condition is true, throwing an error with addError() will prevent the creation or updation of duplicate records.

How to write a test class for the deduping triggers?

Example: Write a test class for a trigger in which while creating records, prevent the creation of duplicate Account records when the Account already exists with the same name in org.

@isTest
public class TestAccountDuplication {
@isTest
static void testDup(){
String addErr;
Account accDup = new Account(Name = 'Test Account Class');
List<Account> accList = [SELECT Id, Name FROM Account WHERE Name = 'Test Account Class'];
if(accList.size() > 0){
addErr ='Duplicate Name in Account';
}
else
{
System.assertEquals(0, accList.size());
//Insert the record
insert accDup;
}
}
}

 

Test data is transient, which means it is not committed to the database. @isTest annotation is used to define the classes and methods as test class and test method.

The return type of test method is void as it doesn’t return anything.

Looking at the above example, we have created an instance of Account with its NAME. Then, we are checking, if that name already exists in our Account object records or not by querying the account object. If a record with the same name exists, we are throwing an error, otherwise inserting the record.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.