From 18f605268100ad4195ae6e9f898e542ca3526342 Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 31 Mar 2021 06:29:08 +0200 Subject: [PATCH] Part of #4566 --- .../Insight/Expense/AccountController.php | 8 +- .../Insight/Income/AccountController.php | 12 +- .../Insight/Transfer/AccountController.php | 2 +- .../Account/OperationsRepository.php | 331 +++++++++++++++++- .../Account/OperationsRepositoryInterface.php | 58 +++ 5 files changed, 402 insertions(+), 9 deletions(-) diff --git a/app/Api/V1/Controllers/Insight/Expense/AccountController.php b/app/Api/V1/Controllers/Insight/Expense/AccountController.php index 66fd5c8ce8..03d3c2418d 100644 --- a/app/Api/V1/Controllers/Insight/Expense/AccountController.php +++ b/app/Api/V1/Controllers/Insight/Expense/AccountController.php @@ -82,12 +82,14 @@ class AccountController extends Controller $start = $request->getStart(); $end = $request->getEnd(); $assetAccounts = $request->getAssetAccounts(); - $expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts); + $expenses = $this->opsRepository->sumExpensesBySource($start, $end, $assetAccounts); $result = []; /** @var array $expense */ foreach ($expenses as $expense) { $result[] = [ + 'id' => (string)$expense['id'], + 'name' => $expense['name'], 'difference' => $expense['sum'], 'difference_float' => (float)$expense['sum'], 'currency_id' => (string)$expense['currency_id'], @@ -109,12 +111,14 @@ class AccountController extends Controller $end = $request->getEnd(); $assetAccounts = $request->getAssetAccounts(); $expenseAccounts = $request->getExpenseAccounts(); - $expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, $expenseAccounts); + $expenses = $this->opsRepository->sumExpensesByDestination($start, $end, $assetAccounts, $expenseAccounts); $result = []; /** @var array $expense */ foreach ($expenses as $expense) { $result[] = [ + 'id' => (string)$expense['id'], + 'name' => $expense['name'], 'difference' => $expense['sum'], 'difference_float' => (float)$expense['sum'], 'currency_id' => (string)$expense['currency_id'], diff --git a/app/Api/V1/Controllers/Insight/Income/AccountController.php b/app/Api/V1/Controllers/Insight/Income/AccountController.php index 9de160f284..63e6db1f91 100644 --- a/app/Api/V1/Controllers/Insight/Income/AccountController.php +++ b/app/Api/V1/Controllers/Insight/Income/AccountController.php @@ -75,7 +75,7 @@ class AccountController extends Controller /** * TODO same code as Expense/AccountController. - * + * TODO does not actually include the name of the expense account. * @param GenericRequest $request * * @return JsonResponse @@ -85,11 +85,13 @@ class AccountController extends Controller $start = $request->getStart(); $end = $request->getEnd(); $assetAccounts = $request->getAssetAccounts(); - $income = $this->opsRepository->sumIncome($start, $end, $assetAccounts); + $income = $this->opsRepository->sumIncomeByDestination($start, $end, $assetAccounts); $result = []; /** @var array $entry */ foreach ($income as $entry) { $result[] = [ + 'id' => (string)$entry['id'], + 'name' => $entry['name'], 'difference' => $entry['sum'], 'difference_float' => (float)$entry['sum'], 'currency_id' => (string)$entry['currency_id'], @@ -101,7 +103,7 @@ class AccountController extends Controller } /** - * // TOOD same as + * TODO does not actually include the name of the expense account. * * @param GenericRequest $request * @@ -113,12 +115,14 @@ class AccountController extends Controller $end = $request->getEnd(); $assetAccounts = $request->getAssetAccounts(); $revenueAccounts = $request->getRevenueAccounts(); - $income = $this->opsRepository->sumIncome($start, $end, $assetAccounts, $revenueAccounts); + $income = $this->opsRepository->sumIncomeBySource($start, $end, $assetAccounts, $revenueAccounts); $result = []; /** @var array $entry */ foreach ($income as $entry) { $result[] = [ + 'id' => (string)$entry['id'], + 'name' => $entry['name'], 'difference' => $entry['sum'], 'difference_float' => (float)$entry['sum'], 'currency_id' => (string)$entry['currency_id'], diff --git a/app/Api/V1/Controllers/Insight/Transfer/AccountController.php b/app/Api/V1/Controllers/Insight/Transfer/AccountController.php index 62204e5e07..3c399574a2 100644 --- a/app/Api/V1/Controllers/Insight/Transfer/AccountController.php +++ b/app/Api/V1/Controllers/Insight/Transfer/AccountController.php @@ -59,7 +59,7 @@ class AccountController extends Controller /** * TODO same code as Expense/AccountController. - * + * TODO does not actually include the name of the expense account. * @param GenericRequest $request * * @return JsonResponse diff --git a/app/Repositories/Account/OperationsRepository.php b/app/Repositories/Account/OperationsRepository.php index fcdd660788..c156b54140 100644 --- a/app/Repositories/Account/OperationsRepository.php +++ b/app/Repositories/Account/OperationsRepository.php @@ -263,7 +263,7 @@ class OperationsRepository implements OperationsRepositoryInterface if (null !== $currency) { /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); - $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]) + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT]) ->setForeignCurrency($currency); if (null !== $accounts) { @@ -310,6 +310,8 @@ class OperationsRepository implements OperationsRepositoryInterface } /** + * TODO same as sumIncome and sumExpense, but copied + * * @inheritDoc */ public function sumTransfers(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array @@ -333,7 +335,7 @@ class OperationsRepository implements OperationsRepositoryInterface if (null !== $currency) { /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); - $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]) + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) ->setForeignCurrency($currency); if (null !== $accounts) { @@ -375,4 +377,329 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } + + /** + * TODO same as sumExpenses + * + * @inheritDoc + */ + public function sumExpensesBySource( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + ): array { + $start->startOfDay(); + $end->endOfDay(); + + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->withAccountInformation(); + + if (null !== $accounts) { + $collector->setSourceAccounts($accounts); + } + if (null !== $expense) { + $collector->setDestinationAccounts($expense); + } + if (null !== $currency) { + $collector->setCurrency($currency); + } + $journals = $collector->getExtractedJournals(); + + // same but for foreign currencies: + if (null !== $currency) { + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setForeignCurrency($currency) + ->withAccountInformation(); + + if (null !== $accounts) { + $collector->setSourceAccounts($accounts); + } + if (null !== $expense) { + $collector->setDestinationAccounts($expense); + } + + $result = $collector->getExtractedJournals(); + + // do not use array_merge because you want keys to overwrite (otherwise you get double results): + $journals = $result + $journals; + } + $array = []; + + foreach ($journals as $journal) { + $key = sprintf('%s-%s', $journal['source_account_id'], $journal['currency_id']); + $array[$key] = $array[$key] ?? [ + 'id' => $journal['source_account_id'], + 'name' => $journal['source_account_name'], + 'iban' => $journal['source_account_iban'], + 'sum' => '0', + 'currency_id' => $journal['currency_id'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->negative($journal['amount'])); + + // also do foreign amount: + if (0 !== (int)$journal['foreign_currency_id']) { + $key = sprintf('%s-%s', $journal['source_account_id'], $journal['foreign_currency_id']); + $array[$key] = $array[$key] ?? [ + 'id' => $journal['source_account_id'], + 'name' => $journal['source_account_name'], + 'iban' => $journal['source_account_iban'], + 'sum' => '0', + 'currency_id' => $journal['foreign_currency_id'], + 'currency_name' => $journal['foreign_currency_name'], + 'currency_symbol' => $journal['foreign_currency_symbol'], + 'currency_code' => $journal['foreign_currency_code'], + 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->negative($journal['foreign_amount'])); + } + } + + return $array; + } + + /** + * @inheritDoc + */ + public function sumExpensesByDestination( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + ): array { + $start->startOfDay(); + $end->endOfDay(); + + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->withAccountInformation(); + + if (null !== $accounts) { + $collector->setSourceAccounts($accounts); + } + if (null !== $expense) { + $collector->setDestinationAccounts($expense); + } + if (null !== $currency) { + $collector->setCurrency($currency); + } + $journals = $collector->getExtractedJournals(); + + // same but for foreign currencies: + if (null !== $currency) { + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setForeignCurrency($currency) + ->withAccountInformation(); + + if (null !== $accounts) { + $collector->setSourceAccounts($accounts); + } + if (null !== $expense) { + $collector->setDestinationAccounts($expense); + } + + $result = $collector->getExtractedJournals(); + + // do not use array_merge because you want keys to overwrite (otherwise you get double results): + $journals = $result + $journals; + } + $array = []; + + foreach ($journals as $journal) { + $key = sprintf('%s-%s', $journal['destination_account_id'], $journal['currency_id']); + $array[$key] = $array[$key] ?? [ + 'id' => $journal['destination_account_id'], + 'name' => $journal['destination_account_name'], + 'iban' => $journal['destination_account_iban'], + 'sum' => '0', + 'currency_id' => $journal['currency_id'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->negative($journal['amount'])); + + // also do foreign amount: + if (0 !== (int)$journal['foreign_currency_id']) { + $key = sprintf('%s-%s', $journal['destination_account_id'], $journal['foreign_currency_id']); + $array[$key] = $array[$key] ?? [ + 'id' => $journal['destination_account_id'], + 'name' => $journal['destination_account_name'], + 'iban' => $journal['destination_account_iban'], + 'sum' => '0', + 'currency_id' => $journal['foreign_currency_id'], + 'currency_name' => $journal['foreign_currency_name'], + 'currency_symbol' => $journal['foreign_currency_symbol'], + 'currency_code' => $journal['foreign_currency_code'], + 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->negative($journal['foreign_amount'])); + } + } + + return $array; + } + + /** + * // TODO copy of previous methods. + * @inheritDoc + */ + public function sumIncomeByDestination( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null + ): array { + $start->startOfDay(); + $end->endOfDay(); + + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->withAccountInformation(); + + if (null !== $accounts) { + $collector->setDestinationAccounts($accounts); + } + if (null !== $revenue) { + $collector->setSourceAccounts($revenue); + } + if (null !== $currency) { + $collector->setCurrency($currency); + } + $journals = $collector->getExtractedJournals(); + + // same but for foreign currencies: + if (null !== $currency) { + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT]) + ->setForeignCurrency($currency)->withAccountInformation(); + + if (null !== $accounts) { + $collector->setDestinationAccounts($accounts); + } + if (null !== $revenue) { + $collector->setSourceAccounts($revenue); + } + $result = $collector->getExtractedJournals(); + + // do not use array_merge because you want keys to overwrite (otherwise you get double results): + $journals = $result + $journals; + } + $array = []; + + foreach ($journals as $journal) { + $key = sprintf('%s-%s', $journal['destination_account_id'], $journal['currency_id']); + $array[$key] = $array[$key] ?? [ + 'sum' => '0', + 'id' => $journal['destination_account_id'], + 'name' => $journal['destination_account_name'], + 'iban' => $journal['destination_account_iban'], + 'currency_id' => $journal['currency_id'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->positive($journal['amount'])); + + // also do foreign amount: + if (0 !== (int)$journal['foreign_currency_id']) { + $key = sprintf('%s-%s', $journal['destination_account_id'], $journal['foreign_currency_id']); + $array[$key] = $array[$key] ?? [ + 'sum' => '0', + 'id' => $journal['destination_account_id'], + 'name' => $journal['destination_account_name'], + 'iban' => $journal['destination_account_iban'], + 'currency_id' => $journal['foreign_currency_id'], + 'currency_name' => $journal['foreign_currency_name'], + 'currency_symbol' => $journal['foreign_currency_symbol'], + 'currency_code' => $journal['foreign_currency_code'], + 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->positive($journal['foreign_amount'])); + } + } + + return $array; + } + + /** + * @inheritDoc + */ + public function sumIncomeBySource( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null + ): array { + $start->startOfDay(); + $end->endOfDay(); + + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->withAccountInformation(); + + if (null !== $accounts) { + $collector->setDestinationAccounts($accounts); + } + if (null !== $revenue) { + $collector->setSourceAccounts($revenue); + } + if (null !== $currency) { + $collector->setCurrency($currency); + } + $journals = $collector->getExtractedJournals(); + + // same but for foreign currencies: + if (null !== $currency) { + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT]) + ->setForeignCurrency($currency)->withAccountInformation(); + + if (null !== $accounts) { + $collector->setDestinationAccounts($accounts); + } + if (null !== $revenue) { + $collector->setSourceAccounts($revenue); + } + $result = $collector->getExtractedJournals(); + + // do not use array_merge because you want keys to overwrite (otherwise you get double results): + $journals = $result + $journals; + } + $array = []; + + foreach ($journals as $journal) { + $key = sprintf('%s-%s', $journal['source_account_id'], $journal['currency_id']); + $array[$key] = $array[$key] ?? [ + 'sum' => '0', + 'id' => $journal['source_account_id'], + 'name' => $journal['source_account_name'], + 'iban' => $journal['source_account_iban'], + 'currency_id' => $journal['currency_id'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->positive($journal['amount'])); + + // also do foreign amount: + if (0 !== (int)$journal['foreign_currency_id']) { + $key = sprintf('%s-%s', $journal['source_account_id'], $journal['foreign_currency_id']); + $array[$key] = $array[$key] ?? [ + 'sum' => '0', + 'id' => $journal['source_account_id'], + 'name' => $journal['source_account_name'], + 'iban' => $journal['source_account_iban'], + 'currency_id' => $journal['foreign_currency_id'], + 'currency_name' => $journal['foreign_currency_name'], + 'currency_symbol' => $journal['foreign_currency_symbol'], + 'currency_code' => $journal['foreign_currency_code'], + 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->positive($journal['foreign_amount'])); + } + } + + return $array; + } } diff --git a/app/Repositories/Account/OperationsRepositoryInterface.php b/app/Repositories/Account/OperationsRepositoryInterface.php index 6e4f0d94a4..86ccdae393 100644 --- a/app/Repositories/Account/OperationsRepositoryInterface.php +++ b/app/Repositories/Account/OperationsRepositoryInterface.php @@ -78,6 +78,36 @@ interface OperationsRepositoryInterface public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null ): array; + /** + * Sum of withdrawal journals in period for a set of accounts, grouped per source / currency. Amounts are always negative. + * + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $expense + * @param TransactionCurrency|null $currency + * + * @return array + */ + public function sumExpensesBySource( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + ): array; + + /** + * Sum of withdrawal journals in period for a set of accounts, grouped per destination / currency. Amounts are always negative. + * + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $expense + * @param TransactionCurrency|null $currency + * + * @return array + */ + public function sumExpensesByDestination( + Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + ): array; + /** * Sum of income journals in period for a set of accounts, grouped per currency. Amounts are always positive. * @@ -92,6 +122,34 @@ interface OperationsRepositoryInterface public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null ): array; + /** + * Sum of income journals in period for a set of accounts, grouped per destination + currency. Amounts are always positive. + * + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $revenue + * @param TransactionCurrency|null $currency + * + * @return array + */ + public function sumIncomeByDestination(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null + ): array; + + /** + * Sum of income journals in period for a set of accounts, grouped per source + currency. Amounts are always positive. + * + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $revenue + * @param TransactionCurrency|null $currency + * + * @return array + */ + public function sumIncomeBySource(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null + ): array; + /** * Sum of transfers in period for a set of accounts, grouped per currency. Amounts are always positive. *