2

I'm trying to build a trigger that will take the value of a Child Object on the Opportunity and write that value to a field on the Opportunity Level.

There are no errors and it seems to run successfully but when I check the Opportunity afterwards the field "Status__c" was not updated.

This is my first attempt at writing a trigger and any help would be greatly appreciated!

trigger updateStatusOnAccountAndOpp on Customer_Success__c (after update, after insert) {
// Find all the customer success records that have a standing assigned.
List<Customer_Success__c> accountsAndOppsToUpdate = [SELECT Id, Standing__c, Opportunity__r.Status__c
    FROM Customer_Success__c
    WHERE Standing__c = 'Good' OR Standing__c = 'Acceptable' OR Standing__c = 'Poor'];
for (Customer_Success__c currentCSRecord : accountsAndOppsToUpdate) {
    if(recursiveTriggerPrevent.runonce()){
    if (currentCSRecord.Standing__c == 'Good') {
        currentCSRecord.Opportunity__r.Status__c = '/img/samples/flag_green.gif';
        update currentCSRecord;
    } else if (currentCSRecord.Standing__c == 'Acceptable') {
        currentCSRecord.Opportunity__r.Status__c = '/img/samples/flag_yellow.gif';
        update currentCSRecord;
    } else {
        currentCSRecord.Opportunity__r.Status__c = '/img/samples/flag_red.gif';
        update currentCSRecord;
    }
   }
  }
}

1 Answer 1

3

You are going to run into issues with this trigger as you are always querying the entire object every time it is invoked... You should only be evaluating records within the trigger...

Although there are many issues in your trigger, the main reason why it was not updating the field on the Opportunity is that you cannot update related object fields via the relationship on the object being update - which means Opportunity__r.Name = xxx will not update the Opportunity

You are also violating the DML inside of a loop.

I assume you went down the path of the query in an after trigger due to attempting to update the records in the trigger, now that you know this will not work it changes the perspective of how you will go about it.

Here is how I would do it:

trigger updateStatusOnAccountAndOpp on Customer_Success__c (after update, after insert) {

    Map<ID,Opportunity> oppsToUpdate = new Map<Id,Opportunity>();

    for(Customer_Success__c cs : trigger.new){
        if(oppsToUpdate.containsKey(cs.Opportunity__c)) continue; //already done - But what if there are multiple Status' for the same opp - this is your decision to make??
        Opportutnity oppToUpdate = new Opportunity(id = cs.Opportunity__c);

        if (cs.Standing__c == 'Good') {
            oppToUpdate.Status__c = '/img/samples/flag_green.gif';
        } else if (cs.Standing__c == 'Acceptable') {
            oppToUpdate.Status__c = '/img/samples/flag_yellow.gif';
        } else if(cs.Standing__c == 'Poor'){
            oppToUpdate.Status__c = '/img/samples/flag_red.gif';
        }

        oppsToUpdate.put(cs.Opportunity__c,oppToUpdate);

    }

    update oppsToUpdate.values();

}
2
  • Thanks Eric! That did the trick. If there is more than one status per opportunity, is there a way to have it choose the opp with the lowest status?
    – MarcM
    Aug 22, 2015 at 1:45
  • Sure, you can add that logic into the trigger. just pull the opp from the map and check the value of the status__c field and see if it is "lower" than what the current context record wants to set it to. If it is not, change the status. Please mark as accepted if the answer solves your issue so the question does not keep surfacing
    – Eric
    Aug 22, 2015 at 1:47

You must log in to answer this question.

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