From ec787de5e0d9a5bfa76aa902c721f2e7c9ddfe48 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 20 Oct 2020 04:36:36 +0200 Subject: [PATCH] Simplify code --- .../Controllers/Report/CategoryController.php | 82 +------ .../Report/Budget/BudgetReportGenerator.php | 194 ++++++++-------- .../Category/CategoryReportGenerator.php | 208 ++++++++++++++++++ 3 files changed, 315 insertions(+), 169 deletions(-) create mode 100644 app/Support/Report/Category/CategoryReportGenerator.php diff --git a/app/Http/Controllers/Report/CategoryController.php b/app/Http/Controllers/Report/CategoryController.php index 5cfc816ae1..c6d409e70c 100644 --- a/app/Http/Controllers/Report/CategoryController.php +++ b/app/Http/Controllers/Report/CategoryController.php @@ -30,6 +30,7 @@ use FireflyIII\Repositories\Category\NoCategoryRepositoryInterface; use FireflyIII\Repositories\Category\OperationsRepositoryInterface; use FireflyIII\Support\CacheProperties; use FireflyIII\Support\Http\Controllers\BasicDataSupport; +use FireflyIII\Support\Report\Category\CategoryReportGenerator; use Illuminate\Contracts\View\Factory; use Illuminate\Support\Collection; use Illuminate\View\View; @@ -643,7 +644,7 @@ class CategoryController extends Controller } /** - * Show overview of operations. + * Show overview of category transactions on the default report. * * @param Collection $accounts * @param Carbon $start @@ -661,79 +662,16 @@ class CategoryController extends Controller $cache->addProperty('category-report'); $cache->addProperty($accounts->pluck('id')->toArray()); if ($cache->has()) { - return $cache->get(); // @codeCoverageIgnore + //return $cache->get(); // @codeCoverageIgnore } - $earnedWith = $this->opsRepository->listIncome($start, $end, $accounts); - $spentWith = $this->opsRepository->listExpenses($start, $end, $accounts); - $earnedWithout = $this->noCatRepository->listIncome($start, $end, $accounts); - $spentWithout = $this->noCatRepository->listExpenses($start, $end, $accounts); - - $report = [ - 'categories' => [], - 'sums' => [], - ]; - - // needs four for-each loops. - foreach ([$earnedWith, $spentWith, $earnedWithout, $spentWithout] as $data) { - foreach ($data as $currencyId => $currencyRow) { - $report['sums'][$currencyId] = $report['sums'][$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currencyRow['currency_id'], - 'currency_symbol' => $currencyRow['currency_symbol'], - 'currency_name' => $currencyRow['currency_name'], - 'currency_code' => $currencyRow['currency_code'], - 'currency_decimal_places' => $currencyRow['currency_decimal_places'], - ]; - - - foreach ($currencyRow['categories'] as $categoryId => $categoryRow) { - $key = sprintf('%s-%s', $currencyId, $categoryId); - $report['categories'][$key] = $report['categories'][$key] ?? [ - 'id' => $categoryId, - 'title' => $categoryRow['name'], - 'currency_id' => $currencyRow['currency_id'], - 'currency_symbol' => $currencyRow['currency_symbol'], - 'currency_name' => $currencyRow['currency_name'], - 'currency_code' => $currencyRow['currency_code'], - 'currency_decimal_places' => $currencyRow['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; - // loop journals: - foreach ($categoryRow['transaction_journals'] as $journal) { - // sum of sums - $report['sums'][$currencyId]['sum'] = bcadd($report['sums'][$currencyId]['sum'], $journal['amount']); - // sum of spent: - $report['sums'][$currencyId]['spent'] = -1 === bccomp($journal['amount'], '0') ? bcadd( - $report['sums'][$currencyId]['spent'], - $journal['amount'] - ) : $report['sums'][$currencyId]['spent']; - // sum of earned - $report['sums'][$currencyId]['earned'] = 1 === bccomp($journal['amount'], '0') ? bcadd( - $report['sums'][$currencyId]['earned'], - $journal['amount'] - ) : $report['sums'][$currencyId]['earned']; - - // sum of category - $report['categories'][$key]['sum'] = bcadd($report['categories'][$key]['sum'], $journal['amount']); - // total spent in category - $report['categories'][$key]['spent'] = -1 === bccomp($journal['amount'], '0') ? bcadd( - $report['categories'][$key]['spent'], - $journal['amount'] - ) : $report['categories'][$key]['spent']; - // total earned in category - $report['categories'][$key]['earned'] = 1 === bccomp($journal['amount'], '0') ? bcadd( - $report['categories'][$key]['earned'], - $journal['amount'] - ) : $report['categories'][$key]['earned']; - } - } - } - } + /** @var CategoryReportGenerator $generator */ + $generator = app(CategoryReportGenerator::class); + $generator->setAccounts($accounts); + $generator->setStart($start); + $generator->setEnd($end); + $generator->operations(); + $report = $generator->getReport(); // @codeCoverageIgnoreStart try { diff --git a/app/Support/Report/Budget/BudgetReportGenerator.php b/app/Support/Report/Budget/BudgetReportGenerator.php index e43a297482..e2b9205208 100644 --- a/app/Support/Report/Budget/BudgetReportGenerator.php +++ b/app/Support/Report/Budget/BudgetReportGenerator.php @@ -41,17 +41,17 @@ use Illuminate\Support\Collection; */ class BudgetReportGenerator { - private User $user; private Collection $accounts; - private Collection $budgets; - private Carbon $start; - private Carbon $end; - private BudgetRepositoryInterface $repository; private BudgetLimitRepositoryInterface $blRepository; + private Collection $budgets; private TransactionCurrency $currency; - private array $report; - private OperationsRepositoryInterface $opsRepository; + private Carbon $end; private NoBudgetRepositoryInterface $nbRepository; + private OperationsRepositoryInterface $opsRepository; + private array $report; + private BudgetRepositoryInterface $repository; + private Carbon $start; + private User $user; /** * BudgetReportGenerator constructor. @@ -65,22 +65,6 @@ class BudgetReportGenerator $this->report = []; } - /** - * Generates the data necessary to create the card that displays - * the budget overview in the general report. - */ - public function general(): void - { - $this->report = [ - 'budgets' => [], - 'sums' => [], - ]; - - $this->generalBudgetReport(); - $this->noBudgetReport(); - $this->percentageReport(); - } - /** * Returns the data necessary for the "account per budget" block on the budget report. */ @@ -108,56 +92,61 @@ class BudgetReportGenerator } /** - * @param User $user + * Process each row of expenses collected for the "Account per budget" partial + * + * @param array $expenses */ - public function setUser(User $user): void + private function processExpenses(array $expenses): void { - $this->user = $user; - $this->repository->setUser($user); - $this->blRepository->setUser($user); - $this->opsRepository->setUser($user); - $this->nbRepository->setUser($user); - $this->currency = app('amount')->getDefaultCurrencyByUser($this->user); + foreach ($expenses['budgets'] as $budget) { + $this->processBudgetExpenses($expenses, $budget); + } } /** - * @param Collection $budgets + * Process each set of transactions for each row of expenses. + * + * @param array $expenses + * @param array $budget */ - public function setBudgets(Collection $budgets): void + private function processBudgetExpenses(array $expenses, array $budget): void { - $this->budgets = $budgets; + $budgetId = (int)$budget['id']; + $currencyId = (int)$expenses['currency_id']; + foreach ($budget['transaction_journals'] as $journal) { + $sourceAccountId = $journal['source_account_id']; + + $this->report[$sourceAccountId]['currencies'][$currencyId] + = $this->report[$sourceAccountId]['currencies'][$currencyId] ?? [ + 'currency_id' => $expenses['currency_id'], + 'currency_symbol' => $expenses['currency_symbol'], + 'currency_name' => $expenses['currency_name'], + 'currency_decimal_places' => $expenses['currency_decimal_places'], + 'budgets' => [], + ]; + + $this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId] + = $this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId] ?? '0'; + + $this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId] + = bcadd($this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId], $journal['amount']); + } } /** - * @param Collection $accounts + * Generates the data necessary to create the card that displays + * the budget overview in the general report. */ - public function setAccounts(Collection $accounts): void + public function general(): void { - $this->accounts = $accounts; - } + $this->report = [ + 'budgets' => [], + 'sums' => [], + ]; - /** - * @param Carbon $start - */ - public function setStart(Carbon $start): void - { - $this->start = $start; - } - - /** - * @param Carbon $end - */ - public function setEnd(Carbon $end): void - { - $this->end = $end; - } - - /** - * @return array - */ - public function getReport(): array - { - return $this->report; + $this->generalBudgetReport(); + $this->noBudgetReport(); + $this->percentageReport(); } /** @@ -179,7 +168,7 @@ class BudgetReportGenerator */ private function processBudget(Budget $budget): void { - $budgetId = (int) $budget->id; + $budgetId = (int)$budget->id; $this->report['budgets'][$budgetId] = $this->report['budgets'][$budgetId] ?? [ 'budget_id' => $budgetId, 'budget_name' => $budget->name, @@ -203,10 +192,10 @@ class BudgetReportGenerator */ private function processLimit(Budget $budget, BudgetLimit $limit): void { - $budgetId = (int) $budget->id; - $limitId = (int) $limit->id; + $budgetId = (int)$budget->id; + $limitId = (int)$limit->id; $currency = $limit->transactionCurrency ?? $this->currency; - $currencyId = (int) $currency->id; + $currencyId = (int)$currency->id; $expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $this->accounts, new Collection([$budget])); $spent = $expenses[$currencyId]['sum'] ?? '0'; $left = -1 === bccomp(bcadd($limit->amount, $spent), '0') ? '0' : bcadd($limit->amount, $spent); @@ -265,7 +254,7 @@ class BudgetReportGenerator foreach ($noBudget as $noBudgetEntry) { // currency information: - $nbCurrencyId = (int) ($noBudgetEntry['currency_id'] ?? $this->currency->id); + $nbCurrencyId = (int)($noBudgetEntry['currency_id'] ?? $this->currency->id); $nbCurrencyCode = $noBudgetEntry['currency_code'] ?? $this->currency->code; $nbCurrencyName = $noBudgetEntry['currency_name'] ?? $this->currency->name; $nbCurrencySymbol = $noBudgetEntry['currency_symbol'] ?? $this->currency->symbol; @@ -310,9 +299,9 @@ class BudgetReportGenerator // make percentages based on total amount. foreach ($this->report['budgets'] as $budgetId => $data) { foreach ($data['budget_limits'] as $limitId => $entry) { - $budgetId = (int) $budgetId; - $limitId = (int) $limitId; - $currencyId = (int) $entry['currency_id']; + $budgetId = (int)$budgetId; + $limitId = (int)$limitId; + $currencyId = (int)$entry['currency_id']; $spent = $entry['spent']; $totalSpent = $this->report['sums'][$currencyId]['spent'] ?? '0'; $spentPct = '0'; @@ -334,44 +323,55 @@ class BudgetReportGenerator } /** - * Process each row of expenses collected for the "Account per budget" partial - * - * @param array $expenses + * @return array */ - private function processExpenses(array $expenses): void + public function getReport(): array { - foreach ($expenses['budgets'] as $budget) { - $this->processBudgetExpenses($expenses, $budget); - } + return $this->report; } /** - * Process each set of transactions for each row of expenses. - * - * @param array $expenses - * @param array $budget + * @param Collection $accounts */ - private function processBudgetExpenses(array $expenses, array $budget): void + public function setAccounts(Collection $accounts): void { - $budgetId = (int) $budget['id']; - $currencyId = (int) $expenses['currency_id']; - foreach ($budget['transaction_journals'] as $journal) { - $sourceAccountId = $journal['source_account_id']; + $this->accounts = $accounts; + } - $this->report[$sourceAccountId]['currencies'][$currencyId] = - $this->report[$sourceAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $expenses['currency_id'], - 'currency_symbol' => $expenses['currency_symbol'], - 'currency_name' => $expenses['currency_name'], - 'currency_decimal_places' => $expenses['currency_decimal_places'], - 'budgets' => [], - ]; + /** + * @param Collection $budgets + */ + public function setBudgets(Collection $budgets): void + { + $this->budgets = $budgets; + } - $this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId] = - $this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId] ?? '0'; + /** + * @param Carbon $end + */ + public function setEnd(Carbon $end): void + { + $this->end = $end; + } - $this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId] = - bcadd($this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId], $journal['amount']); - } + /** + * @param Carbon $start + */ + public function setStart(Carbon $start): void + { + $this->start = $start; + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + $this->repository->setUser($user); + $this->blRepository->setUser($user); + $this->opsRepository->setUser($user); + $this->nbRepository->setUser($user); + $this->currency = app('amount')->getDefaultCurrencyByUser($this->user); } } diff --git a/app/Support/Report/Category/CategoryReportGenerator.php b/app/Support/Report/Category/CategoryReportGenerator.php new file mode 100644 index 0000000000..e9badcf1fa --- /dev/null +++ b/app/Support/Report/Category/CategoryReportGenerator.php @@ -0,0 +1,208 @@ +. + */ + +namespace FireflyIII\Support\Report\Category; + + +use Carbon\Carbon; +use FireflyIII\Repositories\Category\NoCategoryRepositoryInterface; +use FireflyIII\Repositories\Category\OperationsRepositoryInterface; +use FireflyIII\User; +use Illuminate\Support\Collection; + +/** + * Class CategoryReportGenerator + */ +class CategoryReportGenerator +{ + private Collection $accounts; + private Carbon $end; + private NoCategoryRepositoryInterface $noCatRepository; + private OperationsRepositoryInterface $opsRepository; + private array $report; + private Carbon $start; + + /** + * CategoryReportGenerator constructor. + */ + public function __construct() + { + $this->opsRepository = app(OperationsRepositoryInterface::class); + $this->noCatRepository = app(NoCategoryRepositoryInterface::class); + } + + /** + * @return array + */ + public function getReport(): array + { + return $this->report; + } + + /** + * Generate the array required to show the overview of categories on the + * default report. + */ + public function operations(): void + { + $earnedWith = $this->opsRepository->listIncome($this->start, $this->end, $this->accounts); + $spentWith = $this->opsRepository->listExpenses($this->start, $this->end, $this->accounts); + $earnedWithout = $this->noCatRepository->listIncome($this->start, $this->end, $this->accounts); + $spentWithout = $this->noCatRepository->listExpenses($this->start, $this->end, $this->accounts); + + $this->report = [ + 'categories' => [], + 'sums' => [], + ]; + + // needs four for-each loops. + foreach ([$earnedWith, $spentWith, $earnedWithout, $spentWithout] as $data) { + $this->processOpsArray($data); + } + } + + /** + * Process one of the spent arrays from the operations method. + * + * @param array $data + */ + private function processOpsArray(array $data): void + { + /** + * @var int $currencyId + * @var array $currencyRow + */ + foreach ($data as $currencyId => $currencyRow) { + $this->processCurrencyArray($currencyId, $currencyRow); + } + } + + /** + * @param int $currencyId + * @param array $currencyRow + */ + private function processCurrencyArray(int $currencyId, array $currencyRow): void + { + $this->report['sums'][$currencyId] = $this->report['sums'][$currencyId] ?? [ + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currencyRow['currency_id'], + 'currency_symbol' => $currencyRow['currency_symbol'], + 'currency_name' => $currencyRow['currency_name'], + 'currency_code' => $currencyRow['currency_code'], + 'currency_decimal_places' => $currencyRow['currency_decimal_places'], + ]; + + /** + * @var int $categoryId + * @var array $categoryRow + */ + foreach ($currencyRow['categories'] as $categoryId => $categoryRow) { + $this->processCategoryRow($currencyId, $currencyRow, $categoryId, $categoryRow); + } + } + + /** + * @param int $currencyId + * @param array $currencyRow + * @param int $categoryId + * @param array $categoryRow + */ + private function processCategoryRow(int $currencyId, array $currencyRow, int $categoryId, array $categoryRow): void + { + $key = sprintf('%s-%s', $currencyId, $categoryId); + $this->report['categories'][$key] = $this->report['categories'][$key] ?? [ + 'id' => $categoryId, + 'title' => $categoryRow['name'], + 'currency_id' => $currencyRow['currency_id'], + 'currency_symbol' => $currencyRow['currency_symbol'], + 'currency_name' => $currencyRow['currency_name'], + 'currency_code' => $currencyRow['currency_code'], + 'currency_decimal_places' => $currencyRow['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; + // loop journals: + foreach ($categoryRow['transaction_journals'] as $journal) { + // sum of sums + $this->report['sums'][$currencyId]['sum'] = bcadd($this->report['sums'][$currencyId]['sum'], $journal['amount']); + // sum of spent: + $this->report['sums'][$currencyId]['spent'] = -1 === bccomp($journal['amount'], '0') ? bcadd( + $this->report['sums'][$currencyId]['spent'], + $journal['amount'] + ) : $this->report['sums'][$currencyId]['spent']; + // sum of earned + $this->report['sums'][$currencyId]['earned'] = 1 === bccomp($journal['amount'], '0') ? bcadd( + $this->report['sums'][$currencyId]['earned'], + $journal['amount'] + ) : $this->report['sums'][$currencyId]['earned']; + + // sum of category + $this->report['categories'][$key]['sum'] = bcadd($this->report['categories'][$key]['sum'], $journal['amount']); + // total spent in category + $this->report['categories'][$key]['spent'] = -1 === bccomp($journal['amount'], '0') ? bcadd( + $this->report['categories'][$key]['spent'], + $journal['amount'] + ) : $this->report['categories'][$key]['spent']; + // total earned in category + $this->report['categories'][$key]['earned'] = 1 === bccomp($journal['amount'], '0') ? bcadd( + $this->report['categories'][$key]['earned'], + $journal['amount'] + ) : $this->report['categories'][$key]['earned']; + } + } + + /** + * @param Collection $accounts + */ + public function setAccounts(Collection $accounts): void + { + $this->accounts = $accounts; + } + + /** + * @param Carbon $end + */ + public function setEnd(Carbon $end): void + { + $this->end = $end; + } + + /** + * @param Carbon $start + */ + public function setStart(Carbon $start): void + { + $this->start = $start; + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->noCatRepository->setUser($user); + $this->opsRepository->setUser($user); + } + +} \ No newline at end of file