[SalesForce] Trigger to update Opportunity stage from Task subject

I'm looking to conditionally update the Opportunity stage when the Task subject (Opportunity & Task belong to same Account) is changed:

Here is the task page, field of concern is Subject:

Image1

When the subject is changed to 'Send Email', the Opportunity stage linked to the same account auto updates to 'Qualification', for example. Here, the Opportunity and the Task are for Account ABC:

Image2

Now this is what I've done so far; the following is the underdeveloped Apex code to auto update the stage:

public class UpdateOpp {

   public static void update_oppstage(task[] tasks) {

       for (Task t :tasks) {

           if (t.subject == 'Send Letter') {
            // update (account) corresponding opportunity stage field to say 'Qualification'          
            }        
        }
    }
}

And finally, the trigger code:

trigger TaskSubject on Task (after update) {

    Task[] tasks = Trigger.new;
    UpdateOpp.update_oppstage(tasks);
}

I need help to update the stage to a defined value for the corresponding opportunity. Thanks for your time.

Important Update: My task subject has custom entries in the comboBox – Call EJF, Email Centurion, Follow up Merion, etc. Opportunity names are created meaningfully for an account and the opp name will have one of these (EJF, Centurion, Merion) matching names. So when a task with subject Email EJF is created for account ABC, the opp for the same account ABC with opp name 'EJF' should auto update the opp stage to 'Qualification'.

This is more complex but the basic subject change updates opportunity stage remains unchanged.

Best Answer

Hope the below code helps!

trigger TaskSubject on Task (after update, after insert) {

set<id> accountIdSet = new set<id>();
//capture all the subject names in a set
//set<string> subjectName = new set<string>{'Call EJF','Email Centurion','Initiate Merion'};
map<id, list<opportunity>> opptyMap = new map<id, list<opportunity>>();
list<opportunity> updateOppList = new list<opportunity>();

//get those tasks where the tasks are related to account. Capture the account IDs in a set.
for(task t: trigger.new){
            string tempId = string.valueOf(t.WhatId);
    if(tempId.startsWith('001')){
        accountIdSet.add(t.whatId);
    }
}

//If we have any account IDs then get the associated opportuity and store the one account to many opportunity in a map<id, list<opportunity>>
if(accountIdSet.size()>0){
    for(opportunity opp:[select Name, stageName, accountid from opportunity where accountid IN :accountIdSet]){
        if(opptyMap.containsKey(opp.accountId)){
            list<opportunity> oppList = opptyMap.get(opp.accountId);
            oppList.add(opp);
            opptyMap.put(opp.accountId, oppList);
        }else{
            list<opportunity> newOppList = new list<opportunity>();
            newOppList.add(opp);
            opptyMap.put(opp.accountId, newOppList);
        }
    }
}

//If we get the opportunities then change the stage.
if(Trigger.isUpdate && opptyMap.size()>0){
    for(task t: trigger.new){

 //Check if the subject of the task is one among the set 
 //and also confirm that the subject has been changed.

        if(t.subject != trigger.oldMap.get(t.id).subject && opptyMap.containsKey(t.whatId)){

  //iterate thru the list of the opportunity associated with that account 
  //and check which of the opportunity contains the task subject in the 
   //opportunity name and update the stage to qualification

            for(opportunity oppty: opptyMap.get(t.whatId)){
                if(oppty.name.contains(t.subject)){
                    oppty.stageName='Qualification';
                    updateOppList.add(oppty);
                }
            }
        }
    }
}
if(Trigger.isInsert && opptyMap.size()>0){
     for(task t: trigger.new){
            if(opptyMap.containsKey(t.whatId)){
                for(opportunity oppty: opptyMap.get(t.whatId)){
                   if(oppty.name.contains(t.subject)){
                      oppty.stageName='Qualification';
                      updateOppList.add(oppty);
                   }
               }
            }
        }
    }
//update the oppties
if(updateOppList.size()>0){
    update updateOppList;
}
}

EDIT:
This code is working. I followed the below flow: Create an account(test account) --> Create a task for this account (test account) and make sure the subject is not 'Initiate Merion'.
create an opportunity (make sure the stage is not qualification) for the same account, name it 'test oppty Initiate Merion'.
Now edit the task created, change the subject to 'Initiate Merion'. You can now see that the Opportunity stage has been changed to 'Qualification'.

EDIT 2
Added an after insert event. Also the one more code block to handle the insert and update events seperately

EDIT 3 Task subject need not necessarily be from a set of predefined strings. As long as task subject is part of Opp name, stage must be updated

Related Topic