-3

This is what I have to do Write a trigger that automatically sets Tasks to the “Completed” status whenever their associated Leads are set to any Closed status. Make sure your trigger is bulkified - there should be no SOQL queries inside any loops!

My Trigger is as follows:-

trigger LeadClosedStatus on Lead (after insert, after update) {
    SET<ID> listNewLead = new SET<ID>();
    LIST<Task> newTasks = new LIST<Task>();
    if(Trigger.isInsert) {
        if(Trigger.isafter) {
                for(Lead newLead : Trigger.new) {
                listNewLead.add(newLead.Id);
                Task t = new Task();
                t.Status = newLead.Status;
                t.WhoId  = newLead.Id;
                newTasks.add(t);
        }
               insert newTasks;
     }     
 }


    LIST<Lead> leadClosedStatus = [SELECT ID, Status
                                    FROM Lead 
                                    WHERE Status LIKE '%Closed%'];

    MAP<ID, Lead> leadMap = new MAP<ID, Lead>();
    for(Lead leadMapClosed : leadClosedStatus) {
        leadMap.put(leadMapClosed.Id, leadMapClosed);
    }

    MAP<ID, Task> taskMap = new MAP<ID, Task>();
    for(Task UpdateTask : newTasks) {
        taskMap.put(updateTask.ID, updateTask);
    }
    if(Trigger.isUpdate) {
        if(leadMap.size() > 0) {
            for (Task finalUpdate : taskMap.values()) {
                if(taskMap.get(finalUpdate.WhoId).Status != 'Closed') {
                    finalUpdate.Status = 'Completed';
                }
            }
        }
    }
    update TaskMap.values();
}

It is not giving me an error but it is not updating the task to Closed or Completed status after the Lead is updated to closed status. Please help

2 Answers 2

1

There are a lot of problems with this code that won't cause errors. Many flaws won't: as here, flaws in logic often result in code simply doing nothing, or behaving strangely without throwing errors. In those situations, it's critical to read your logic carefully and closely, mapping out the pathway that records follow as your code executes.

Writing unit tests is also often a helpful way to pinpoint the spots at which your logic goes wrong.

Let's look at what is going on in this trigger.

trigger LeadClosedStatus on Lead (after insert, after update) {
    SET<ID> listNewLead = new SET<ID>();
    LIST<Task> newTasks = new LIST<Task>();
    if(Trigger.isInsert) {
        if(Trigger.isafter) {
                for(Lead newLead : Trigger.new) {
                listNewLead.add(newLead.Id);

listNewLead is never used. Why is it here?

                Task t = new Task();
                t.Status = newLead.Status;
                t.WhoId  = newLead.Id;
                newTasks.add(t);
        }
               insert newTasks;

This creation of new Tasks is not part of the requirement shown to us, so I can't evaluate whether it's right by those standards or not. From a business-process standpoint, I don't think it makes a lot of sense to add a new Task that just mirrors a Lead's Status every time a Lead is inserted.

     }     
 }


    LIST<Lead> leadClosedStatus = [SELECT ID, Status
                                    FROM Lead 
                                    WHERE Status LIKE '%Closed%'];

This may or may not be the right way to find "any closed Lead status" as specified by your exercise. Closed is an attribute of Opportunity Stages, not Lead Statuses. Unless you've been given a list of valid Lead Statuses and there is more than one that contains the word "Closed", I would interpret this as a need to query the LeadStatus object for status values that have IsConverted set to true. You should consider asking for clarification here.

    MAP<ID, Lead> leadMap = new MAP<ID, Lead>();
    for(Lead leadMapClosed : leadClosedStatus) {
        leadMap.put(leadMapClosed.Id, leadMapClosed);
    }

    MAP<ID, Task> taskMap = new MAP<ID, Task>();
    for(Task UpdateTask : newTasks) {
        taskMap.put(updateTask.ID, updateTask);
    }

Both of these loops are unneeded. You can create a Map<Id, sObject> from a List<sObject> with a standard constructor:

Map<Id, sObject> objectMap = new Map<Id, sObject>(sobjectList);

where sObject is any sObject.

However, there's a deeper logical error here: you're populating taskMap only with the brand-new Tasks you just created, not with the existing Tasks associated with the updated Leads in your database. That's not what your requirement says to do. You'll need to write a new query here to find Tasks by their WhoId being one of the Leads in Trigger.new.

    if(Trigger.isUpdate) {
        if(leadMap.size() > 0) {

Why are you checking the size of leadMap? You're iterating over taskMap, and iterating over an empty collection simply does nothing.

            for (Task finalUpdate : taskMap.values()) {
                if(taskMap.get(finalUpdate.WhoId).Status != 'Closed') {
                    finalUpdate.Status = 'Completed';
                }
            }

This logic does not make sense. You're iterating over the Tasks you created earlier and setting each Task's status to "Completed" if the status is anything other than "Closed". That's not your requirement.

Once you make the above changes to query the other Tasks you need, you'll need to iterate over those Tasks and make changes to their statuses based on the statuses of their associated Leads.

You should do some searching on SFSE for examples of the "collect-query-update" pattern that you should be applying here. Framing your queries carefully will result in you having to write relatively little logic. Ask yourself at each step: what set of records do I need to work on here? How do I identify those records, and can I do it in SOQL, Apex, or both?

        }
    }
    update TaskMap.values();
}
0

If you are wanting to set all tasks related to a Lead to complete when the Lead Status is changed to "Closed", then this could be done by querying all open tasks where whoId = the lead Id. Then you can iterate over the list, assign a complete status and update.

trigger LeadClosedStatus on Lead (after insert, after update) {
    Set<Id> listNewLead = new Set<Id>(); 
    if(trigger.isUpdate){
        if(trigger.isAfter){
            for(Lead newLead : Trigger.new) {
                if(newLead.status == 'Unqualified'){
                    listNewLead.add(newLead.Id);
                }
            }

            LIST<Task> relatedTasks = [SELECT ID, Status
                                           FROM Task 
                                           WHERE WhoId IN :listNewLead 
                                           AND Status != 'Completed'];
            for(Task t :relatedTasks){
                t.status = 'Completed';
            }
            update relatedTasks;
        }
    }
}

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.