1

The Trigger below i'm getting error when my IF statement has more that 2 conditions, I Understand it is a recursion issue. However not sure how to fix this, so i can include all the conditions below and more.

trigger OppToUpdate on Opportunity (after update) {
    //Create an Empty Opportunity List
    List<Opportunity> opps = new List<Opportunity>();
    //Create an Empty Opportunity List for the Update Opportunity that Pertain to the specific Account
    List<Opportunity> oppToUpdate = new List<Opportunity>();
    //Create a set collector for Account's associated to the opportunity
    Set<Id> associatedAccId = new Set<Id>();

    for(Opportunity opp : Trigger.New){
        associatedAccId.add(opp.AccountId);
    }

    opps=[SELECT Id, AccountId, RFP_Response_Status__c, StageName 
          From Opportunity  
          WHERE AccountId in : associatedAccId];

    for(Opportunity opp : opps){
        if(opp.RFP_Response_Status__c != 'Out of Business'
           || opp.RFP_Response_Status__c != 'Do NOT Call'
           || opp.RFP_Response_Status__c != 'sub-contractor'
           || opp.RFP_Response_Status__c != 'Bad Number'
           && (opp.StageName !='Closed Won' || opp.StageName !='Closed Lost')){
            opp.RFP_Response_Status__c = 'Out of Business';
            opp.StageName = 'Closed Lost';
            oppToUpdate.add(opp);
        }
    }
    if(!oppToUpdate.isEmpty()){
          Update oppToUpdate;  
    }
}
5

First of all, your if statement is incorrect: using OR means that this branch will always execute. For example, if RFP Response Status is "Out of business", then it will not be "Bad Number". You need to use && (and) instead of || (or).

   if(opp.RFP_Response_Status__c != 'Out of Business'
       && opp.RFP_Response_Status__c != 'Do NOT Call'
       && opp.RFP_Response_Status__c != 'sub-contractor'
       && opp.RFP_Response_Status__c != 'Bad Number'
       && opp.StageName !='Closed Won'
       && opp.StageName !='Closed Lost') {

Also, you can build all of this in to your query:

Opportunity[] opps = [SELECT Id FROM Opportunity WHERE AccountId IN :associatedAccId AND
                      RFP_Response_Status__c NOT IN ('Out of Business','Do NOT CALL',
                      'sub-contractor','Bad Number') AND
                      StageName NOT IN ('Closed Won','Closed Lost')];

Also, you should probably specifically exclude opportunities that are already in the trigger (or process them independently).

Opportunity[] opps = [SELECT Id FROM Opportunity WHERE AccountId IN :associatedAccId AND
                      RFP_Response_Status__c NOT IN ('Out of Business','Do NOT CALL',
                      'sub-contractor','Bad Number') AND
                      StageName NOT IN ('Closed Won','Closed Lost')
                      AND Id NOT IN :Trigger.new];

So, putting this all together gives you:

trigger OppToUpdate on Opportunity (after update) {
    //Create a set collector for Account's associated to the opportunity
    Set<Id> associatedAccId = new Set<Id>();
    for(Opportunity opp : Trigger.New){
        associatedAccId.add(opp.AccountId);
    }

    Opportunity[] opps = [SELECT Id FROM Opportunity WHERE AccountId IN :associatedAccId AND
                          RFP_Response_Status__c NOT IN ('Out of Business','Do NOT CALL',
                          'sub-contractor','Bad Number') AND
                          StageName NOT IN ('Closed Won','Closed Lost')
                          AND Id NOT IN :Trigger.new];

    for(Opportunity opp : opps){
        opp.RFP_Response_Status__c = 'Out of Business';
        opp.StageName = 'Closed Lost';
    }
    update opps;
}
  • Excellent !! it works. Thanks – Templar May 22 '16 at 18:14
  • Is there a way to Make the opp.RFP_Response_Status__c = the value the user choose from the picklist rather than assigning a default one? Also the value user pick from the pick list get passed to the rest of the opportunities related to the same Account ID. – Templar May 23 '16 at 14:15
  • @Templar Something like Map<Id, String> rfpResStatus = new Map<Id, String>(); for(Opportunity opp: Trigger.new) { rfpResStatus.put(opp.AccountId, opp.RFP_Response_Status__c); } ... for(Opportunity opp: opps) { opp.RFP_Response_Status__c = rfpResStatus.get(opp.AccountId); opp.StageName = 'Closed Lost'; } update opps; You'll also want to add AccountId to the opps query so you can look up the correct account. – sfdcfox May 23 '16 at 15:42
  • it is working when you have one Opp, However when 2 or more OPP the moment I change the RFP_Response_Status__c to any other different Status other than the above 4 ('Out of Business', 'Do NOT CALL','sub-contractor','Bad Contact Number'), it is marking all the related OPPs to that account as Closed-Lost. It should only mark opp(s) closed-Lost with the status is one of the 4 picklist values AND stage <> close Lost || Close Won. – Templar May 25 '16 at 18:48
  • @Templar If I understand your comment correctly, it sounds like you need to adjust your first loop: for(Opportunity opp: Trigger.new) { if(opp.RFP_Response_Status__c == 'out of business' || opp.RFP_Response_Status__c == 'do not call' ...) { associatedAccId.add(opp.AccountId); } } – sfdcfox May 25 '16 at 19:14

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.