Skip to content
Advertisement

Accumulate monthly totals while looping

I have an array of data containing monthly amounts from the current year and the previous year. The previous year always has all of its amounts, but when a current/future month in the current year is iterated it has a null value. Here is an example:

[
    {
        "month": 1,
        "total_now": "3,000"
        "total_before": "2,000"
    },
    {
        "month": 2,
        "total_now": "1,000"
        "total_before": "3,000"
    },
    {
        "month": 3,
        "total_now": null 
        "total_before": "1,000"
    },
    ...
    {
        "month": 12,
        "total_now": null,
        "total_before": "20,422"
    },
]

This is my current code

public function loop_get(){
    $thn_now = date('Y'); 
    $thn_before = date('Y') -1; 
    $result = [];
    for ($month = 1; $month <= 12; $month++) {
        $result[] = [
            'month' => $month,
            'total_now' => $this->model->dbget($thn_now ,$month)->row()->total?? null
            'total_before' => $this->model->dbget($thn_before,$month )->row()->total?? null,
        ];
    }
}

How can I roll previous month amounts into current month to keep a running total month-to-month for each year? Also, as soon as a month returns a null amount, all previous amounts should be dropped and the month should show null for the rest of the year.

Desired output (assuming the current month is February):

[
    {
        "month": 1,
        "total_now": "3,000"
        "total_before": "2,000" 
    },
    {
        "month": 2,
        "total_now": "1,000" // arr[0] + arr[1] = value 4000
        "total_before": "3,000" // arr[0] + arr[1] = value 5000
    },
    {
        "month": 3,
        "total_now": null 
        "total_before": "1,000" // arr[0] + arr[1] + arr[2] = value 6000
    },
    ...
    {
        "month": 12,
        "total_now": null,
        "total_before": "20,422" // arr[0] + arr[1] + arr[2] ..... = 20000
    },
]

Advertisement

Answer

I am assuming that you are dealing with integer values and your commas represent thousands placeholders. These need to be sanitized to allow the addition to take place.

I have included the null checks and it assumes that once a null date is encountered in the current year, there won’t be a subsequent numeric value.

Code: (Demo)

public function GetMonthlyTotalsSincePreviousYear($year = null): void
{
    $thisYear = $year ?? date('Y');
    $lastYear = $thisYear - 1;
    $thisYearRunningTotal = 0;
    $lastYearRunningTotal = 0;
    $result = [];
    for ($month = 1; $month <= 12; ++$month) {
        $thisYearMonthTotal = $this->My_model->model_month($month, $thisYear)->row()->hasil;
        $thisYearRunningTotal = $thisYearMonthTotal === null
            ? null
            : (int)str_replace(',', '', $thisYearMonthTotal) + $thisYearRunningTotal;
        
        $lastYearMonthTotal = $this->My_model->model_month($month, $lastYear)->row()->hasil;
        $lastYearRunningTotal = $lastYearMonthTotal === null
            ? null
            : (int)str_replace(',', '', $lastYearMonthTotal) + ($lastYearRunningTotal ?? 0);

        $result[] = [
            'month' => $month,
            'total_now' => $thisYearRunningTotal,
            'total_before' => $lastYearRunningTotal,
        ];
    }
    $this->set_response($result, 200);  
}
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement