From 5ecc1929f99dbdab978418728af883739306d4c6 Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 20 Dec 2023 07:31:32 +0100 Subject: [PATCH] Add balance group. --- .../Controllers/Summary/BasicController.php | 130 +--------------- .../Http/Api/SummaryBalanceGrouped.php | 142 ++++++++++++++++++ 2 files changed, 149 insertions(+), 123 deletions(-) create mode 100644 app/Support/Http/Api/SummaryBalanceGrouped.php diff --git a/app/Api/V2/Controllers/Summary/BasicController.php b/app/Api/V2/Controllers/Summary/BasicController.php index 6166b21675..8aa837fca1 100644 --- a/app/Api/V2/Controllers/Summary/BasicController.php +++ b/app/Api/V2/Controllers/Summary/BasicController.php @@ -33,7 +33,6 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Report\NetWorthInterface; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; -use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionType; use FireflyIII\Models\UserGroup; use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; @@ -43,6 +42,7 @@ use FireflyIII\Repositories\UserGroups\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\UserGroups\Budget\OperationsRepositoryInterface; use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Http\Api\ExchangeRateConverter; +use FireflyIII\Support\Http\Api\SummaryBalanceGrouped; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\User; use Illuminate\Http\JsonResponse; @@ -126,20 +126,12 @@ class BasicController extends Controller */ private function getBalanceInformation(Carbon $start, Carbon $end): array { - // prep some arrays: - $incomes = [ - 'native' => '0', - ]; - $expenses = [ - 'native' => '0', - ]; - $sums = [ - 'native' => '0', - ]; $return = []; $currencies = []; - $converter = new ExchangeRateConverter(); + $object = new SummaryBalanceGrouped(); $default = app('amount')->getDefaultCurrency(); + + $object->setDefault($default); /** @var User $user */ $user = auth()->user(); @@ -156,30 +148,8 @@ class BasicController extends Controller ->setRange($start, $end); $set = $collector->getExtractedJournals(); - /** @var array $transactionJournal */ - foreach ($set as $transactionJournal) { - // transaction info: - $currencyId = (int)$transactionJournal['currency_id']; - $amount = bcmul($transactionJournal['amount'], '-1'); - $currency = $currencies[$currencyId] ?? TransactionCurrency::find($currencyId); - $currencies[$currencyId] = $currency; - $nativeAmount = $converter->convert($currency, $default, $transactionJournal['date'], $amount); - if ((int)$transactionJournal['foreign_currency_id'] === $default->id) { - // use foreign amount instead - $nativeAmount = $transactionJournal['foreign_amount']; - } - // prep the arrays - $incomes[$currencyId] ??= '0'; - $incomes['native'] ??= '0'; - $sums[$currencyId] ??= '0'; - $sums['native'] ??= '0'; + $object->groupTransactions('income', $set); - // add values: - $incomes[$currencyId] = bcadd($incomes[$currencyId], $amount); - $sums[$currencyId] = bcadd($sums[$currencyId], $amount); - $incomes['native'] = bcadd($incomes['native'], $nativeAmount); - $sums['native'] = bcadd($sums['native'], $nativeAmount); - } // collect expenses of user using the new group collector. /** @var GroupCollectorInterface $collector */ @@ -193,95 +163,9 @@ class BasicController extends Controller ->setTypes([TransactionType::WITHDRAWAL]) ->setRange($start, $end); $set = $collector->getExtractedJournals(); + $object->groupTransactions('expense', $set); - /** @var array $transactionJournal */ - foreach ($set as $transactionJournal) { - // transaction info - $currencyId = (int)$transactionJournal['currency_id']; - $amount = $transactionJournal['amount']; - $currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId); - $currencies[$currencyId] = $currency; - $nativeAmount = $converter->convert($currency, $default, $transactionJournal['date'], $amount); - if ((int)$transactionJournal['foreign_currency_id'] === $default->id) { - // use foreign amount instead - $nativeAmount = $transactionJournal['foreign_amount']; - } - - // prep arrays - $expenses[$currencyId] ??= '0'; - $expenses['native'] ??= '0'; - $sums[$currencyId] ??= '0'; - $sums['native'] ??= '0'; - - // add values - $expenses[$currencyId] = bcadd($expenses[$currencyId], $amount); - $sums[$currencyId] = bcadd($sums[$currencyId], $amount); - $expenses['native'] = bcadd($expenses['native'], $nativeAmount); - $sums['native'] = bcadd($sums['native'], $nativeAmount); - } - - // create special array for native currency: - $return[] = [ - 'key' => 'balance-in-native', - 'value' => $sums['native'], - 'currency_id' => (string)$default->id, - 'currency_code' => $default->code, - 'currency_symbol' => $default->symbol, - 'currency_decimal_places' => $default->decimal_places, - ]; - $return[] = [ - 'key' => 'spent-in-native', - 'value' => $expenses['native'], - 'currency_id' => (string)$default->id, - 'currency_code' => $default->code, - 'currency_symbol' => $default->symbol, - 'currency_decimal_places' => $default->decimal_places, - ]; - $return[] = [ - 'key' => 'earned-in-native', - 'value' => $incomes['native'], - 'currency_id' => (string)$default->id, - 'currency_code' => $default->code, - 'currency_symbol' => $default->symbol, - 'currency_decimal_places' => $default->decimal_places, - ]; - - // format amounts: - $keys = array_keys($sums); - foreach ($keys as $currencyId) { - if ('native' === $currencyId) { - // skip native entries. - continue; - } - $currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId); - $currencies[$currencyId] = $currency; - // create objects for big array. - $return[] = [ - 'key' => sprintf('balance-in-%s', $currency->code), - 'value' => $sums[$currencyId] ?? '0', - 'currency_id' => (string)$currency->id, - 'currency_code' => $currency->code, - 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => $currency->decimal_places, - ]; - $return[] = [ - 'key' => sprintf('spent-in-%s', $currency->code), - 'value' => $expenses[$currencyId] ?? '0', - 'currency_id' => (string)$currency->id, - 'currency_code' => $currency->code, - 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => $currency->decimal_places, - ]; - $return[] = [ - 'key' => sprintf('earned-in-%s', $currency->code), - 'value' => $incomes[$currencyId] ?? '0', - 'currency_id' => (string)$currency->id, - 'currency_code' => $currency->code, - 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => $currency->decimal_places, - ]; - } - return $return; + return $object->groupData(); } /** diff --git a/app/Support/Http/Api/SummaryBalanceGrouped.php b/app/Support/Http/Api/SummaryBalanceGrouped.php new file mode 100644 index 0000000000..b2c45ffd3d --- /dev/null +++ b/app/Support/Http/Api/SummaryBalanceGrouped.php @@ -0,0 +1,142 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Support\Http\Api; + +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface; + +class SummaryBalanceGrouped +{ + private TransactionCurrency $default; + private array $amounts = []; + private array $keys = []; + private const string SUM = 'sum'; + private CurrencyRepositoryInterface $currencyRepository; + + public function __construct() + { + $this->keys = [self::SUM]; + $this->currencyRepository = app(CurrencyRepositoryInterface::class); + } + + /** + * TODO remember to do -1 for deposits. + * + * @param array $journals + * + * @return void + */ + public function groupTransactions(string $key, array $journals): void + { + $converter = new ExchangeRateConverter(); + $this->keys[] = $key; + /** @var array $journal */ + foreach ($journals as $journal) { + // transaction info: + $currencyId = (int)$journal['currency_id']; + $amount = $journal['amount']; + $currency = $currencies[$currencyId] ?? TransactionCurrency::find($currencyId); + $currencies[$currencyId] = $currency; + $nativeAmount = $converter->convert($currency, $this->default, $journal['date'], $amount); + if ((int)$journal['foreign_currency_id'] === $this->default->id) { + // use foreign amount instead + $nativeAmount = $journal['foreign_amount']; + } + // prep the arrays + $this->amounts[$key] ??= []; + $this->amounts[$key][$currencyId] ??= '0'; + $this->amounts[$key]['native'] ??= '0'; + $this->amounts[self::SUM][$currencyId] ??= '0'; + $this->amounts[self::SUM]['native'] ??= '0'; + + // add values: + $this->amounts[$key][$currencyId] = bcadd($this->amounts[$key][$currencyId], $amount); + $this->amounts[self::SUM][$currencyId] = bcadd($this->amounts[self::SUM][$currencyId], $amount); + $this->amounts[$key]['native'] = bcadd($this->amounts[$key]['native'], $nativeAmount); + $this->amounts[self::SUM]['native'] = bcadd($this->amounts[self::SUM]['native'], $nativeAmount); + } + } + + /** + * @return array + */ + public function groupData(): array + { + $return = []; + foreach ($this->keys as $key) { + $title = match ($key) { + 'sum' => 'balance', + 'expense' => 'spent', + 'income' => 'earned', + default => 'something' + }; + $amount = 'income' === $key ? bcsub($this->amounts[$key]['native'], '-1') : $this->amounts[$key]['native']; + $return[] = [ + 'key' => sprintf('%s-in-native', $title), + 'value' => $amount, + 'currency_id' => (string)$this->default->id, + 'currency_code' => $this->default->code, + 'currency_symbol' => $this->default->symbol, + 'currency_decimal_places' => $this->default->decimal_places, + ]; + } + // loop 3: format amounts: + $currencyIds = array_keys($this->amounts[self::SUM]); + foreach ($currencyIds as $currencyId) { + if ('native' === $currencyId) { + // skip native entries. + continue; + } + $currency = $currencies[$currencyId] ?? $this->currencyRepository->find($currencyId); + $currencies[$currencyId] = $currency; + // create objects for big array. + foreach ($this->keys as $key) { + $title = match ($key) { + 'sum' => 'balance', + 'expense' => 'spent', + 'income' => 'earned', + default => 'something' + }; + $amount = $this->amounts[$key][$currencyId] ?? '0'; + $amount = 'income' === $key ? bcsub($amount, '-1') : $amount; + $return[] = [ + 'key' => sprintf('%s-in-%s', $title, $currency->code), + 'value' => $amount, + 'currency_id' => (string)$currency->id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => $currency->decimal_places, + ]; + } + } + return $return; + } + + public function setDefault(TransactionCurrency $default): void + { + $this->default = $default; + } + + +}