diff --git a/app/Factory/PiggyBankFactory.php b/app/Factory/PiggyBankFactory.php index df9b54bc46..7f9def7600 100644 --- a/app/Factory/PiggyBankFactory.php +++ b/app/Factory/PiggyBankFactory.php @@ -169,9 +169,20 @@ class PiggyBankFactory } - private function resetOrder(): void + public function resetOrder(): void { - $set = $this->user->piggyBanks()->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']); + // TODO duplicate code + $set = PiggyBank + ::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') + ->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id') + ->where('accounts.user_id', $this->user->id) + ->with( + [ + 'account', + 'objectGroups', + ] + ) + ->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']); $current = 1; foreach ($set as $piggyBank) { if ($piggyBank->order !== $current) { diff --git a/app/Http/Controllers/PiggyBank/IndexController.php b/app/Http/Controllers/PiggyBank/IndexController.php index 9c08ebdf25..eca160f505 100644 --- a/app/Http/Controllers/PiggyBank/IndexController.php +++ b/app/Http/Controllers/PiggyBank/IndexController.php @@ -36,6 +36,7 @@ use FireflyIII\Transformers\PiggyBankTransformer; use Illuminate\Contracts\View\Factory; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Collection; use Illuminate\View\View; use Symfony\Component\HttpFoundation\ParameterBag; @@ -57,7 +58,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string)trans('firefly.piggyBanks')); + app('view')->share('title', (string) trans('firefly.piggyBanks')); app('view')->share('mainTitleIcon', 'fa-bullseye'); $this->piggyRepos = app(PiggyBankRepositoryInterface::class); @@ -79,63 +80,26 @@ class IndexController extends Controller public function index() { $this->cleanupObjectGroups(); - //$this->piggyRepos->resetOrder(); - $collection = $this->piggyRepos->getPiggyBanks(); - $accounts = []; + $this->piggyRepos->resetOrder(); + $collection = $this->piggyRepos->getPiggyBanks(); /** @var Carbon $end */ - $end = session('end', today(config('app.timezone'))->endOfMonth()); + $end = session('end', today(config('app.timezone'))->endOfMonth()); // transform piggies using the transformer: - $parameters = new ParameterBag(); + $parameters = new ParameterBag(); $parameters->set('end', $end); - // make piggy bank groups: - $piggyBanks = []; - - /** @var PiggyBankTransformer $transformer */ - $transformer = app(PiggyBankTransformer::class); - $transformer->setParameters(new ParameterBag()); /** @var AccountTransformer $accountTransformer */ $accountTransformer = app(AccountTransformer::class); $accountTransformer->setParameters($parameters); - /** @var PiggyBank $piggy */ - foreach ($collection as $piggy) { - $array = $transformer->transform($piggy); - $groupOrder = (int)$array['object_group_order']; - // make group array if necessary: - $piggyBanks[$groupOrder] ??= [ - 'object_group_id' => $array['object_group_id'] ?? 0, - 'object_group_title' => $array['object_group_title'] ?? trans('firefly.default_group_title_name'), - 'piggy_banks' => [], - ]; - - $account = $accountTransformer->transform($piggy->account); - $accountId = (int)$account['id']; - $array['attachments'] = $this->piggyRepos->getAttachments($piggy); - if (!array_key_exists($accountId, $accounts)) { - // create new: - $accounts[$accountId] = $account; - - // add some interesting details: - $accounts[$accountId]['left'] = $accounts[$accountId]['current_balance']; - $accounts[$accountId]['saved'] = 0; - $accounts[$accountId]['target'] = 0; - $accounts[$accountId]['to_save'] = 0; - } - - // calculate new interesting fields: - $accounts[$accountId]['left'] -= $array['current_amount']; - $accounts[$accountId]['saved'] += $array['current_amount']; - $accounts[$accountId]['target'] += $array['target_amount']; - $accounts[$accountId]['to_save'] += ($array['target_amount'] - $array['current_amount']); - $array['account_name'] = $account['name']; - $piggyBanks[$groupOrder]['piggy_banks'][] = $array; - } - // do a bunch of summaries. - $piggyBanks = $this->makeSums($piggyBanks); + // data + $piggyBanks = $this->groupPiggyBanks($collection); + $accounts = $this->collectAccounts($collection); + $accounts = $this->mergeAccountsAndPiggies($piggyBanks, $accounts); + $piggyBanks = $this->makeSums($piggyBanks); ksort($piggyBanks); @@ -148,7 +112,7 @@ class IndexController extends Controller foreach ($piggyBanks as $groupOrder => $group) { $groupId = $group['object_group_id']; foreach ($group['piggy_banks'] as $piggy) { - $currencyId = $piggy['currency_id']; + $currencyId = $piggy['currency_id']; $sums[$groupId][$currencyId] ??= [ 'target' => '0', 'saved' => '0', @@ -163,10 +127,10 @@ class IndexController extends Controller // current_amount // left_to_save // save_per_month - $sums[$groupId][$currencyId]['target'] = bcadd($sums[$groupId][$currencyId]['target'], (string)$piggy['target_amount']); - $sums[$groupId][$currencyId]['saved'] = bcadd($sums[$groupId][$currencyId]['saved'], (string)$piggy['current_amount']); - $sums[$groupId][$currencyId]['left_to_save'] = bcadd($sums[$groupId][$currencyId]['left_to_save'], (string)$piggy['left_to_save']); - $sums[$groupId][$currencyId]['save_per_month'] = bcadd($sums[$groupId][$currencyId]['save_per_month'], (string)$piggy['save_per_month']); + $sums[$groupId][$currencyId]['target'] = bcadd($sums[$groupId][$currencyId]['target'], (string) $piggy['target_amount']); + $sums[$groupId][$currencyId]['saved'] = bcadd($sums[$groupId][$currencyId]['saved'], (string) $piggy['current_amount']); + $sums[$groupId][$currencyId]['left_to_save'] = bcadd($sums[$groupId][$currencyId]['left_to_save'], (string) $piggy['left_to_save']); + $sums[$groupId][$currencyId]['save_per_month'] = bcadd($sums[$groupId][$currencyId]['save_per_month'], (string) $piggy['save_per_month']); } } foreach ($piggyBanks as $groupOrder => $group) { @@ -182,8 +146,8 @@ class IndexController extends Controller */ public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse { - $objectGroupTitle = (string)$request->get('objectGroupTitle'); - $newOrder = (int)$request->get('order'); + $objectGroupTitle = (string) $request->get('objectGroupTitle'); + $newOrder = (int) $request->get('order'); $this->piggyRepos->setOrder($piggyBank, $newOrder); if ('' !== $objectGroupTitle) { $this->piggyRepos->setObjectGroup($piggyBank, $objectGroupTitle); @@ -194,4 +158,91 @@ class IndexController extends Controller return response()->json(['data' => 'OK']); } + + private function groupPiggyBanks(Collection $collection): array + { + /** @var PiggyBankTransformer $transformer */ + $transformer = app(PiggyBankTransformer::class); + $transformer->setParameters(new ParameterBag()); + $piggyBanks = []; + /** @var PiggyBank $piggy */ + foreach ($collection as $piggy) { + $array = $transformer->transform($piggy); + $groupOrder = (int) $array['object_group_order']; + $piggyBanks[$groupOrder] ??= [ + 'object_group_id' => $array['object_group_id'] ?? 0, + 'object_group_title' => $array['object_group_title'] ?? trans('firefly.default_group_title_name'), + 'piggy_banks' => [], + ]; + $array['attachments'] = $this->piggyRepos->getAttachments($piggy); + + // sum the total amount for the index. + $piggyBanks[$groupOrder]['piggy_banks'][] = $array; + } + return $piggyBanks; + } + + private function collectAccounts(Collection $collection): array + { + /** @var Carbon $end */ + $end = session('end', today(config('app.timezone'))->endOfMonth()); + + // transform piggies using the transformer: + $parameters = new ParameterBag(); + $parameters->set('end', $end); + + /** @var AccountTransformer $accountTransformer */ + $accountTransformer = app(AccountTransformer::class); + $accountTransformer->setParameters($parameters); + + $return = []; + /** @var PiggyBank $piggy */ + foreach ($collection as $piggy) { + $accounts = $piggy->accounts; + /** @var Account $account */ + foreach ($accounts as $account) { + $array = $accountTransformer->transform($account); + $accountId = (int) $array['id']; + if (!array_key_exists($accountId, $return)) { + $return[$accountId] = $array; + + // add some interesting details: + $return[$accountId]['left'] = $return[$accountId]['current_balance']; + $return[$accountId]['saved'] = '0'; + $return[$accountId]['target'] = '0'; + $return[$accountId]['to_save'] = '0'; + } + + // calculate new interesting fields: +// $return[$accountId]['left'] -= $array['current_amount']; +// $return[$accountId]['saved'] += $array['current_amount']; +// $return[$accountId]['target'] += $array['target_amount']; +// $return[$accountId]['to_save'] += ($array['target_amount'] - $array['current_amount']); +// $return['account_name'] = $account['name']; + + } + } + return $return; + } + + private function mergeAccountsAndPiggies(array $piggyBanks, array $accounts): array + { + /** @var array $piggyBank */ + foreach ($piggyBanks as $group) { + foreach ($group['piggy_banks'] as $piggyBank) { + // loop all accounts in this piggy bank subtract the current amount from "left to save" in the $accounts array. + /** @var array $piggyAccount */ + foreach ($piggyBank['accounts'] as $piggyAccount) { + $accountId = $piggyAccount['id']; + if (array_key_exists($accountId, $accounts)) { + $accounts[$accountId]['left'] = bcsub($accounts[$accountId]['left'], $piggyAccount['current_amount']); + $accounts[$accountId]['saved'] = bcadd($accounts[$accountId]['saved'], $piggyAccount['current_amount']); + $accounts[$accountId]['target'] = bcadd($accounts[$accountId]['target'], $piggyBank['target_amount']); + $accounts[$accountId]['to_save'] = bcadd($accounts[$accountId]['to_save'], bcsub($piggyBank['target_amount'], $piggyAccount['current_amount'])); + } + } + } + } + return $accounts; + } } diff --git a/app/Models/PiggyBank.php b/app/Models/PiggyBank.php index d5a936cf31..fa797977fc 100644 --- a/app/Models/PiggyBank.php +++ b/app/Models/PiggyBank.php @@ -116,7 +116,7 @@ class PiggyBank extends Model public function accounts(): BelongsToMany { - return $this->belongsToMany(Account::class); + return $this->belongsToMany(Account::class)->withPivot('current_amount'); } public function piggyBankRepetitions(): HasMany diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index ce32ca3269..cf73589b94 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -25,6 +25,7 @@ namespace FireflyIII\Repositories\PiggyBank; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Factory\PiggyBankFactory; use FireflyIII\Models\Attachment; use FireflyIII\Models\Note; use FireflyIII\Models\PiggyBank; @@ -285,7 +286,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface 'objectGroups', ] ) - ->orderBy('piggy_banks.order', 'ASC')->get(); + ->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']); } /** @@ -352,4 +353,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface { throw new FireflyException('TODO Not implemented'); } + + #[\Override] public function resetOrder(): void + { + $factory = new PiggyBankFactory(); + $factory->setUser($this->user); + $factory->resetOrder(); + } } diff --git a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php index dfe534f4cf..b2c13d5764 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php +++ b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php @@ -113,10 +113,7 @@ interface PiggyBankRepositoryInterface public function removeObjectGroup(PiggyBank $piggyBank): PiggyBank; -// /** -// * Correct order of piggies in case of issues. -// */ -// public function resetOrder(): void; + public function resetOrder(): void; /** * Search for piggy banks. diff --git a/app/Transformers/PiggyBankTransformer.php b/app/Transformers/PiggyBankTransformer.php index 701c816257..ae15958fbe 100644 --- a/app/Transformers/PiggyBankTransformer.php +++ b/app/Transformers/PiggyBankTransformer.php @@ -132,10 +132,11 @@ class PiggyBankTransformer extends AbstractTransformer private function renderAccounts(PiggyBank $piggyBank): array { $return = []; - foreach ($piggyBank->accounts as $account) { + foreach ($piggyBank->accounts()->get() as $account) { $return[] = [ 'id' => $account->id, 'name' => $account->name, + 'current_amount' => $account->pivot->current_amount, // TODO add balance, add left to save. ]; }