0

We have a custom object, Strategy__c, that has a one-to-many lookup relationship to opportunities, so in order to recalculate opp rollup amounts (that are updated via a PB+flow) when the user changes the Strategy selected in an Opportunity I'm trying to use a trigger to subtract the opportunity amount registered in the corresponding field (open, won or lost rollup) on the previous strategy. The below code is unfortunately not working (doesn't update any of the strategy fields) -

trigger OpportunityTrigger on Opportunity (before update) {

List<Opportunity> changedOpps = new List<Opportunity>();
for (Opportunity oppty : Trigger.new) {
    Opportunity oldOpp = Trigger.oldMap.get(oppty.Id);
    if (oppty.Strategy__c != oldOpp.Strategy__c){
        changedOpps.add(oldOpp);
    }
}
system.debug('opps ' + changedOpps);

if (changedOpps.size() > 0){
List<Strategy__c> stratsToUpdate =  new List<Strategy__c>();
    
    for (Opportunity opp : changedOpps) {
        Strategy__c strat = new Strategy__c();
        strat.Id = opp.Strategy__c;
        
        if (!opp.IsClosed && (strat.Opportunities_Open__c != null)) {
            strat.Opportunities_Open__c = strat.Opportunities_Open__c - opp.Amount;
            stratsToUpdate.add(strat);
        } else if (opp.IsWon && (strat.Opportunities_Won__c != null)) {
            strat.Opportunities_Won__c = strat.Opportunities_Won__c - opp.Amount;
            stratsToUpdate.add(strat);
        } else if (!opp.IsWon && (strat.Opportunities_Lost__c != null)) {
            strat.Opportunities_Lost__c = strat.Opportunities_Lost__c - opp.Amount; 
            stratsToUpdate.add(strat);
        }
    }  
    system.debug('strategies ' + stratsToUpdate);
    update stratsToUpdate;   
  }
}

The debug logs show the stratsToUpdate list comes up empty, but I can't figure out why since the variable "strat" does have a value (sorry if this is too newb a question, I'm an admin in learning). Any help would be greatly appreciated!

update: moved it to an after trigger, no dice

4
  • Cross object logic should go in after contexts.
    – Adrian Larson
    Aug 24 '20 at 17:41
  • @AdrianLarson I thought an after update trigger wouldn't hold the original values of the record before the update?
    – gamund
    Aug 24 '20 at 17:56
  • you never query for Strategy__c - those recs are not in trigger context
    – cropredy
    Aug 24 '20 at 17:57
  • Your oldMap will still be the same...
    – Adrian Larson
    Aug 24 '20 at 17:58
1

You are creating new strategy instances and then you are checking if Opportunities_Open__c / Opportunities_Won__c / Opportunities_Lost__c fields on these strategies are not null in order to populate stratsToUpdate variable. So issues is that these new strategy instances will not have any data and it will not go inside the if conditions which will result in empty stratsToUpdate.

To calculate the value of Opportunities_Open__c / Opportunities_Won__c / Opportunities_Lost__c fields, you need to first query them as your calculation and if condition both depends on the these values.

Please try something like below code:

trigger OpportunityTrigger on Opportunity (before update) {

List<Opportunity> changedOpps = new List<Opportunity>();
List<Id> strategiesIds = new List<Id>();
for (Opportunity oppty : Trigger.new) {
    Opportunity oldOpp = Trigger.oldMap.get(oppty.Id);
    if (oppty.Strategy__c != oldOpp.Strategy__c){
        changedOpps.add(oldOpp);
        strategiesIds.add(oldOpp.Strategy__c);
    }
}
system.debug('opps ' + changedOpps);

if (changedOpps.size() > 0){
    Map<Id, Strategy__c> strategyMap = new Map<Id,Strategy__c>([select id,Opportunities_Open__c , Opportunities_Won__c, Opportunities_Lost__c from Strategy__c where id IN: oppoStrategiesIds.values()]);

    List<Strategy__c> stratsToUpdate = new List<Strategy__c>();

    for (Opportunity opp : changedOpps) {
        Strategy__c strat = strategyMap.get(opp.Strategy__c);
        
        if (!opp.IsClosed && (strat.Opportunities_Open__c != null)) {
            strat.Opportunities_Open__c = strat.Opportunities_Open__c - opp.Amount;
            stratsToUpdate.add(strat);
        } else if (opp.IsWon && (strat.Opportunities_Won__c != null)) {
            strat.Opportunities_Won__c = strat.Opportunities_Won__c - opp.Amount;
            stratsToUpdate.add(strat);
        } else if (!opp.IsWon && (strat.Opportunities_Lost__c != null)) {
            strat.Opportunities_Lost__c = strat.Opportunities_Lost__c - opp.Amount; 
            stratsToUpdate.add(strat);
        }
    }  
    system.debug('strategies ' + stratsToUpdate);
    update stratsToUpdate;   
  }
}
  1. Create a map of strategies by fetching them using SOQL with all the required fields. To fetch specific strategies which are going to change, create a list of strategy id first.
  2. instead of creating new strategy instances, get the strategy from the map created in first step and use it in the logic.

I would suggest you to do such updates in after update as in future if you add something which can change the data post this logic is run or if there are any other calculations to be done before running this, you will not have to think about sequencing.

1
  • thank you, that worked perfectly!!
    – gamund
    Aug 24 '20 at 20:01

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.