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

I need help Bulkifying this Trigger!
This is my first Apex Trigger and I realize it will make most of you cringe your teeth! It is a simple trigger that will update the lead 'status' field to 'contacted' when the following criteria are met:
1- its 'lead rating' is either D1,D2,D3, or D4
2- the current lead 'status' is "open"
3- the lead has a related task containing "Message Sent:" in the subject
Can anyone please help me bulkify this?
trigger dleadstatus on Lead (before insert, before update) {
for (Lead l : Trigger.new) {
if((l.Eloqua_Lead_Rating__c =='D1' || l.Eloqua_Lead_Rating__c =='D2'|| l.Eloqua_Lead_Rating__c =='D3'|| l.Eloqua_Lead_Rating__c =='D4')&& l.Status =='Open') {
List<Task> sentemails = [SELECT Id FROM Task WHERE Subject LIKE '%Message Sent:%'];
if(sentemails.size() > 0) {
l.Status = 'Contacted';}
else {l.Status = 'Open';}}}
}
1- its 'lead rating' is either D1,D2,D3, or D4
2- the current lead 'status' is "open"
3- the lead has a related task containing "Message Sent:" in the subject
Can anyone please help me bulkify this?
trigger dleadstatus on Lead (before insert, before update) {
for (Lead l : Trigger.new) {
if((l.Eloqua_Lead_Rating__c =='D1' || l.Eloqua_Lead_Rating__c =='D2'|| l.Eloqua_Lead_Rating__c =='D3'|| l.Eloqua_Lead_Rating__c =='D4')&& l.Status =='Open') {
List<Task> sentemails = [SELECT Id FROM Task WHERE Subject LIKE '%Message Sent:%'];
if(sentemails.size() > 0) {
l.Status = 'Contacted';}
else {l.Status = 'Open';}}}
}
Hi Mike,
Nice name mate. I have reformed your trigger. There may be some issues as I was not 100% sure on what you were trying to do or how your org is structured.
However, this is what I have done: I have filled it to the brim with comments, this should help you with understanding bulkifying -
Important thing to remember, is that you dont perform any DML actions or SOQL within a for loop and when you query, you query the whole group of records and then sort through it with a for loop and if statements.
NOTE: if you need to update, insert, query, delete, etc always add to a list and then perform one dml function.
I hope this helps, select as Best answer if it does!
All Answers
Hi Mike,
Nice name mate. I have reformed your trigger. There may be some issues as I was not 100% sure on what you were trying to do or how your org is structured.
However, this is what I have done: I have filled it to the brim with comments, this should help you with understanding bulkifying -
Important thing to remember, is that you dont perform any DML actions or SOQL within a for loop and when you query, you query the whole group of records and then sort through it with a for loop and if statements.
NOTE: if you need to update, insert, query, delete, etc always add to a list and then perform one dml function.
I hope this helps, select as Best answer if it does!
PS. This bit:
if(Email.Subject LIKE '&Message Sent:%'){
may word, but im not 100% sure, it is something that you may have trouble with.
If so, just look into all the ways that you can compare a string.
LIKE, contains, substring, etc etc
I could not agree more, I learnt all my salesforce development initially through the forums until I could read code better and then from others examples which I craft to my own.
Back in the day, I would be stuck on a trigger problem for days, raking through the forums and reposting my questions hoping that someone would see them.
Even if that trigger still needs some work, read through it carefully it will teach you some formations for bulkified triggers.
You are on the right track with bulkifying as governor limits is one of the main issues i would say that people experience with writing triggers.
Particularly the two errors:
Too many SOQL 101
Too many DML 101
Once you have mastered bulkifying, the next step is creating maps. If you have any questions about bulkification or the changes i amde to your trigger, just comment below.
I changed LIKE to == for testing's sake and am still ending up with this error message
Hey yeah,
So this error basically means that the SOQL you used to query into the tasks of your system, you did not add whoid to it.
My fault sorry - basically:
when using trigger, the for loop for (Lead L: Trigger.new) { like this, already has all the fields that are contained within the object. However, should you use another object that is not mainly defined by trigger, you need to query each field that you use within if statements.
Basically it is saying you used whoid in your if statement, but you did not query it within your soql.
Just add whoid to the lsit of queried fields from the task and thatll solve that issue
this should solve it
I will stop bugging you and pick this up tomorrow. Thank you for your help, it will really be good for me to review and learn from.
This is waht i think it is from memory. Basically saying String (segement of characters) String.Contains({!InsertString_). So it would be:
if(Email.Subject.CONTAINS('Message Sent:')){
}
Email.Subject is a string field, .Contains (is the function) and 'Messeage Sent:" is the string we are looking for
below is best way to wright the same above code and will work exactly the way you want it to work.
Let me know if it helps you and don't forget to mark this as best answer if it resolves your query.
Thanks for the response. When using that version, I'm getting an error for using LIKE on line 10. When I change it to .Contains, it gives me an error saying that "Error: Compile Error: Variable does not exist: L.Eloqua_Lead_Rating__c at line 10 column 32"
No worries at all Mike, there isnt really anything you can do for me. The best way to return the favour is to learn from what I have taught you and repeat it to someone who is asking if you ever have the opportunity. That is how these forums work.
In regards to writing another trigger for the task side of things. Personally, I think that you should just add it to your existing trigger.
Triggers can impact on each other and there is no real point in adding two different triggers that are triggered by the same thing on two different objects.
i am not completely sure what you mean by adding a trigger to ask, but:
If you are refering to adding information to the task when the criteria sets the lead status to "Contacted", then adding a completely new trigger would probably only complicate things. As you already have the event and the record queried within your current trigger you can do something like this:
Step 1: add custom boolean field to activity called something like: ContactStatusSet__c or whatever field you would like to use for stating that the lead status was altered through the trigger.
Step 2. Introduce a list of Tasks at the top of the page List<Task> tasksToUpdate = new List<Task>();
Step 3: Change this line:
to this line:
Step 4: Add this line at the end:
Finally:
It is best to keep all trigger functions to do with an object under one trigger.
E.G. Every Account trigger in the one super account trigger. This is to ensure that you control the order of which processes are executed.
You can do so and keep it ordered through:
trigger LeadTrigger on Lead (before update,before insert, before delete, after update, after insert, after delete) {
if(trigger.isbefore){
if(trigger.isinsert){
}else if(trigger.isupdate){
}
}
if(trigger.isafter){
if(trigger.isinsert){
}else if(trigger.isupdate){
}
}
}
All logic that occurs before insert, after insert, etc You can decide where and when it is exactly executed.
This way whenever a DML function is executed, you can catch it and perform neccessary work on it.
Hope this helps, all the best and goodluck
This is working. I added whoid and subject to the selected SOQL items. Question- how would i get this to update the lead when only the task is being updated to meet the criteria 'subject contains Message Sent:' ? Basically I like how it works now but I would like it to evaluate if even only the related task is updated or created to meet that criteria as well. So if a lead already met the criteria then later a task was added to it with the subject= Message Sent: , it would still update the lead status???
That make sense to me that instead of writing above trigger on Lead, you shoud be this on Task.
So whever you send an email, the trigger would fire n update the lead status. Make sense......then let me know
Don't forget to mark it as best answer, if it resolve your issue.
I am very sure in that case, one trigger is enough on task.
Since I am a beginner I'm having a hard time writing a test class for this trigger on leads. I used a version of your lead trigger above. Here is what I have for a test class so far:
@isTest
public class Testdleadstatus2 {
static testMethod void testLeads(){
Lead l = new Lead();
l.FirstName = 'Michael';
l.LastName = 'Burns';
l.Eloqua_Lead_Rating__c = 'D1';
l.Status = 'Open';
insert l;
Task t = new Task();
t.subject = 'Message Sent: Error';
insert t;
List<Lead> open = [SELECT Id, Status FROM Lead WHERE FirstName = 'Michael'];
System.assertEquals(0,open.size());
List<Lead> contacted = [SELECT Id, Status FROM Lead WHERE FirstName = 'Michael'];
System.assertEquals(1,contacted.size());
}}
I'm only getting about 57% coverage