Вы находитесь на странице: 1из 17

6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the

e 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 1/17
SALESFORCE CODING LESSONS FOR THE 99%
Finally, Apex tutorials for point-and-click admins! Written by a self-taught Google engineer.
Example: How to write a deduping trigger
for leads and contacts
O C T O B E R 1 9 , 2 0 1 3
Preface This post is part of the Write Your First Intermediate Trigger series.
Ok guys lets write a trigger that will prevent a user from creating a lead that already exists as a contact!
Well use the lead/contacts email address to detect duplicates.
A brilliant person once told me that even the most complicated code can be broken down into tiny,
individual steps that are easy to implement. Lets see what our steps are:
1. Lead is created or updated
2. Lead has an email address
3. Try to find a matching Contact based on email address (using SOQL!)
4. If a match is found, give the user an error
5. If a match is not found, do nothing
Now, try to match the steps above with the code! Each step should match to at least one line of code.
Step 5 is the exception, but bonus points if you know where itd go otherwise!
trigger FindDupes on Lead (before insert, before update) {
for (Lead myLead : Trigger.new) {
if (myLead.Email != null) {
List<Contact> dupes = [SELECT Id FROM Contact
WHERE Email = :myLead.Email];
if (dupes.size() > 0) {
String errorMessage = 'Duplicate contact found! ';
errorMessage += 'Record ID is ' + dupes[0].Id;
myLead.addError(errorMessage);
}
}
}
BEGINNER TUTORIALS LOGIN TO SFDC99 HOW TO READ CODE ABOUT ME Follow @dvdkliu

for post updates!
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 2/17
Mithun Sapui
J UNE 9, 2014 @ 12: 12 PM
Hi David
I have a strange issue here . I have written the below deduping trigger based on your webinar. I have
defined the Dupe contact fields as a text field and have a validation rule on it. I am getting the error
while insert/update with a duplicate email id, but the value of the Id field is not getting populated in the
Dupe Contact field. What am I missing here ? (So, I am getting a validation error on the Dupe Contact
field but the field itself is blank)
trigger DetectDupes on Contact (before update, before insert) {
for (Contact l : Trigger.new) {
if (l.Email != null) {
String contactEmail = l.Email;
list dupeContacts = [Select Email from Contact
where Email = :contactEmail];
if (dupeContacts.size() > 0) {
l.Dupe_contact__c = dupeContacts[0].Id;
} else {
l.Dupe_contact__c = null;
}
} else {
l.Dupe_contact__c = null;
}
}
}
}
And in case youve forgotten
How to read code
Where to write code in Salesforce
Login to Sfdc99 to see this in action!
Next post: An extended look at our deduping trigger!
33 Comments
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 3/17
Mithun
J UNE 11, 2014 @ 7: 20 PM
Thanks so much, David and Viru. I will do it that way.
Davi d Li u
J UNE 10, 2014 @ 6: 46 PM
Great one Viru, very close! If this was an after trigger you d be spot on!
Since it s a before trigger there is an implied update call automatically at
the end of the trigger. It literally means before update !
It s best if you don t add the Dupe_Contact__c field to the layout and simply
have the error message up on the top of the page. Having the field there
doesn t add any value to the user or the admin. But you re right that the
email address won t show on that field if the validation rule catches it!
Repl y
Viru
J UNE 10, 2014 @ 2: 20 AM
Hello Mithun Sapui,
i think the Dupe_contact__c field is empty because in trigger the record is not committed till you
use DML operation like update or insert.
this trigger work fine but when you assign I.Dupe_contact__c = dupeContacts[0].Id itll
assigned but not committed thats why your text field is still empty when record is duplicated.
Am i right David ?
Reply
Reply
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 4/17
Reply
Davi d Li u
J UNE 2, 2014 @ 7: 58 PM
hahaha awesome, great observation! I cover how to do this in chapter 5!
Repl y
Sanjay
J UNE 2, 2014 @ 2: 10 PM
Hi David.
I think ,it is not a good option to write SOQL inside loop. So I modified it. Let me know ,is it right?
trigger DuplicateTrigger on Lead (before insert , before update) {
List leadEmail= new List();
for(Lead l:Trigger.new){
leadEmail.add(l.Email);
}
Integer dupContact=[select count() from Contact where Email=:leadEmail];
for(Lead l:Trigger.new){
if(l.Email!=null){
if(dupContact>0){
l.addError(Duplicate lead record );
}
}
}
}
Reply
Amitabh Sharma
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 5/17
Davi d Li u
MAY 6, 2014 @ 10: 59 PM
Well done Amitabh!!! Way to hang in there!
Repl y
MAY 5, 2014 @ 9: 51 AM
Hi David, this is in continuation to my previous reply.
I modified the code with the following to check only when the lead status is not
closed converted as this is the status that every lead gets on conversion.
This has fixed the problem for now.
if(leadforDupe.Email != null && leadforDupe.Status Closed converted )
Reply
Amitabh Sharma
MAY 5, 2014 @ 9: 34 AM
Hi David, thanks for all the help, I have moved till chapter 7 successfully.
However when i revisited the code on chapter 4, this is working fine if i update an existing Lead record.
When I create a new Lead and try to convert it , again the validation is hit :-(. as the converted contact
will have the same email as that of the lead.
thanks in advance.
/*
not lead a new lead create if the contact exists.
Since leads and contacts are not related
*/
trigger SFDC99_Chap4_LeadDedupe on Lead (before insert, before update) {
for(Lead leadforDupe :Trigger.new){
//checking if the lead has an email
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 6/17
if(leadforDupe.Email != null){
//checking the values of the contacts for emails
List dupe = [SELECT Id,LastName,email FROM Contact where email =: leadforDupe.email];
//if email
if(dupe.size() > 0){
leadforDupe.addError(Duplicate value on + dupe[0].id);
}
}
}
}
Reply
Vaishali Singh
APRIL 29, 2014 @ 9: 29 AM
Hi David,
I know i have been bugging you with my questions. But i am really enjoying coding:
another one for you: I have tried a little different not sure if this is right. I have done this for contact as i
am trying on my developer org and all the licences are consumed so instead of using lead i have used
contact.
But it is giving error on the user page when i am trying to deactivate the user:
Review all error messages below to correct your data.
Apex trigger reassignUser caused an unexpected exception, contact your administrator: reassignUser:
execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with
id 0039000000VUI8GAAX; first error: MIXED_DML_OPERATION, DML operation on setup object is not
permitted after you have updated a non-setup object (or vice versa): Contact, original object: User: []:
Trigger.reassignUser: line 25, column 1

I am clueless what this erro is talkinng about.


code snippet:
trigger reassignUser on User (after update)
{
Set userIds = new Set();
List conList= new List();
List oppList= new List();
List updateCon = new List();
for(User loopUser:trigger.new)
{
if(loopUser.IsActive==false)
{
userIds.add(loopUser.id);
}
}
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 7/17
Davi d Li u
APRIL 29, 2014 @ 8: 24 PM
This one s a tough one and can go many directions try Googling the error message
and see where that takes you!
Repl y
system.debug(@@ UserIds @@+userIds);
conList=[Select id,OwnerId from Contact where OwnerId in: userIds];
system.debug(contact list+conList);
User sysAdmin= [Select id, name from User where name='Poornima S'];
system.debug(@@system admin @@+sysAdmin);
for(Contact loopCon:conList)
{
loopCon.OwnerId=sysAdmin.id;
system.debug(@@ loop contact @@+loopCon);
updateCon.add(loopCon);
}
update updateCon ;
system.debug(@@ contact list @@+updateCon );
}
Thanks
Reply
Vaishali Singh
APRIL 29, 2014 @ 7: 30 AM
Hi David,
Really thanks for starting this blog. I m loving it :)
I used this way of doing the dupeblocker code since i did not want to query inside the for loop as it will
query every time the loop is iterated . But i ended up using iterative for loop, which i suppose may be a
problem in bulk data. Please suggest how this can be written in a better way.
trigger findDupes on Lead (before insert, before update)
{
List conList = new List();
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 8/17
Vaishali Singh
APRIL 30, 2014 @ 9: 05 AM
Bravo!! Chapter 5 is amazing. I always had a problem in getting this map thing worked
out. But now i have got the clear understanding on this.
Davi d Li u
APRIL 29, 2014 @ 8: 22 PM
Great call!
You definitely need to check out Chapter 5, as it s entirely dedicated to answering
this question you have!
Basically, you need to learn the proper way to bulkify =)
David
Repl y
conList= [Select email,id from Contact];
for(Lead loopLead: Trigger.new)
{
if(loopLead.email!= null)
{
for(Contact loopCon:conList)
{
if(loopLead.email==loopCon.email)
{
String errorMessage = Duplicate contact found! ;
errorMessage += Record ID is + loopCon.Id;
loopLead.addError(errorMessage);
}
}
}
}
}
Cheers!!
Reply
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 9/17
Reply
Davi d Li u
APRIL 22, 2014 @ 9: 12 PM
A common trigger!
Try this:
1. Create a trigger on Tasks
2. Create a set of all Opportunities related to Tasks in your trigger
3. Do one SOQL query to get all Opportunities in #2 and their related tasks
http://www.sfdc99.com/2013/06/24/example-how-to-write-a-cross-object-soql-
query-part-2/
4. For each Opportunity, count the number of related tasks!
You can do it!!!!
But if you re lazy, you can just download this:
https://appexchange.salesforce.com/listingDetail?listingId=a0N30000009i3UpEAI
=)
Repl y
Mercy Fields
APRIL 22, 2014 @ 2: 22 PM
Hi David,
Thank you for your tutorials. I know nothing about coding, so your tutorials are easy to follow. I want to
create a trigger that calculates the # of activity per opportunity. The roll-up summary is very limited in
Salesforce and I think a trigger would give me the activity count. Please advise. Thanks in advance for
your help.
Reply
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 10/17
Davi d Li u
APRIL 21, 2014 @ 8: 27 PM
My pleasure!
The first line is getting a List of all Opportunities that have a specific owner. The
second line goes through each of these opps one by one, then changes their owner
to the owner s manager.
So if I own 5 opps and my manager on my user record is Sandeep, all 5 of my opps
will be changed to be owned by Sandeep!
Hope this helps!
David
Repl y
Sandeep Dharwar
APRIL 21, 2014 @ 12: 42 PM
Hi David,
Your explanations are crisp and amazing.Its like no other. I love the way you have structured content.
And you are doing such an amazing job not only helping beginners like me learn but also inspire them
which makes Salesforce coding such a joy to learn.I cant thank you enough.
I have a doubt, could you please make me understand these two lines of code
1)List userOpps = [select Id from opportunity
where ownerId = :u.id];
2)for(opportunity x:userOpps){x.ownerId = u.ManagerId;}
I understand that Contact and Account also follow the same pattern.
from Andreass post.
Thanks a Million
Sandeep
P.S Dav you are the best
Reply
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 11/17
Davi d Li u
APRIL 16, 2014 @ 10: 28 PM
Oh my goodness what a wonderful method! Thank you for showing me!
Repl y
Davi d Li u
MARCH 20, 2014 @ 8: 27 PM
What are you trying to do? =)
Repl y
Teja
APRIL 16, 2014 @ 1: 50 PM
Just to improve upon the great work, you can also use getLevenshteinDistance method to find similar
emails too, so for example you can take the string, strip out the domain(to reduce the Levenshteins
Distance) and see how many similar records are there with a Distance of 2-5 so you can calculate it for
user typos or different spelling combinations.
Reply
Andreas
MARCH 20, 2014 @ 3: 18 PM
oki doesnt work , mixed DML exception (setup / non setup object)
Reply
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 12/17
Davi d Li u
MARCH 16, 2014 @ 9: 26 PM
Excellent observation Tom!
I m building the user up at this point =) You ll want to zip to Chapter 5 for tutorials
on bulkifying code!
David
Repl y
Anonymous
MARCH 16, 2014 @ 9: 52 AM
Hi David,
Once again great site I am really enjoying your work; not just the lessons but the entire site
structure and how you have it tied in with WordPress slick stuff. I am impressed with your energy
level! Keep it going! :)
In regard to the code example above and to make sure that I am not misunderstanding things that I
thought I knew and continue to learn would you say that the SELECT query on the contacts should
not be inside the trigger.new loop? Would it be best to some how get a map of the contacts prior to the
trigger loop? Am I wrong or are you building us up to that and want to keep the lessons learned as
basic as possible?
I just want to make sure I am staying on the right track so I appreciate your feedback.
Tom B.
Reply
Rajesh Kumar
FEBRUARY 12, 2014 @ 3: 10 AM
But above trigger is not working in case of convert lead. So do you have any other way to implement
convert Lead also.
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 13/17
Davi d Li u
FEBRUARY 12, 2014 @ 7: 01 PM
This will work when the lead is inserted/updated so it runs before the lead
conversion, which is even better!!
Repl y
Davi d Li u
DECEMBER 7, 2013 @ 10: 51 AM
Here s another trigger to try:
Write a trigger that reassigns all of a User s leads, accounts, contacts, and
opportunities when he/she is deactivated!
David
Reply
Graham
DECEMBER 6, 2013 @ 6: 18 AM
Hi David,
Not sure if you received my last comment as it does not appear to have posted. I wanted to thank you
for providing the most easy to understand tutorials for beginners trying to learn apex. Please keep on
posting. Also, could you possibly send me some intermediate sample trigger exercises (like the
deduping one) so that I can try to create them? I would really appreciate it. I am getting to grips with
Apex at a phenomenal rate thanks to this site.
Thank you
Graham
Reply
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 14/17
Davi d Li u
DECEMBER 22, 2013 @ 10: 27 PM
Awesome stuff Keith, you are very close! This is incredibly impressive!
Keith Larsen
DECEMBER 20, 2013 @ 9: 11 AM
Hi David, you explanations are the best Ive ever seen, keep up the great work. I wrote
the trigger you suggested that that reassigns all of a Users leads, accounts, contacts,
and opportunities when he/she is deactivated and wanted you to see if I did it
correctly.
trigger ReassignUserRecs on User (after update) {
for (User u : trigger.new ){
If (u.isActive = true) {
List userLeads = [select Id from lead
where ownerId = :u.id];
List userContact = [select Id from contact
where ownerId = :u.id];
List userOpps = [select Id from opportunity
where ownerId = :u.id];
If (userLeads != null && userLeads.size() > 0){
for (Integer i = 0; i 0){
for (Integer i = 0; i 0){
for (Integer i = 0; i <= userOpps.size() -1; i++){
// reassign owner to sys admin
userOpps[i].ownerId = '00570000001LL9';
}
update userOpps;
}
}
}
}
Reply
Repl y
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 15/17
Andreas
MARCH 20, 2014 @ 3: 09 PM
Looks this better ? , but not bulkified
trigger ReassignUserRecs on User (after update) {
for (User u : trigger.new ){
If (!u.isActive) {
List userLeads = [select Id from lead
where ownerId = :u.id];
List userContact = [select Id from contact
where ownerId = :u.id];
List userOpps = [select Id from opportunity
where ownerId = :u.id];
List userAccount = [select Id from Account
where ownerId = :u.id];
for(Lead x:userLeads){x.ownerId = u.ManagerId;}
for(contact x:userContact){x.ownerId = u.ManagerId;}
for(opportunity x:userOpps){x.ownerId = u.ManagerId;}
for(Account x:userAccount){x.ownerId = u.ManagerId;}
update userLeads;
update userContact;
update userOpps;
update useraccount;
}
}
}
Here are some potential areas of improvement:
- I think there is a small error in that you run the trigger if a User is
active instead of inactive!
- This may be something wrong with the way comments work on this
site, but some of your code might be cut off. I m talking about the area
where you check if leads exists, then iterate across each to reassign
them. Ditto for contacts as well! Try re-pasting those lines and I ll let
you know if they look good.
David
Repl y
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 16/17
Davi d Li u
APRIL 19, 2014 @ 12: 00 AM
By deactivated I simply mean the Active checkbox on the User is
unchecked =)
But even better than this, try this quiz for this chapter (answers are
posted as well)
http://www.sfdc99.com/2014/02/01/quiz-chapter-4/
Repl y
Srinivas
APRIL 18, 2014 @ 11: 08 PM
Hey David,
Please explain that question once again..if u dont mindi didnt understand the
meaning of term deactivated.
Thanks,
Srinivas.
Reply
Leave a Reply
Enter your comment here...
6/15/2014 Example: How to write a deduping trigger for leads and contacts Salesforce coding lessons for the 99%
http://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/ 17/17
THEME: SI MPLE STYLE BY FI MPLY

Вам также может понравиться