+ Start a Discussion
-d-g--d-g- 

Task and Event Update Triggers, Causing Exception on Converting Lead

So, I've got a couple of triggers that work well when working directly from tasks or events.  An issue has arisen though, where the triggers are causing this: System.ListException: List index out of bounds: 0 when someone tries to Convert a Lead.  Here is the offending code:

 

Id WhoIDCheck = trigger.new[0].WhoId;

List<Event> WhoNum = [SELECT Who.Type FROM Task WHERE WhoId = :WhoIDCheck];

 

The trigger is a Before Update trigger, I am thinking about converting the trigger to an After Update, but I really don't understand how the whole process of converting a lead works (what happens to the ID over the course of the process, it seems to be changed, but when?), so I don't know if that will work.  Any suggestions/help would be greatly appreciated.

Best Answer chosen by Admin (Salesforce Developers) 
SFAdmin5SFAdmin5

alright I ran several tests on this in the ui and did a bulk test as well.  i also tested it for that lead convert failure you had and this trigger resolves that.  this trigger should do the job.  note I took out a few update fields just for the sake of saving coding time.  feel free to add em back.  also let me know if this meets your needs.  in looking at your original code it seems like you only want this trigger to fire on tasks hanging off contacts or leads, and not on tasks on other objects (like opps), but this trigger can easily be modified to handle those objects as well

 

let me know if this works and if so if you need a test class for this thing. 

 

trigger taskTrigger on Task (before update) {

    String contact_prefix = Schema.SObjectType.Contact.getKeyPrefix();
    String lead_prefix = Schema.SObjectType.Lead.getKeyPrefix();

    Set<Id> ids = new Set<Id>();
        for(Task tk : trigger.new)
        {
            ids.add(tk.WhoId);
        }

    Map<Id,Contact> contacts = new Map<Id,Contact>([SELECT id,Phone,Email,Description, Name from Contact where id IN : ids]);
    Map<Id,Lead> leads = new Map<Id,Lead>([SELECT id,Phone,Email,Description, Name from Lead where id IN : ids]);

    for(Task tk : trigger.new)
    
        if(tk.WhoId != null)
        {            
            if(((String)tk.WhoId).startsWith(contact_prefix) )
            {                
                string contactInfo = 
                'A Contact' + '\n' + 
                'Related To: ' + contacts.get(tk.WhoId).Name + '\n' + 
                'Contact: ' + contacts.get(tk.WhoId).Name + '\n' + 
                'Phone: ' + contacts.get(tk.WhoId).Phone + '\n' + 
                'Email: '+ contacts.get(tk.WhoId).Email + '\n' +
                'Comments: '+ contacts.get(tk.WhoId).Description; 
                tk.Description = contactInfo;
            } else if(((String)tk.WhoId).startsWith(lead_prefix))
            {
                string leadInfo= 
                'A Contact' + '\n' + 
                'Related To: ' + leads.get(tk.WhoId).Name + '\n' + 
                'Contact: ' + leads.get(tk.WhoId).Name + '\n' + 
                'Phone: ' + leads.get(tk.WhoId).Phone + '\n' + 
                'Email: '+ leads.get(tk.WhoId).Email + '\n' +
                'Comments: '+ leads.get(tk.WhoId).Description; 
                tk.Description = leadInfo;                         
            }
        } 
}

 

All Answers

SFAdmin5SFAdmin5

please post all the trigger code

-d-g--d-g-

Here ya go!

 

trigger TasksOutlookTaskUpdate on Task (before update) {
    String TaskType = trigger.new[0].Type;
    Id WhoIDCheck = trigger.new[0].WhoId;
    Id WhatIDCheck = trigger.new[0].WhatId;
    String DescField = trigger.new[0].Description;
    String DescMod = DescField;
    
    If (DescMod == null) {
        DescMod = '**>' + '  ' + '<**';
    }
    If (DescMod.contains('**>') == true) {
        DescMod = DescMod.substringBetween('**>','<**');
    } else if (DescMod.contains('**>') == false) {
        DescMod = DescField;
    }
    
    List<Task> RefName = [SELECT What.Type, What.Name FROM Task WHERE WhatId = :WhatIDCheck];
    List<Task> WhoNum = [SELECT Who.Type FROM Task WHERE WhoId = :WhoIDCheck];
    If ( WhoNum[0].Who.Type == 'Contact' ) {
        List<Contact> ContData = [SELECT Name, Phone, Email FROM Contact WHERE Id = :WhoIDCheck];
        String TaskID = trigger.new[0].Id;
        string ForOutlook = 'A Contact' + '\n' + 'Type: ' + TaskType + '\n' + 'Related To: ' + RefName[0].What.Type + ': '
        + RefName[0].What.Name + '\n'
        + 'Contact: ' + ContData[0].Name + '\n' + 'Phone: ' + ContData[0].Phone + '\n' + 'Email: '
        + ContData[0].Email + '\n' + 'Comments: '
        + '**>' + DescMod + '<**'
        + '\n' + 'Link to Activity: https://na6.salesforce.com/' + TaskID;
        trigger.new[0].Description = ForOutlook;
    } else if ( WhoNum[0].Who.Type == 'Lead' ) {
        List<Lead> LeadData = [SELECT Name, Phone, Email FROM Lead WHERE Id = :WhoIDCheck];
        String TaskID = trigger.new[0].Id;
        string ForOutlook = 'A Lead' + '\n' + 'Type: ' + TaskType + '\n'
        + 'Contact: ' + LeadData[0].Name + '\n' + 'Phone: ' + LeadData[0].Phone + '\n' + 'Email: '
        + LeadData[0].Email + '\n' + 'Comments: '
        + '**>' + DescMod + '<**' + '\n'
        + 'Link to Activity: https://na6.salesforce.com/' + TaskID;
        trigger.new[0].Description = ForOutlook;
    }
    
}

-d-g--d-g-

Oh, there is another one where basically "Task" is replaced with "Event"... I should probably explain what I'm doing: basically I'm trying to gather information from the account, and some extended information about the record, so our sales guy can have that easily available on his phone.  To make it work I had to get around the fact that there is no Long text area available for activity objects, so I am using the description field... which lead to another workaround to preserve actual description contents.  Anyway .... it works except when it is activated from a Convert... so far.

SFAdmin5SFAdmin5

alright so, i see what you're trying to do.  i was able to replicate the problem you see in my dev org.  that trigger code should be re-written because it's not written properly.  the problem is it isn't bulkified (whenever you see [0] that is a bad sign, and that trigger is full of them)/  i'm working on re-writing it.  hopefully someone can do this faster than I can for your sake (and there are a lot of people on here who are a lot better at this than I am), but, I'm working on it

SFAdmin5SFAdmin5

alright I ran several tests on this in the ui and did a bulk test as well.  i also tested it for that lead convert failure you had and this trigger resolves that.  this trigger should do the job.  note I took out a few update fields just for the sake of saving coding time.  feel free to add em back.  also let me know if this meets your needs.  in looking at your original code it seems like you only want this trigger to fire on tasks hanging off contacts or leads, and not on tasks on other objects (like opps), but this trigger can easily be modified to handle those objects as well

 

let me know if this works and if so if you need a test class for this thing. 

 

trigger taskTrigger on Task (before update) {

    String contact_prefix = Schema.SObjectType.Contact.getKeyPrefix();
    String lead_prefix = Schema.SObjectType.Lead.getKeyPrefix();

    Set<Id> ids = new Set<Id>();
        for(Task tk : trigger.new)
        {
            ids.add(tk.WhoId);
        }

    Map<Id,Contact> contacts = new Map<Id,Contact>([SELECT id,Phone,Email,Description, Name from Contact where id IN : ids]);
    Map<Id,Lead> leads = new Map<Id,Lead>([SELECT id,Phone,Email,Description, Name from Lead where id IN : ids]);

    for(Task tk : trigger.new)
    
        if(tk.WhoId != null)
        {            
            if(((String)tk.WhoId).startsWith(contact_prefix) )
            {                
                string contactInfo = 
                'A Contact' + '\n' + 
                'Related To: ' + contacts.get(tk.WhoId).Name + '\n' + 
                'Contact: ' + contacts.get(tk.WhoId).Name + '\n' + 
                'Phone: ' + contacts.get(tk.WhoId).Phone + '\n' + 
                'Email: '+ contacts.get(tk.WhoId).Email + '\n' +
                'Comments: '+ contacts.get(tk.WhoId).Description; 
                tk.Description = contactInfo;
            } else if(((String)tk.WhoId).startsWith(lead_prefix))
            {
                string leadInfo= 
                'A Contact' + '\n' + 
                'Related To: ' + leads.get(tk.WhoId).Name + '\n' + 
                'Contact: ' + leads.get(tk.WhoId).Name + '\n' + 
                'Phone: ' + leads.get(tk.WhoId).Phone + '\n' + 
                'Email: '+ leads.get(tk.WhoId).Email + '\n' +
                'Comments: '+ leads.get(tk.WhoId).Description; 
                tk.Description = leadInfo;                         
            }
        } 
}

 

This was selected as the best answer
-d-g--d-g-

Oh, wow, that's amazing....sorry I didn't get back to you sooner. I haven't tested it yet, because the code doesn't work with the records existing description, yet.

 

I'm still learning the in's and out's of apex coding (comparing the primitive code I wrote vs your code).  So I have a question: with the map method, how would I extract the records existing description, so I could check it/manipulate it?  Just a quick sketch of how to get the string from the field would be wonderful.

 

Anyway, you went above and beyond. That's awsome!

SFAdmin5SFAdmin5

cool.  can you please mark my solution as a resolution to this thread?  thanks again

-d-g--d-g-

Hey, so I'm running into problems with this code.  The first, is that I want the ID for the task, not the account appended to the URL in the description, I'm not sure how to do this with the way this code is setup.  The second, is that I am trying to take the Description from the Task, and test/manipulate it... again, I don't know how to access this data with the way this was coded.  Any help would be appreciated... here's the modified code:

 

trigger TaskOutlookUpdate3 on Task (before update) {

    String contact_prefix = Schema.SObjectType.Contact.getKeyPrefix();
    String lead_prefix = Schema.SObjectType.Lead.getKeyPrefix();

    Set<Id> ids = new Set<Id>();
        for(Task tk : trigger.new)
        {
            ids.add(tk.WhoId);
        }
    
    Map<Id,Contact> contacts = new Map<Id,Contact>([SELECT id,Phone,Email,Description, Name from Contact where id IN : ids]);
    Map<Id,Lead> leads = new Map<Id,Lead>([SELECT id,Phone,Email,Description, Name from Lead where id IN : ids]);

    for(Task tk : trigger.new)
    
        if(tk.WhoId != null)
        {            
            if(((String)tk.WhoId).startsWith(contact_prefix) )
            {
                // String DescField = contacts.get(tk.WhoId).Description;
                String DescField = contacts.get(tk.Id).Description;
                String DescMod = DescField;
    If (DescMod == null) {
        DescMod = '**>' + ' ' + '<**';
    }
    If (DescMod.contains('**>') == true) {
        DescMod = DescMod.substringBetween('**>','<**');
    } else if (DescMod.contains('**>') == false) {
        DescMod = DescField;
    }
                    
                string contactInfo =
                'A Contact' + '\n' +
                'Related To: ' + contacts.get(tk.WhoId).Name + '\n' +
                'Contact: ' + contacts.get(tk.WhoId).Name + '\n' +
                'Phone: ' + contacts.get(tk.WhoId).Phone + '\n' +
                'Email: '+ contacts.get(tk.WhoId).Email + '\n' +
                'Description: ' + '**>' + DescMod + '<**' + '\n' +
                'Link to Activity: https://na6.salesforce.com/' + contacts.get(tk.WhoId).Id;
                tk.Description = contactInfo;
            } else if(((String)tk.WhoId).startsWith(lead_prefix))
            {
                // String DescField = contacts.get(tk.WhoId).Description;
           String DescField = leads.get(tk.Id).Description;
        String DescMod = DescField;
    If (DescMod == null) {
        DescMod = '**>' + ' ' + '<**';
    }
    If (DescMod.contains('**>') == true) {
        DescMod = DescMod.substringBetween('**>','<**');
    } else if (DescMod.contains('**>') == false) {
        DescMod = DescField;
    }
                string leadInfo=
                'A Contact' + '\n' +
                'Related To: ' + leads.get(tk.WhoId).Name + '\n' +
                'Contact: ' + leads.get(tk.WhoId).Name + '\n' +
                'Phone: ' + leads.get(tk.WhoId).Phone + '\n' +
                'Email: '+ leads.get(tk.WhoId).Email + '\n' +
                'Comments: ' + '**>' + DescMod + '<**' + '\n' +
                'Link to Activity: https://na6.salesforce.com/' + leads.get(tk.WhoId).Id;
                tk.Description = leadInfo;                         
            }
        }
}

-d-g--d-g-

So I fixed the problem (without the elegance that the previous poster showed) by using trigger.new[0]'s when getting the Description and Id for the current Task.  So excited to get this working.  Thank you kind dev's for the help.  Case closed.