1

Last week, I deployed the following Apex Trigger & Class in order to update a custom field called "Open Tasks" on both the Lead & Contact Record. It pulls in the number of open tasks related to that lead/contact.

Here is the trigger:

trigger UpdateLeadOpenTasks on Task (after delete, after insert, after undelete,
after update) {

// Declare the variables

public set<Id> LeadIDs = new Set<Id>();  
public list<Lead> LeadsToUpdate = new List<Lead>();  
public set<Id> ContactIDs = new Set<Id>();  
public list<Contact> ContactsToUpdate = new List<Contact>();  

// Build the list of Leads and Contacts to update  
if(Trigger.isInsert || Trigger.isUnDelete || Trigger.isUpdate){  
    for(Task t: Trigger.new){  
    if(string.valueOf(t.WhoId).startsWith('00Q'))  
    LeadIDs.add(t.WhoId);  
    if(string.valueOf(t.WhoId).startsWith('003'))  
    ContactIDs.add(t.WhoId);  
    }  
}  

if(Trigger.isDelete || Trigger.isUpdate){  
    for(Task t: Trigger.old){  
    if(string.valueOf(t.WhoId).startsWith('00Q'))  
    LeadIDs.add(t.WhoId);  
    if(string.valueOf(t.WhoId).startsWith('003'))  
    ContactIDs.add(t.WhoId);  
    }  
}  

// Update the Leads  

if(LeadIDs.size()>0){  
for(Lead l: [Select l.Id, l.Open_Tasks__c,  
(Select Id From Tasks where IsClosed = False)  
From Lead l where Id in :LeadIDs])  
LeadsToUpdate.add(new Lead(Id=l.Id, Open_Tasks__c = l.Tasks.size()));  
update LeadsToUpdate;  
}  

// Update the Contacts  

if(ContactIDs.size()>0){  
for(Contact c: [Select c.Id, c.Open_Tasks__c,  
(Select Id From Tasks where IsClosed = False)  
From Contact c where Id in :ContactIDs])  
ContactsToUpdate.add(new Contact(Id=c.Id, Open_Tasks__c = c.Tasks.size()));  
update ContactsToUpdate;  
}  
}  
}  

Here is the class:

@isTest  
private class OpenTask {  
static testMethod void LeadTest(){  
// Create a Lead  
Lead newLead = new Lead(LastName='Test', Company='ABC', Status='Targeted');  
insert newLead;  

// Create a Task  
Task newTask = new Task(Subject='Open Task', Status='Not Started', WhoId=newLead.Id);  
test.startTest();  
insert newTask;  
test.stopTest();  

// Verify that the # Open Tasks is correct  
newLead = [select Open_Tasks__c from Lead where Id=:newLead.Id ];  
System.assertEquals(1,newLead.Open_Tasks__c);  
}  

static testMethod void ContactTest(){  
// Create a Contact  
Contact newContact = new Contact(LastName='Test');  
insert newContact;  

// Create a Task  
Task newTask = new Task(Subject='Open Task', Status='Not Started', WhoId=newContact.Id);  
test.startTest();  
insert newTask;  
test.stopTest();  

// Verify that the # Open Tasks is correct  
newContact = [select Open_Tasks__c from Contact where Id=:newContact.Id];  
System.assertEquals(1,newContact.Open_Tasks__c);  
}  

static testMethod void CompletedTest(){  
// Create a Lead  
Lead newLead = new Lead(LastName='Test', Company='ABC', Status='Targeted');  
insert newLead;  

// Create a Completed Task  
Task newTask = new Task(Subject='Open Task', Status='Completed', WhoId=newLead.Id);  
test.startTest();  
insert newTask;  
test.stopTest();  

// Verify that the # Open Tasks is empty  
newLead = [select Open_Tasks__c from Lead where Id=:newLead.Id ];  
System.assertEquals(0,newLead.Open_Tasks__c);  
}  

static testMethod void BatchTest(){  
// Create 100 Leads  
List<Lead> newLeads = new List<Lead>();  
for (Integer i = 0; i < 200; i++) {  
newLeads.add(new Lead(LastName='Test '+i, Company='ABC', Status='Targeted'));  
}  
insert newLeads;  

// Create a task for each one  
List<Task> newTasks = new List<Task>();  
for(Lead l : newLeads){  
newTasks.add(new Task(Subject='Open Task', Status='Completed', WhoId=l.Id));  
}  

// Insert the tasks  
test.startTest();  
insert newTasks;  
test.stopTest();  

// We could verify that the Open Tasks fields were updated correctly,  
// but this is just testing the governor limits so it's not necessary  
}  
}  

The issue that I'm currently running into concerns the "Email to Salesforce" functionality. I am receiving the following error message:
"Apex script unhandled trigger exception by user/organization:UpdateLeadOpenTasks: execution of AfterInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Trigger.UpdateLeadOpenTasks: line 14, column 1"

The message is Undeliverable. Any advice would be greatly appreciated. Thanks,

  • Can you verify that line 14 in your trigger is if(string.valueOf(t.WhoId).startsWith('00Q')) I'm not seeing how that would give you a null reference error. – mrBlaQ May 5 '14 at 18:44
  • That is correct, that is line 14. – ddean.au May 5 '14 at 18:45
  • 3
    You should make sure Whoid isn't null. – sfdcfox May 5 '14 at 19:09
1

Thanks to @sfdcfx, Here's my updated trigger:

    trigger UpdateLeadOpenTasks on Task (after delete, after insert, after undelete,
after update) {

// Declare the variables

public set<Id> LeadIDs = new Set<Id>();
public list<Lead> LeadsToUpdate = new List<Lead>();
public set<Id> ContactIDs = new Set<Id>();
public list<Contact> ContactsToUpdate = new List<Contact>();

// Build the list of Leads and Contacts to update
if(Trigger.isInsert || Trigger.isUnDelete || Trigger.isUpdate){
    for(Task t: Trigger.new){
    if(t.WhoId != NULL){
        if(string.valueOf(t.WhoId).startsWith('00Q'))
        LeadIDs.add(t.WhoId);
        if(string.valueOf(t.WhoId).startsWith('003'))
        ContactIDs.add(t.WhoId);
        }
    }
}
if(Trigger.isDelete || Trigger.isUpdate){
    for(Task t: Trigger.old){
    if(t.WhoId != NULL){
         if(string.valueOf(t.WhoId).startsWith('00Q'))
         LeadIDs.add(t.WhoId);
         if(string.valueOf(t.WhoId).startsWith('003'))
         ContactIDs.add(t.WhoId);
         }
     }
}

// Update the Leads

if(LeadIDs.size()>0){
for(Lead l: [Select l.Id, l.Open_Tasks__c,
(Select Id From Tasks where IsClosed = False)
From Lead l where Id in :LeadIDs])
LeadsToUpdate.add(new Lead(Id=l.Id, Open_Tasks__c = l.Tasks.size()));
update LeadsToUpdate;
}

// Update the Contacts

if(ContactIDs.size()>0){
for(Contact c: [Select c.Id, c.Open_Tasks__c,
(Select Id From Tasks where IsClosed = False)
From Contact c where Id in :ContactIDs])
ContactsToUpdate.add(new Contact(Id=c.Id, Open_Tasks__c = c.Tasks.size()));
update ContactsToUpdate;
}


}
| improve this answer | |
  • Probably ought to check your Deleted and Updated Tasks for null WhoIDs as well. – Thomas Taylor May 5 '14 at 19:28
  • @ThomasTaylor - You're exactly right. I corrected it on there as well. Thanks! – ddean.au May 5 '14 at 19:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.