2

I'm fairly new to coding and my admin has asked me to create a couple of triggers to update a multi-select picklist for our Opportunity page or maybe I could combine them into one. I have created the pseudo code for the triggers I need to code, but I'm struggling with the syntax. The following is my pseudo code:

trigger UpdateOpportunity on Opportunity (before insert, before update) {    
    for (Opportunity)    
        if (win_reason = no competitor)     
            then    
            Competitor(s) = No Competiton/Sole Source

        if (Unsolicited Bid = "Yes")    
            then    
            Competitor(s) = No Competiton/Sole Source    
}

Any kind of help is greatly appreciated!

4
  • 1
    What part of the syntax are you struggling with? Your pseudo code looks pretty good in terms of structure. Aug 7, 2014 at 15:21
  • What's the MultiSelect Field? Competitor__c? MutliSelect Fields have a special syntax where as Picklist & Text fields follow the same rules Aug 7, 2014 at 15:35
  • Thanks Alex. I guess I'm looking for advice on the logic. Can you use If/then statements? Is that the correct way to go about, if a=b then c=d? I do realize that I need to use the actually API name for the fields but any other advice? Aug 7, 2014 at 15:39
  • That is correct, amatorVitae. Aug 7, 2014 at 15:39

1 Answer 1

5

Here's some the gaps filled in. I am assuming that Competitor__c is your MultiSelect field, that Win_Reason__c is a Picklist and that Unsolicited_Bid__c is a Checkbox. If not, adjust accordingly.

------------------------------------------------------
-- Field Type    *  Data Type                       --
------------------------------------------------------
-- Picklist      *  String                          --
-- Text          *  String                          --
-- Checkbox      *  Boolean                         --
-- MultiSelect   *  String with ; to delimit values --
-- Number        *  Decimal                         --
-- Currency      *  Decimal                         --
-- Date          *  Date                            --
-- Datetime      *  Datetime                        --
-- Master-Detail *  Id                              --
-- Loookup       *  Id                              --
-- TextArea      *  String                          --
------------------------------------------------------

trigger UpdateOpportunity on Opportunity (before insert, before update){    
    for(Opportunity opp :Trigger.new){ 

        // MultiSelect Fields are a single String with values delimited by a semi-colon

        // TODO: Double check Field API Names
        // TODO: Double check Field values spelling for Case Sensitivity 
        if(opp.win_reason__c == 'No Competitor'){   
            opp.Competitor__c = 'No Competiton;Sole Source'; 
        }
        if(opp.Unsolicited_Bid__c == true){  
            opp.Competitor__c = 'No Competiton;Sole Source';
        } 
    }   
}

Here's some helpful docs when working with Triggers:


Update

To neatly add the condition not to have the above execute if the Stage = 0%, I will introduce using an Apex Class static function. Separating what we are doing into individual methods simplifies logic and code-readability.

First let's create an Apex Class:

public Class OpportunityMethods {

    public static void updateOppCompetitor(Opportunity opp){
        if(opp.win_reason__c == 'No Competitor'){   
            opp.Competitor__c = 'No Competiton;Sole Source'; 
        }
        if(opp.Unsolicited_Bid__c == true){  
            opp.Competitor__c = 'No Competiton;Sole Source';
        } 
    }

}

Now rewrite the trigger to use the OpportunityMethods.updateOppCompetitor(...) method:

trigger UpdateOpportunity on Opportunity (before insert, before update){    
    for(Opportunity opp: trigger.new){
        OpportunityMethods.updateCompetitor(opp);
    }  
}

Cool. The rewritten trigger does look a bit simpler. But we still need to only updateOppCompetitor if the opp.StageName != 0 %. (Or you might be referring to the opp.Probability = 0 where the Opportunity Probability is a decimal, so adjust accordingly.) To do this, let's add a simple if statement and execute updateCompetitor(opp) if opp.StageName != '0 %':

trigger UpdateOpportunity on Opportunity (before insert, before update){    
    for(Opportunity opp: trigger.new){
        if(opp.StageName != '0 %'){
            OpportunityMethods.updateOppCompetitor(opp);  
        }
    }  
}

Double cool. That does exactly what we want it to do, and just reading the code tell us simply what it's doing.

Being astute, we notice, "Hey, could put that StageName-condition in the updateCompetitor method directly?" And the answer is, "Yes. Furthermore, instead of sending each Opportunity through the method, we could send the whole List<Opportunity> through and do all the processing there in a method."

One path to realizing this is through the following: First let's add to our OpportunityMethods class

public Class OpportunityMethods {

    public static void updateOppCompetitor(Opportunity opp){
        if(opp.win_reason__c == 'No Competitor'){   
            opp.Competitor__c = 'No Competiton;Sole Source'; 
        }
        if(opp.Unsolicited_Bid__c == true){  
            opp.Competitor__c = 'No Competiton;Sole Source';
        } 
    }

    public static void updateComptetitor(List<Opportunity> newList){
        for(Opportunity op :newList){
            if(opp.StageName != '0 %'){
                OpportunityMethods.updateOppCompetitor(opp);  
            }
        }
    }
}

And the trigger simplifies to:

trigger UpdateOpportunity on Opportunity (before insert, before update){    
    OpportunityMethods.updateCompetitor(trigger.new);  
}

Notice how we re-used the updateOppCompetitor-method in the updateCompetitor-method. We already did the work of writing the method, so let's reuse what we have. Also, with any type of code, there are many ways to go about accomplishing the same end result. The key to good programming is having the flexibility to accomplish the same results using various paths -- sometimes certain paths offer a much shorter route than others, and each path-lengths depends on the destination. When Limits are imposed on a situations, cough cough Governor Limits, some paths may be closed off, so it's handy to know alternative routes when necessary.

3
  • Hi amatorVitae, I'm back for help. I would like to now perform this trigger on every stage besides when a Lead is = 0%. How would I exclude this trigger from functioning when Stage= Lead 0%? Thanks again. Aug 12, 2014 at 17:25
  • 1
    Check out the update Aug 13, 2014 at 16:01
  • amatorVitae, thank you so much for your help and the extensiveness in your answer. This is exactly what I was looking for. Can I please take you out for a beer sometimes or something? Or maybe I'll just listen to your music. Any way to pay you back, my friend. Aug 13, 2014 at 17:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .