From 975a6c34bfe777a007f78221c5baa5967777a237 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 15 Dec 2016 14:38:05 +0100 Subject: [PATCH] Finished #452 --- .../Report/ChartJsReportChartGenerator.php | 180 ----------- .../Report/ReportChartGeneratorInterface.php | 65 ---- .../Controllers/Chart/ReportController.php | 290 +++++++----------- resources/lang/en_US/firefly.php | 2 + 4 files changed, 112 insertions(+), 425 deletions(-) delete mode 100644 app/Generator/Chart/Report/ChartJsReportChartGenerator.php delete mode 100644 app/Generator/Chart/Report/ReportChartGeneratorInterface.php diff --git a/app/Generator/Chart/Report/ChartJsReportChartGenerator.php b/app/Generator/Chart/Report/ChartJsReportChartGenerator.php deleted file mode 100644 index d36c68815c..0000000000 --- a/app/Generator/Chart/Report/ChartJsReportChartGenerator.php +++ /dev/null @@ -1,180 +0,0 @@ - 2, - 'labels' => [], - 'datasets' => [ - [ - 'label' => trans('firefly.income'), - 'data' => [], - ], - [ - 'label' => trans('firefly.expenses'), - 'data' => [], - ], - ], - ]; - - foreach ($entries as $entry) { - $data['labels'][] = $entry[0]->formatLocalized('%Y'); - $data['datasets'][0]['data'][] = round($entry[1], 2); - $data['datasets'][1]['data'][] = round($entry[2], 2); - } - - return $data; - } - - /** - * @param string $income - * @param string $expense - * @param int $count - * - * @return array - */ - public function multiYearSum(string $income, string $expense, int $count): array - { - $data = [ - 'count' => 2, - 'labels' => [trans('firefly.sum_of_years'), trans('firefly.average_of_years')], - 'datasets' => [ - [ - 'label' => trans('firefly.income'), - 'data' => [], - ], - [ - 'label' => trans('firefly.expenses'), - 'data' => [], - ], - ], - ]; - $data['datasets'][0]['data'][] = round($income, 2); - $data['datasets'][1]['data'][] = round($expense, 2); - $data['datasets'][0]['data'][] = round(($income / $count), 2); - $data['datasets'][1]['data'][] = round(($expense / $count), 2); - - return $data; - } - - /** - * @param Collection $entries - * - * @return array - */ - public function netWorth(Collection $entries): array - { - $format = (string)trans('config.month_and_day'); - $data = [ - 'count' => 1, - 'labels' => [], - 'datasets' => [ - [ - 'label' => trans('firefly.net_worth'), - 'data' => [], - ], - ], - ]; - foreach ($entries as $entry) { - $data['labels'][] = trim($entry['date']->formatLocalized($format)); - $data['datasets'][0]['data'][] = round($entry['net-worth'], 2); - } - - return $data; - } - - /** - * @param Collection $entries - * - * @return array - */ - public function yearOperations(Collection $entries): array - { - // language: - $format = (string)trans('config.month'); - - $data = [ - 'count' => 2, - 'labels' => [], - 'datasets' => [ - [ - 'label' => trans('firefly.income'), - 'data' => [], - ], - [ - 'label' => trans('firefly.expenses'), - 'data' => [], - ], - ], - ]; - - foreach ($entries as $entry) { - $data['labels'][] = $entry[0]->formatLocalized($format); - $data['datasets'][0]['data'][] = round($entry[1], 2); - $data['datasets'][1]['data'][] = round($entry[2], 2); - } - - return $data; - } - - /** - * @param string $income - * @param string $expense - * @param int $count - * - * @return array - */ - public function yearSum(string $income, string $expense, int $count): array - { - - $data = [ - 'count' => 2, - 'labels' => [trans('firefly.sum_of_year'), trans('firefly.average_of_year')], - 'datasets' => [ - [ - 'label' => trans('firefly.income'), - 'data' => [], - ], - [ - 'label' => trans('firefly.expenses'), - 'data' => [], - ], - ], - ]; - $data['datasets'][0]['data'][] = round($income, 2); - $data['datasets'][1]['data'][] = round($expense, 2); - $data['datasets'][0]['data'][] = round(($income / $count), 2); - $data['datasets'][1]['data'][] = round(($expense / $count), 2); - - return $data; - } -} diff --git a/app/Generator/Chart/Report/ReportChartGeneratorInterface.php b/app/Generator/Chart/Report/ReportChartGeneratorInterface.php deleted file mode 100644 index 745756c825..0000000000 --- a/app/Generator/Chart/Report/ReportChartGeneratorInterface.php +++ /dev/null @@ -1,65 +0,0 @@ -generator = app(ReportChartGeneratorInterface::class); + $this->generator = app(GeneratorInterface::class); } /** @@ -59,30 +59,25 @@ class ReportController extends Controller { // chart properties for cache: $cache = new CacheProperties; - $cache->addProperty('netWorth'); + $cache->addProperty('chart.report.net-worth'); $cache->addProperty($start); $cache->addProperty($accounts); $cache->addProperty($end); if ($cache->has()) { return Response::json($cache->get()); } - $ids = $accounts->pluck('id')->toArray(); - $current = clone $start; - $entries = new Collection; + $ids = $accounts->pluck('id')->toArray(); + $current = clone $start; + $chartData = []; while ($current < $end) { - $balances = Steam::balancesById($ids, $current); - $sum = $this->arraySum($balances); - $entries->push( - [ - 'date' => clone $current, - 'net-worth' => $sum, - ] - ); - + $balances = Steam::balancesById($ids, $current); + $sum = $this->arraySum($balances); + $label = $current->formatLocalized(strval(trans('config.month_and_day'))); + $chartData[$label] = $sum; $current->addDays(7); } - $data = $this->generator->netWorth($entries); + $data = $this->generator->singleSet(strval(trans('firefly.net_worth')), $chartData); $cache->store($data); return Response::json($data); @@ -103,31 +98,47 @@ class ReportController extends Controller { // chart properties for cache: $cache = new CacheProperties; - $cache->addProperty('yearInOut'); + $cache->addProperty('chart.report.operations'); $cache->addProperty($start); $cache->addProperty($accounts); $cache->addProperty($end); if ($cache->has()) { return Response::json($cache->get()); } + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); + $source = $this->getChartData($accounts, $start, $end); + $chartData = [ + [ + 'label' => trans('firefly.income'), + 'type' => 'bar', + 'entries' => [], + ], + [ + 'label' => trans('firefly.expenses'), + 'type' => 'bar', + 'entries' => [], + ], + ]; - $chartSource = $this->getYearData($accounts, $start, $end); - - if ($start->diffInMonths($end) > 12) { - // data = method X - $data = $this->multiYearOperations($chartSource['earned'], $chartSource['spent'], $start, $end); - $cache->store($data); - - return Response::json($data); + foreach ($source['earned'] as $date => $amount) { + $carbon = new Carbon($date); + $label = $carbon->formatLocalized($format); + $earned = $chartData[0]['entries'][$label] ?? '0'; + $chartData[0]['entries'][$label] = bcadd($earned, $amount); + } + foreach ($source['spent'] as $date => $amount) { + $carbon = new Carbon($date); + $label = $carbon->formatLocalized($format); + $spent = $chartData[1]['entries'][$label] ?? '0'; + $chartData[1]['entries'][$label] = bcadd($spent, $amount); } - // data = method Y - $data = $this->singleYearOperations($chartSource['earned'], $chartSource['spent'], $start, $end); + + $data = $this->generator->multiSet($chartData); $cache->store($data); return Response::json($data); - } /** @@ -142,162 +153,67 @@ class ReportController extends Controller public function sum(Collection $accounts, Carbon $start, Carbon $end) { + // chart properties for cache: $cache = new CacheProperties; - $cache->addProperty('yearInOutSummarized'); + $cache->addProperty('chart.report.sum'); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($accounts); if ($cache->has()) { return Response::json($cache->get()); } - $chartSource = $this->getYearData($accounts, $start, $end); - - if ($start->diffInMonths($end) > 12) { - // per year - $data = $this->multiYearSum($chartSource['earned'], $chartSource['spent'], $start, $end); - $cache->store($data); - - return Response::json($data); + $source = $this->getChartData($accounts, $start, $end); + $numbers = [ + 'sum_earned' => '0', + 'avg_earned' => '0', + 'count_earned' => 0, + 'sum_spent' => '0', + 'avg_spent' => '0', + 'count_spent' => 0, + ]; + foreach ($source['earned'] as $amount) { + $numbers['sum_earned'] = bcadd($amount, $numbers['sum_earned']); + $numbers['count_earned']++; } - // per month! - $data = $this->singleYearSum($chartSource['earned'], $chartSource['spent'], $start, $end); + if ($numbers['count_earned'] > 0) { + $numbers['avg_earned'] = $numbers['sum_earned'] / $numbers['count_earned']; + } + foreach ($source['spent'] as $amount) { + $numbers['sum_spent'] = bcadd($amount, $numbers['sum_spent']); + $numbers['count_spent']++; + } + if ($numbers['count_spent'] > 0) { + $numbers['avg_spent'] = $numbers['sum_spent'] / $numbers['count_spent']; + } + + $chartData = [ + [ + 'label' => strval(trans('firefly.income')), + 'type' => 'bar', + 'entries' => [ + strval(trans('firefly.sum_of_period')) => $numbers['sum_earned'], + strval(trans('firefly.average_in_period')) => $numbers['avg_earned'], + ], + ], + [ + 'label' => trans('firefly.expenses'), + 'type' => 'bar', + 'entries' => [ + strval(trans('firefly.sum_of_period')) => $numbers['sum_spent'], + strval(trans('firefly.average_in_period')) => $numbers['avg_spent'], + ], + ], + ]; + + + $data = $this->generator->multiSet($chartData); $cache->store($data); return Response::json($data); } - /** - * @param array $earned - * @param array $spent - * @param Carbon $start - * @param Carbon $end - * - * @return array - */ - protected function multiYearOperations(array $earned, array $spent, Carbon $start, Carbon $end) - { - $entries = new Collection; - while ($start < $end) { - - $incomeSum = $this->pluckFromArray($start->year, $earned); - $expenseSum = $this->pluckFromArray($start->year, $spent); - - $entries->push([clone $start, $incomeSum, $expenseSum]); - $start->addYear(); - } - - $data = $this->generator->multiYearOperations($entries); - - return $data; - } - - /** - * @param array $earned - * @param array $spent - * @param Carbon $start - * @param Carbon $end - * - * @return array - */ - protected function multiYearSum(array $earned, array $spent, Carbon $start, Carbon $end) - { - $income = '0'; - $expense = '0'; - $count = 0; - while ($start < $end) { - - $currentIncome = $this->pluckFromArray($start->year, $earned); - $currentExpense = $this->pluckFromArray($start->year, $spent); - $income = bcadd($income, $currentIncome); - $expense = bcadd($expense, $currentExpense); - - $count++; - $start->addYear(); - } - - $data = $this->generator->multiYearSum($income, $expense, $count); - - return $data; - } - - /** - * @param int $year - * @param array $set - * - * @return string - */ - protected function pluckFromArray($year, array $set) - { - $sum = '0'; - foreach ($set as $date => $amount) { - if (substr($date, 0, 4) == $year) { - $sum = bcadd($sum, $amount); - } - } - - return $sum; - - } - - /** - * @param array $earned - * @param array $spent - * @param Carbon $start - * @param Carbon $end - * - * @return array - */ - protected function singleYearOperations(array $earned, array $spent, Carbon $start, Carbon $end) - { - // per month? simply use each month. - - $entries = new Collection; - while ($start < $end) { - // total income and total expenses: - $date = $start->format('Y-m'); - $incomeSum = isset($earned[$date]) ? $earned[$date] : 0; - $expenseSum = isset($spent[$date]) ? $spent[$date] : 0; - - $entries->push([clone $start, $incomeSum, $expenseSum]); - $start->addMonth(); - } - - $data = $this->generator->yearOperations($entries); - - return $data; - } - - /** - * @param array $earned - * @param array $spent - * @param Carbon $start - * @param Carbon $end - * - * @return array - */ - protected function singleYearSum(array $earned, array $spent, Carbon $start, Carbon $end) - { - $income = '0'; - $expense = '0'; - $count = 0; - while ($start < $end) { - $date = $start->format('Y-m'); - $currentIncome = isset($earned[$date]) ? $earned[$date] : 0; - $currentExpense = isset($spent[$date]) ? $spent[$date] : 0; - $income = bcadd($income, $currentIncome); - $expense = bcadd($expense, $currentExpense); - - $count++; - $start->addMonth(); - } - - $data = $this->generator->yearSum($income, $expense, $count); - - return $data; - } - /** * @param $array * @@ -314,31 +230,45 @@ class ReportController extends Controller } /** + * Collects the incomes and expenses for the given periods, grouped per month. Will cache its results + * * @param Collection $accounts * @param Carbon $start * @param Carbon $end * * @return array */ - private function getYearData(Collection $accounts, Carbon $start, Carbon $end): array + private function getChartData(Collection $accounts, Carbon $start, Carbon $end): array { + $cache = new CacheProperties; + $cache->addProperty('chart.report.get-chart-data'); + $cache->addProperty($start); + $cache->addProperty($accounts); + $cache->addProperty($end); + if ($cache->has()) { + return $cache->get(); + } + + $tasker = app(AccountTaskerInterface::class); $currentStart = clone $start; $spentArray = []; $earnedArray = []; while ($currentStart <= $end) { - $currentEnd = Navigation::endOfPeriod($currentStart, '1M'); - $date = $currentStart->format('Y-m'); - $spent = $tasker->amountOutInPeriod($accounts, $accounts, $currentStart, $currentEnd); - $earned = $tasker->amountInInPeriod($accounts, $accounts, $currentStart, $currentEnd); - $spentArray[$date] = bcmul($spent, '-1'); - $earnedArray[$date] = $earned; - $currentStart = Navigation::addPeriod($currentStart, '1M', 0); + $currentEnd = Navigation::endOfPeriod($currentStart, '1M'); + $label = $currentStart->format('Y-m') . '-01'; + $spent = $tasker->amountOutInPeriod($accounts, $accounts, $currentStart, $currentEnd); + $earned = $tasker->amountInInPeriod($accounts, $accounts, $currentStart, $currentEnd); + $spentArray[$label] = bcmul($spent, '-1'); + $earnedArray[$label] = $earned; + $currentStart = Navigation::addPeriod($currentStart, '1M', 0); } - - return [ + $result = [ 'spent' => $spentArray, 'earned' => $earnedArray, ]; + $cache->store($result); + + return $result; } } diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 45665c2921..0e698e598e 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -719,6 +719,8 @@ return [ 'average_income_per_account' => 'Average income per account', 'total' => 'Total', 'description' => 'Description', + 'sum_of_period' => 'Sum of period', + 'average_in_period' => 'Average in period', // charts: