function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Mathew Andresen 5Mathew Andresen 5 

year over year changes

Hi,

I have a map/list with year over year sales by quarter for accounts.  I want to calculate the change year over year.  For example if Q1 prior year is 100 and Q1 current year is 150 then the growth should be 150.

Currently what I'm doing is changing my map into a list and then doing the calculation based on the position in the list, but I'm wondering if there is a better way to do this. 

Any thoughts?
 
for (PivotTimeSeries_Class.PivotRowWrapper wrapper :partialRowList) {
            List<decimal> salesList = new List<decimal>();
            for (string period:periodYearList) {
                salesList.add(wrapper.amountMap.get(period));
            }
        	map<string, decimal> growthMap = new map<string, decimal>();
            decimal Y1Total;
            decimal Y2Total;
            decimal q1Growth;
            decimal q2Growth;
            decimal q3Growth;
            decimal q4Growth;
            decimal YGrowth;
            
            Y1Total = salesList[0] + salesList[1] + salesList[2] + salesList[3];
            Y2Total = salesList[5] + salesList[6] + salesList[7] + salesList[8];

            wrapper.amountMap.put('Y1 Total', Y1Total);
            wrapper.amountMap.put('Y2 Total', Y2Total);
            if (salesList[0] != 0 && salesList[0] != NULL && salesList[4] != 0 && salesList[4] != NULL) { q1Growth = salesList[4]/salesList[0]*100 -100; } else { q1Growth = 0; } growthMap.put('P1Growth', q1Growth); 
            if (salesList[1] != 0 && salesList[1] != NULL && salesList[5] != 0 && salesList[5] != NULL) { q2Growth = salesList[5]/salesList[1]*100 -100; } else { q2Growth = 0; } growthMap.put('P2Growth', q2Growth); 
            if (salesList[2] != 0 && salesList[2] != NULL && salesList[6] != 0 && salesList[6] != NULL) { q3Growth = salesList[6]/salesList[2]*100 -100; } else { q3Growth = 0; } growthMap.put('P3Growth', q3Growth); 
            if (salesList[3] != 0 && salesList[3] != NULL && salesList[7] != 0 && salesList[7] != NULL) { q4Growth = salesList[7]/salesList[3]*100 -100; } else { q4Growth = 0; } growthMap.put('P4Growth', q4Growth); 
            if (Y1Total != 0 && Y2Total != 0) { YGrowth = Y2Total / Y1TOtal*100 -100; system.debug ('firing'); } else { YGrowth = 0; } growthMap.put('YoY Growth', YGrowth);
            system.debug('YGrowth = ' +YGrowth);
            sortList.add(new SortWrapper(new CompleteRowWrapper(wrapper, growthMap)));

        }
        sortList.sort();
        for (SortWrapper sorted:sortList) {
            CompleteRowList.add(sorted.wrapper);
        }

 
Best Answer chosen by Mathew Andresen 5
pconpcon
You could simplify this quite a bit by adding a getGrowth method
 
public static Decimal getGrowth(Decimal d, Decimal n) {
    if (n == 0 || d == 0) {
        return 0;
    }

    return n / d * 100 - 100;
}

Then this makes the rest of your code look like
 
for (PivotTimeSeries_Class.PivotRowWrapper wrapper : partialRowList) {
    List<Decimal> salesList = new List<Decimal>();

    for (String period : periodYearList) {
        salesList.add(wrapper.amountMap.get(period));
    }

    Decimal s0 = (salesList.get(0) == null) ? 0;
    Decimal s1 = (salesList.get(1) == null) ? 0;
    Decimal s2 = (salesList.get(2) == null) ? 0;
    Decimal s3 = (salesList.get(3) == null) ? 0;
    Decimal s4 = (salesList.get(4) == null) ? 0;
    Decimal s5 = (salesList.get(5) == null) ? 0;
    Decimal s6 = (salesList.get(6) == null) ? 0;
    Decimal s7 = (salesList.get(7) == null) ? 0;
    Decimal s8 = (salesList.get(8) == null) ? 0;
    
    Decimal y1Total = s0 + s1 + s2 + s3;
    Decimal y2Total = s5 + s6 + s7 + s8;

    wrapper.amountMap.put('Y1 Total', Y1Total);
    wrapper.amountMap.put('Y2 Total', Y2Total);

    Map<String, Decimal> growthMap = new Map<String, Decimal>();
    growthMap.put('P1Growth', getGrowth(s0, s4);
    growthMap.put('P2Growth', getGrowth(s1, s5);
    growthMap.put('P3Growth', getGrowth(s2, s6);
    growthMap.put('P4Growth', getGrowth(s3, s7);
    growthMap.put('YoY Growth', getGrowth(y1Total, y2Total));

    sortList.add(new SortWrapper(new CompleteRowWrapper(wrapper, growthMap)));

}
sortList.sort();

for (SortWrapper sorted : sortList) {
    completeRowList.add(sorted.wrapper);
}
NOTE: This code has not been tested and may contain typographical or logical errors

You could condense it down a bit more, but I think this is a better balance between readability and size.  If I were to make any additional changes, I would move you strings ('P1Growth', 'P2Growth', etc) into class level static variables to make it easier to reference and reduce the chance of typos.

All Answers

pconpcon
You could simplify this quite a bit by adding a getGrowth method
 
public static Decimal getGrowth(Decimal d, Decimal n) {
    if (n == 0 || d == 0) {
        return 0;
    }

    return n / d * 100 - 100;
}

Then this makes the rest of your code look like
 
for (PivotTimeSeries_Class.PivotRowWrapper wrapper : partialRowList) {
    List<Decimal> salesList = new List<Decimal>();

    for (String period : periodYearList) {
        salesList.add(wrapper.amountMap.get(period));
    }

    Decimal s0 = (salesList.get(0) == null) ? 0;
    Decimal s1 = (salesList.get(1) == null) ? 0;
    Decimal s2 = (salesList.get(2) == null) ? 0;
    Decimal s3 = (salesList.get(3) == null) ? 0;
    Decimal s4 = (salesList.get(4) == null) ? 0;
    Decimal s5 = (salesList.get(5) == null) ? 0;
    Decimal s6 = (salesList.get(6) == null) ? 0;
    Decimal s7 = (salesList.get(7) == null) ? 0;
    Decimal s8 = (salesList.get(8) == null) ? 0;
    
    Decimal y1Total = s0 + s1 + s2 + s3;
    Decimal y2Total = s5 + s6 + s7 + s8;

    wrapper.amountMap.put('Y1 Total', Y1Total);
    wrapper.amountMap.put('Y2 Total', Y2Total);

    Map<String, Decimal> growthMap = new Map<String, Decimal>();
    growthMap.put('P1Growth', getGrowth(s0, s4);
    growthMap.put('P2Growth', getGrowth(s1, s5);
    growthMap.put('P3Growth', getGrowth(s2, s6);
    growthMap.put('P4Growth', getGrowth(s3, s7);
    growthMap.put('YoY Growth', getGrowth(y1Total, y2Total));

    sortList.add(new SortWrapper(new CompleteRowWrapper(wrapper, growthMap)));

}
sortList.sort();

for (SortWrapper sorted : sortList) {
    completeRowList.add(sorted.wrapper);
}
NOTE: This code has not been tested and may contain typographical or logical errors

You could condense it down a bit more, but I think this is a better balance between readability and size.  If I were to make any additional changes, I would move you strings ('P1Growth', 'P2Growth', etc) into class level static variables to make it easier to reference and reduce the chance of typos.
This was selected as the best answer
Mathew Andresen 5Mathew Andresen 5
That's helpful thanks.  I'm trying to learn how to do things the right (or at least better) way and not just knock them out.