You need to sign in to do that
Don't have an account?

Bilkify Trigger Before Insert Lead Object / Update Contact then delete Lead
Hello Users
I have a need to bulkify the below trigger.
This works great with the UI, however with an API bulk inserting, is causing some issues with SOQL 101 governing limit.
The process is, on the before insert of a lead, it checks to see if
1) an existing lead is in the database with the same email (update a field on lead if found), then delete the lead record after insert
2) if an email address exists on the contact record, update the contact record if found, and delete the lead after insert.
3) Write a custom object (LDS__c) record with some details. (not important)
I am failing at line 75, when i query the contact object to update within the for loop
Contact Contact1 = [Select Id from Contact where Id =: ContactId limit 1];
I am failing in my test class to push in bulk records
All help is appreciated.
Lead before insert trigger
Lead after insert (delete record)
Lead test class
I have a need to bulkify the below trigger.
This works great with the UI, however with an API bulk inserting, is causing some issues with SOQL 101 governing limit.
The process is, on the before insert of a lead, it checks to see if
1) an existing lead is in the database with the same email (update a field on lead if found), then delete the lead record after insert
2) if an email address exists on the contact record, update the contact record if found, and delete the lead after insert.
3) Write a custom object (LDS__c) record with some details. (not important)
I am failing at line 75, when i query the contact object to update within the for loop
Contact Contact1 = [Select Id from Contact where Id =: ContactId limit 1];
I am failing in my test class to push in bulk records
All help is appreciated.
Lead before insert trigger
/****************************************************************** Created By : David Robinson (Blirt) *******************************************************************/ trigger Lead_HDL_BI on Lead (before insert) { public string LeadEmail; public boolean ContactFound; public string ContactId; public boolean LeadFound; public string LeadId; Id LeadRTNonSearchable = [SELECT Id,Name,DeveloperName FROM RecordType WHERE DeveloperName='Non_Searchable' AND SObjectType='Lead' LIMIT 1].Id; Id LeadRTSearchable = [SELECT Id,Name,DeveloperName FROM RecordType WHERE DeveloperName='Searchable' AND SObjectType='Lead' LIMIT 1].Id; //Query Contacts for matching email address List<Contact> ContactList = [ SELECT Id FROM Contact WHERE Email =: LeadEmail ORDER BY LastModifiedDate DESC LIMIT 1 ]; //Query Leads for matching email address List<Lead> LeadList = [ SELECT Id FROM Lead WHERE Email =: LeadEmail AND IsConverted = false //Only include Non Converted Leads AND (RecordTypeId =: LeadRTSearchable OR RecordTypeId = null) //Only include Searchable Leads or RT = null ORDER BY LastModifiedDate DESC LIMIT 1 ]; for(Lead record: Trigger.new) { try{ LeadEmail = record.Email.trim(); }catch(Exception e){ } if(record.LeadSource == 'Big Commerce Book Purchase') { record.Book_Purchaser__c = 'Yes'; } if(record.LeadSource == 'Blog Subscriber') { record.Blog_Subscriber__c = 'Yes'; } ContactId = null; try{ ContactId = ContactList[0].Id; ContactFound=true; }catch(Exception e){ ContactId = null; ContactFound=false; } LeadId = null; try{ LeadId = LeadList[0].Id; LeadFound=true; }catch(Exception e){ LeadId = null; LeadFound=false; } //Only run when email address field has a value if(record.Email!=null){ //Run if Contact with same email Found if(ContactFound=true){ //Update Contact and Lead if(record.LeadSource == 'Big Commerce Book Purchase') { try{ //Update Found Contact Contact Contact1 = [Select Id from Contact where Id =: ContactId limit 1]; Contact1.Book_Purchaser__c = 'Yes'; Contact1.Book_Purchase_date__c = record.Book_Purchase_date__c; update Contact1; //Update New Lead record.TriggerDelete__c=true; //Insert log record LDS__c LeadLog = new LDS__c( CreatedDate__c=datetime.now() ,Company__c=record.Company ,Description__c='ContactFound=true, record.LeadSource == Big Commerce Book Purchase' ,Email__c=record.Email ,FirstName__c=record.FirstName ,LastName__c=record.LastName ,LeadSource__c=record.LeadSource ,Book_Purchase_date__c=record.Book_Purchase_date__c ,Blog_Subscription_date__c=record.Blog_Subscription_date__c ); //insert LeadLog; }catch(Exception e){ } } //Update Contact and Lead if(record.LeadSource == 'Blog Subscriber') { try{ //Update Found Contact Contact Contact1 = [Select Id from Contact where Id =: ContactId limit 1]; Contact1.Blog_Subscriber__c = 'Yes'; Contact1.Blog_Subscription_date__c = record.Blog_Subscription_date__c; update Contact1; //Update New Lead record.TriggerDelete__c=true; //Insert log record LDS__c LeadLog = new LDS__c( CreatedDate__c=datetime.now() ,Company__c=record.Company ,Description__c='ContactFound=true, record.LeadSource == Blog Subscriber' ,Email__c=record.Email ,FirstName__c=record.FirstName ,LastName__c=record.LastName ,LeadSource__c=record.LeadSource ,Book_Purchase_date__c=record.Book_Purchase_date__c ,Blog_Subscription_date__c=record.Blog_Subscription_date__c ); insert LeadLog; }catch(Exception e){ } } } //Run if Lead with same email Found if(LeadFound=true){ //Update Lead if(record.LeadSource == 'Big Commerce Book Purchase') { try{ //Update Found Lead Lead Lead1 = [Select Id from Lead where Id =: LeadId limit 1]; Lead1.Book_Purchaser__c = 'Yes'; Lead1.Book_Purchase_date__c = record.Book_Purchase_date__c; update Lead1; //Update New Lead record.TriggerDelete__c=true; //Insert log record LDS__c LeadLog = new LDS__c( CreatedDate__c=datetime.now() ,Company__c=record.Company ,Description__c='LeadFound=true, record.LeadSource == Big Commerce Book Purchase' ,Email__c=record.Email ,FirstName__c=record.FirstName ,LastName__c=record.LastName ,LeadSource__c=record.LeadSource ,Book_Purchase_date__c=record.Book_Purchase_date__c ,Blog_Subscription_date__c=record.Blog_Subscription_date__c ); insert LeadLog; }catch(Exception e){ } } //Update Lead if(record.LeadSource == 'Blog Subscriber') { try{ //Update Found Lead Lead Lead1 = [Select Id from Lead where Id =: LeadId limit 1]; Lead1.Blog_Subscriber__c = 'Yes'; Lead1.Blog_Subscription_date__c = record.Blog_Subscription_date__c; update Lead1; //Update New Lead record.TriggerDelete__c=true; //Insert log record LDS__c LeadLog = new LDS__c( CreatedDate__c=datetime.now() ,Company__c=record.Company ,Description__c='LeadFound=true, record.LeadSource == Blog Subscriber' ,Email__c=record.Email ,FirstName__c=record.FirstName ,LastName__c=record.LastName ,LeadSource__c=record.LeadSource ,Book_Purchase_date__c=record.Book_Purchase_date__c ,Blog_Subscription_date__c=record.Blog_Subscription_date__c ); insert LeadLog; }catch(Exception e){ } } } } } }
Lead after insert (delete record)
/****************************************************************** Created By : David Robinson (Blirt) *******************************************************************/ trigger Lead_HDL_AI on Lead (after insert) { for(Lead record: Trigger.new) { //Query Lead List<Lead> LeadList = [SELECT Id FROM Lead WHERE Id =:record.Id LIMIT 1]; //Delete Lead if(record.TriggerDelete__c==true){try{DELETE LeadList;}catch(Exception e){} } } }
Lead test class
/****************************************************************** Created By : David Robinson Blirt *******************************************************************/ @isTest private without sharing class Lead_HDL_TC{ /****************************************************************** Declare all record variables here. Examples: private static Account AC1; private static Tax__c TA1; ********************************************************************/ private static Account AC1; private static Contact CO1; private static Lead L1; private static Lead L2; private static Lead L3; private static Lead L4; private static Lead L5; /****************************************************************** Write your Test Methods Here. You can write as many as you like ********************************************************************/ static testMethod void TestBatch() { try { insert createLeads(200); System.assert(false, 'Exception expected'); } catch (DmlException e) { System.assertEquals(200 - 100, e.getNumDml()); } } //static testMethod void Increment() { // insert createLeads(98); // try { // insert createLeads(5); // System.assert(false, 'Exception expected'); // } catch (DmlException e) { // System.assertEquals(100 - 98 + 5, e.getNumDml()); // } //} private static Lead[] createLeads(Integer n) { Lead[] leads = new Lead[] {}; for(Integer i = 0; i < n; i++) { leads.add(new Lead( FirstName='F1'+ i ,LastName='L1'+ i ,Email='test@test'+ i +'.com' ,Status='Open' ,Company='Test1' ,LeadSource='Big Commerce Book Purchase' ,TriggerDelete__c=false )); } return leads; } private static testMethod void TestUI() { /*********************************************************** * INSERT TEST METHODS HERE ************************************************************/ insertTestAccounts(); insertTestContacts(); //insertTestLeads(); } /****************************************************************** Write your InsertRecord functions here. ********************************************************************/ // INSERT ACCOUNTS public static void insertTestAccounts() { List<Account> remRecords= [SELECT Id FROM Account]; DELETE remRecords; System.assertEquals(0,[SELECT count() FROM Account]); List<Account> Accounts = new List<Account>(); AC1 = NEW Account( Name='Test1' ); Accounts.add(AC1); INSERT Accounts; UPDATE Accounts; System.assertEquals(1,[SELECT count() FROM Account]); } // INSERT CONTACTS public static void insertTestContacts() { List<Contact> remRecords= [SELECT Id FROM Contact]; DELETE remRecords; System.assertEquals(0,[SELECT count() FROM Contact]); List<Contact> Contacts = new List<Contact>(); CO1 = NEW Contact( FirstName='F1' ,LastName='L1' ,Account=AC1 ,Email='test@test.com' ); Contacts.add(CO1); INSERT Contacts; UPDATE Contacts; System.assertEquals(1,[SELECT count() FROM Contact]); } // INSERT LEADS public static void insertTestLeads() { //List<Lead> remRecords= [SELECT Id FROM Lead]; //DELETE remRecords; //System.assertEquals(0,[SELECT count() FROM Lead]); List<Lead> Leads = new List<Lead>(); L1 = NEW Lead( FirstName='F1' ,LastName='L1' ,Email='test@test.com' ,Status='Open' ,Company='Test1' ,LeadSource='Big Commerce Book Purchase' ,TriggerDelete__c=false ); L2 = NEW Lead( FirstName='F1' ,LastName='L1' ,Email='test@test.com' ,Status='Open' ,Company='Test1' ,LeadSource='Blog Subscriber' ,TriggerDelete__c=false ); L3 = NEW Lead( FirstName='F1' ,LastName='L1' ,Email='test41234234234324324@test.com' ,Status='Open' ,Company='Test1' ,LeadSource='Some Other Source' ,TriggerDelete__c=false ); L4 = NEW Lead( FirstName='F1' ,LastName='L1' ,Email='test@test.com' ,Status='Open' ,Company='Test1' ,LeadSource='Blog Subscriber' ,TriggerDelete__c=false ); L5 = NEW Lead( FirstName='F1' ,LastName='L1' ,Email='test12121@1212121test.com' ,Status='Open' ,Company='Test1' ,LeadSource='Blog Subscriber' ,TriggerDelete__c=true ); Leads.add(L1); Leads.add(L2); Leads.add(L3); Leads.add(L4); Leads.add(L5); INSERT Leads; //UPDATE Leads; //System.assertEquals(5,[SELECT count() FROM Lead]); } }
There were some issues with code.
There are some apex best practices which must be followed for effective development of the code.
Here is the link for you to go through:
https://developer.salesforce.com/page/Apex_Code_Best_Practices
One of them being , we should not write SOQL and DML operations inside a loop, beacuse we might hit the salesforce governor limits.As you are getting the SOQL 101 exception it is one of the governor limit that in one instance we cannot apply more that 100 SOQL .
Here is the updated code of the trigger ,
/******************************************************************
Created By : David Robinson (Blirt)
*******************************************************************/
trigger Lead_HDL_BI on Lead (before insert) {
public string LeadEmail;
public boolean ContactFound;
public string ContactId;
public boolean LeadFound;
public string LeadId;
Id LeadRTNonSearchable = [SELECT Id,Name,DeveloperName FROM RecordType WHERE DeveloperName='Non_Searchable' AND SObjectType='Lead' LIMIT 1].Id;
Id LeadRTSearchable = [SELECT Id,Name,DeveloperName FROM RecordType WHERE DeveloperName='Searchable' AND SObjectType='Lead' LIMIT 1].Id;
//Query Contacts for matching email address
List<Contact> ContactList = [
SELECT Id ,Book_Purchaser__c,Book_Purchase_date__c,Blog_Subscriber__c,Blog_Subscription_date__c
FROM Contact
WHERE Email =: LeadEmail
ORDER BY LastModifiedDate DESC
LIMIT 1
];
//Query Leads for matching email address
List<Lead> LeadList = [
SELECT Id,Book_Purchaser__c,Book_Purchase_date__c,Blog_Subscriber__c,Blog_Subscription_date__c
FROM Lead
WHERE Email =: LeadEmail
AND IsConverted = false //Only include Non Converted Leads
AND (RecordTypeId =: LeadRTSearchable OR RecordTypeId = null) //Only include Searchable Leads or RT = null
ORDER BY LastModifiedDate DESC
LIMIT 1
];
list<LDS__c> newLDSList = new List<LDS__c>();
for(Lead record: Trigger.new) {
try{
LeadEmail = record.Email.trim();
}catch(Exception e){
}
if(record.LeadSource == 'Big Commerce Book Purchase') {
record.Book_Purchaser__c = 'Yes';
}
if(record.LeadSource == 'Blog Subscriber') {
record.Blog_Subscriber__c = 'Yes';
}
ContactId = null;
try{
ContactId = ContactList[0].Id;
ContactFound=true;
}catch(Exception e){
ContactId = null;
ContactFound=false;
}
LeadId = null;
try{
LeadId = LeadList[0].Id;
LeadFound=true;
}catch(Exception e){
LeadId = null;
LeadFound=false;
}
//Only run when email address field has a value
if(record.Email!=null){
//Run if Contact with same email Found
if(ContactFound=true){
//Update Contact and Lead
if(record.LeadSource == 'Big Commerce Book Purchase') {
try{
//Update Found Contact
//Contact Contact1 = [Select Id from Contact where Id =: ContactId limit 1];
//Contact1.Book_Purchaser__c = 'Yes';
//Contact1.Book_Purchase_date__c = record.Book_Purchase_date__c;
//update Contact1;
ContactList[0].Book_Purchaser__c = 'Yes';
ContactList[0].Book_Purchase_date__c = record.Book_Purchase_date__c;
//Update New Lead
record.TriggerDelete__c=true;
//Insert log record
LDS__c LeadLog = new LDS__c(
CreatedDate__c=datetime.now()
,Company__c=record.Company
,Description__c='ContactFound=true, record.LeadSource == Big Commerce Book Purchase'
,Email__c=record.Email
,FirstName__c=record.FirstName
,LastName__c=record.LastName
,LeadSource__c=record.LeadSource
,Book_Purchase_date__c=record.Book_Purchase_date__c
,Blog_Subscription_date__c=record.Blog_Subscription_date__c
);
//insert LeadLog;
}catch(Exception e){
}
}
//Update Contact and Lead
if(record.LeadSource == 'Blog Subscriber') {
try{
//Update Found Contact
//Contact Contact1 = [Select Id from Contact where Id =: ContactId limit 1];
//Contact1.Blog_Subscriber__c = 'Yes';
//Contact1.Blog_Subscription_date__c = record.Blog_Subscription_date__c;
//update Contact1;
ContactList[0].Blog_Subscriber__c = 'Yes';
ContactList[0].Blog_Subscription_date__c = record.Blog_Subscription_date__c;
//Update New Lead
record.TriggerDelete__c=true;
//Insert log record
LDS__c LeadLog = new LDS__c(
CreatedDate__c=datetime.now()
,Company__c=record.Company
,Description__c='ContactFound=true, record.LeadSource == Blog Subscriber'
,Email__c=record.Email
,FirstName__c=record.FirstName
,LastName__c=record.LastName
,LeadSource__c=record.LeadSource
,Book_Purchase_date__c=record.Book_Purchase_date__c
,Blog_Subscription_date__c=record.Blog_Subscription_date__c
);
newLDSList.add(LeadLog);
//insert LeadLog;
}catch(Exception e){
}
}
}
//Run if Lead with same email Found
if(LeadFound=true){
//Update Lead
if(record.LeadSource == 'Big Commerce Book Purchase') {
try{
//Update Found Lead
//Lead Lead1 = [Select Id from Lead where Id =: LeadId limit 1];
//Lead1.Book_Purchaser__c = 'Yes';
//Lead1.Book_Purchase_date__c = record.Book_Purchase_date__c;
//update Lead1;
LeadList[0].Book_Purchaser__c = 'Yes';
LeadList[0].Book_Purchase_date__c = record.Book_Purchase_date__c;
//Update New Lead
record.TriggerDelete__c=true;
//Insert log record
LDS__c LeadLog = new LDS__c(
CreatedDate__c=datetime.now()
,Company__c=record.Company
,Description__c='LeadFound=true, record.LeadSource == Big Commerce Book Purchase'
,Email__c=record.Email
,FirstName__c=record.FirstName
,LastName__c=record.LastName
,LeadSource__c=record.LeadSource
,Book_Purchase_date__c=record.Book_Purchase_date__c
,Blog_Subscription_date__c=record.Blog_Subscription_date__c
);
newLDSList.add(LeadLog);
//insert LeadLog;
}catch(Exception e){
}
}
//Update Lead
if(record.LeadSource == 'Blog Subscriber') {
try{
//Update Found Lead
//Lead Lead1 = [Select Id from Lead where Id =: LeadId limit 1];
//Lead1.Blog_Subscriber__c = 'Yes';
//Lead1.Blog_Subscription_date__c = record.Blog_Subscription_date__c;
//update Lead1;
LeadList[0].Blog_Subscriber__c = 'Yes';
LeadList[0].Blog_Subscription_date__c = record.Blog_Subscription_date__c;
//Update New Lead
record.TriggerDelete__c=true;
//Insert log record
LDS__c LeadLog = new LDS__c(
CreatedDate__c=datetime.now()
,Company__c=record.Company
,Description__c='LeadFound=true, record.LeadSource == Blog Subscriber'
,Email__c=record.Email
,FirstName__c=record.FirstName
,LastName__c=record.LastName
,LeadSource__c=record.LeadSource
,Book_Purchase_date__c=record.Book_Purchase_date__c
,Blog_Subscription_date__c=record.Blog_Subscription_date__c
);
newLDSList.add(LeadLog);
//insert LeadLog;
}catch(Exception e){
}
}
}
}
}
update contactList;
update LeadList;
insert newLDSList;
}
I hope this solves your SOQL 101 exception.Contact me if there is some other issues.
THanks
Nitin
1. Check to see if the lead exists with same email id as that of lead which is currently being inserted. If its found dont insert lead at all. Just add an error to it. As of now you are inserting the lead and tracking it with seperate variable and later you are deleting the lead record based on the tracking field.
2. Check to see if there exists a contact with similar email as that of lead record bing inserted. If email matches then update the contact record with the lead fields you wanted and dont insert the lead record at atll. Instead add an error to it.
3. You cant have a soql query inside a for loop(Which lead to 101 soql exception). Instead use collections efficiently.
Below is the skeleton provided,
trigger Lead_HDL_BI on Lead(before insert) {
//there is no need of this statement exactly as we are using only one event here
if(Trigger.isInsert && Trigger.isBefore) {
Lead_HDL_BI_LeadHandler.handleBeforeInsert(trigger.new);
}
}
public with sharing class Lead_HDL_BI_LeadHandler {
public static void handleBeforeInsert(List<Lead> list_Leads){
//Write your logic here not insert lead at all
List<Contact> List_con = new List<Contact>();
List<Lead> list_LeadsUpdate = new List<Lead>();
Map<String,Lead> map_StrEmail;
Map<String,Lead> map_strEmail2;
for(Lead objLead : list_Leads)
map_StrEmail.add(objLead.Email,objLead);
for(Lead objLead2 :[SELECT Id,Email FROM Lead WHERE Email In :map_StrEmail.keySet()];
map_strEmail2.add(objLead2.Email, objLead2);
for(Lead objLead : list_Leads) {
if(map_strEmail2.contains(objLead.Email)) {
Lead objLeadUp = map_strEmail2.get(objLead.Email);
//do updates to the existing lead and add to the list
list_LeadsUpdate.add(objLeadUp);
objLead.addError('New lead record wont inserted because there exists a lead with same email id already, And existing lead has been updated');
}
}
if(list_LeadsUpdate.size() > 0)
update list_LeadsUpdate;
}
//similar logic can be tried for contact insertion/ updating logic.
}
Do we have an alternative like not inserting the lead record at all(just tried adding an error to it)
Why do we need repetaed DML such as inserting and deleting the same ?
I have modified the code as you suggested, but I am getting null for the LeadEmail string, which in turn make my leadlist query wrong (it has a null value in the line WHERE Email =: LeadEmail) because the value sits inside the for statement, however the query is outside.
The whole trigger is reliant on me getting this email (well the LeadList) within the for statement.
How do you suggest I do this and keep it batchified?
debug:
update code below