[SalesForce] Add result of several calculations to total & store in variable

Maybe I'm approaching this in completely the wrong way but..

In a trigger, I need to calculate an amount multiplied by a % which has been multiplied by an integer. For example if the amount is 100 and the percentage is 25% then in loop 1, the integer is 1 and the result is 25, in loop 2 the integer is 2 and the result is 50 etc.

Each time the calculation produces an amount, I want to add that amount to a total and store that total in a variable. But I can't work out how to keep adding each amount that's calculated to the total?

I'll then subtract that total from another amount and use that figure in additional calculations. The amounts that are being calculated are populating the Monthly_Settlement1__c field.

I'm doing the calculations in a loop so I can't use an SOQL query to SUM the amount from each record which has been created as part of the process.

For context, this is a calculation that spreads an annual revenue figure over a set number of months, taking into account a ramp up period when the revenue is reduced by a percentage and increases by equal increments.

Here's my code, the percentage is stored as Decimal 'Increment'

trigger MRFv2 on Opportunity (after insert, after update) {

    List<WEID__c> weids = WEID__c.getall().values();
    Set<Id> validRecordTypeIds = new Set<Id>();

    // add Opportunity Record Type Ids from Custom Setting to list of valid Ids      
    for(WEID__c weid: weids) {
        try {
            validRecordTypeIds.add(weid.WEOppId__c);
        } catch (System.StringException e) {
            System.debug(
                System.LoggingLevel.ERROR,
                'Invalid Record Type Id ' + weid.WEOppId__c
            );
        }
    }

    List<Opportunity> insOpps = new List<Opportunity>();
    List<Opportunity> upOpps = new List<Opportunity>();
    Map<Id, Integer> rampDuration = new Map<Id, Integer>();
    Map<Id,Integer> forecastDuration = new Map<Id,Integer>();
    Map<Integer,String> monthName = new Map<Integer,String>{1 => 'January', 2 => 'February', 3 => 'March', 4 => 'April', 5 => 'May', 6 => 'June', 7 => 'July', 8 => 'August', 9 => 'September', 10 => 'October', 11 => 'November', 12 => 'December'};
    List<Monthly_Revenue_Forecast__c> newMRFs = new List<Monthly_Revenue_Forecast__c>();
    List<Monthly_Revenue_Forecast__c> existMRFs = new List<Monthly_Revenue_Forecast__c>();

    for(Opportunity o : Trigger.New){

        if(validRecordTypeIds.contains(o.RecordTypeId))
        {
            try{
                Opportunity oldO = Trigger.OldMap.get(o.Id);

                if(oldO.CloseDate != o.CloseDate
                    ||
                    oldO.Implementation_Revenue__c != o.Implementation_Revenue__c
                    ||
                    oldO.Forecast_Full_Service_Revenue_Date__c != o.Forecast_Full_Service_Revenue_Date__c
                    ||
                    oldO.FSR_End_Date__c != o.FSR_End_Date__c)
                {
                    upOpps.add(o);
                    rampDuration.put(o.Id , o.Implementation_Revenue__c.monthsBetween(o.Forecast_Full_Service_Revenue_Date__c));
                    forecastDuration.put(o.Id, o.Implementation_Revenue__c.monthsBetween(o.FSR_End_Date__c));
                }
                //if old.Map is null, record has been inserted & MRF records should be added
            }catch(system.NullPointerException e){
                insOpps.add(o);
                rampDuration.put(o.Id , o.Implementation_Revenue__c.monthsBetween(o.Forecast_Full_Service_Revenue_Date__c));
                forecastDuration.put(o.Id, o.Implementation_Revenue__c.monthsBetween(o.FSR_End_Date__c));
            }
        }
    }

    if(insOpps.size() > 0){

    //deleted section

    }
    if(upOpps.size() > 0){

        for(Opportunity o : [SELECT Id,
                            (SELECT Id FROM Monthly_Revenue_Forecasts__r) FROM Opportunity
                              WHERE Id IN :upOpps])
        {               
            system.debug('o.Monthly_Revenue_Forecasts__r size is ' + o.Monthly_Revenue_Forecasts__r.size());
            if(o.Monthly_Revenue_Forecasts__r.size()> 0){
                existMRFs.addAll(o.Monthly_Revenue_Forecasts__r);
                delete existMRFs;
            }
        }

        for(Opportunity o : upOpps){

            Date ic = o.Implementation_Revenue__c;
            Integer icm = o.Implementation_Revenue__c.month();

            //Ramp calculations
            Decimal increment = o.Implementation_Revenue_as_a_of_FSR__c;
            Integer rdur = (1 / increment).setscale(0, roundingMode.DOWN);
            //assume that if MRF duration is capped then so is the Annual Settlement figure
            Decimal monthlySett = o.Annual_Settlement_Value__c / forecastDuration.get(o.Id);

            //FSR calculations
            Integer fsrDur = forecastDuration.get(o.Id) - rdur;

            //add Monthly Forecast records for 'ramp' months
            for(Integer m = 0; m < icm + rDur + 1; m++){

                Monthly_Revenue_Forecast__c fm = new Monthly_Revenue_Forecast__c();
                fm.Opportunity__c = o.Id;
                fm.Name = monthName.get(ic.addMonths(m).month()) +' '+ ic.addMonths(m).year();
                fm.Revenue_Date__c = ic.addMonths(m + 1).toStartOfMonth() - 1;
                //fm.Monthly_Settlement1__c = (monthlySett*(increment*m + 1));
                //if test for empty list?
                newMRFs.add(fm);
            }

            //Decimal rampSett = ;
            //Decimal remSett = ;

            for(Integer m = icm + rDur; m < icm + fsrDur + 1; m++){

            }
        }        
    }
    insert newMRFS;
}

Best Answer

In a trigger, I need to calculate an amount multiplied by a % which has been multiplied by an integer. For example if the amount is 100 and the percentage is 25% then in loop 1, the integer is 1 and the result is 25, in loop 2 the integer is 2 and the result is 50 etc.

Each time the calculation produces an amount, I want to add that amount to a total and store that total in a variable. But I can't work out how to keep adding each amount that's calculated to the total?

If I understand your question correctly, here's one possible solution to it.

list<decimal>dec = new list<decimal>();
Decimal d = 0.00;
list<integer>int = new list<integer>();
Decimal pct = .25;
Decimal LoopTotal = 0.00;
integer i = 0;
Map<integer,decimal>MonthMap = new map<integer,decimal>();

For(decimal d1:dec){
   
   d = d1*pct*int[i];

   LoopTotal = LoopTotal + d;

   MonthMap.put(i,LoopTotal);

   i++;

}

Note: If your list of integers is for months, you can easily populate that for record 0 to be 1 (Jan) and record 11 to be 12 (Dec) to cover your 12 month range. Putting this in a map allows you to retrieve it for each separate month throughout the 12 month period. You could also vary the percentage by using a list in a similar fashion for that value too.

I'll then subtract that total from another amount and use that figure in additional calculations. The amounts that are being calculated are populating the Monthly_Settlement1__c field.

The above is why I've put everything in a map since I don't know when or where you'll need it. That part wasn't at all clear to me, but the above should be adaptable to most any situation I can think of.

Related Topic