diff --git a/app/Api/V1/Controllers/Models/AvailableBudget/ShowController.php b/app/Api/V1/Controllers/Models/AvailableBudget/ShowController.php index 3cecd9c500..8de4ceaed8 100644 --- a/app/Api/V1/Controllers/Models/AvailableBudget/ShowController.php +++ b/app/Api/V1/Controllers/Models/AvailableBudget/ShowController.php @@ -89,8 +89,6 @@ class ShowController extends Controller $admin = auth()->user(); $enrichment = new AvailableBudgetEnrichment(); $enrichment->setUser($admin); - $enrichment->setStart($start); - $enrichment->setEnd($end); $availableBudgets = $enrichment->enrich($availableBudgets); // make paginator: diff --git a/app/Repositories/Budget/NoBudgetRepository.php b/app/Repositories/Budget/NoBudgetRepository.php index 3cf6e2d846..4a36b6cdc9 100644 --- a/app/Repositories/Budget/NoBudgetRepository.php +++ b/app/Repositories/Budget/NoBudgetRepository.php @@ -32,6 +32,7 @@ use FireflyIII\Support\Report\Summarizer\TransactionSummarizer; use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface; use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; /** * Class NoBudgetRepository @@ -98,4 +99,22 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface, UserGroupInterf return $summarizer->groupByCurrencyId($journals); } + + #[\Override] public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array + { + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); + + if ($accounts instanceof Collection && $accounts->count() > 0) { + $collector->setAccounts($accounts); + } + if ($currency instanceof TransactionCurrency) { + $collector->setCurrency($currency); + } + $collector->withoutBudget(); + $collector->withBudgetInformation(); + return $collector->getExtractedJournals(); + } + } diff --git a/app/Repositories/Budget/NoBudgetRepositoryInterface.php b/app/Repositories/Budget/NoBudgetRepositoryInterface.php index f35cbba670..01b42c3396 100644 --- a/app/Repositories/Budget/NoBudgetRepositoryInterface.php +++ b/app/Repositories/Budget/NoBudgetRepositoryInterface.php @@ -49,4 +49,6 @@ interface NoBudgetRepositoryInterface public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array; public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array; + + public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array; } diff --git a/app/Repositories/Budget/OperationsRepository.php b/app/Repositories/Budget/OperationsRepository.php index a2fc46ca2a..db8c85a20a 100644 --- a/app/Repositories/Budget/OperationsRepository.php +++ b/app/Repositories/Budget/OperationsRepository.php @@ -283,16 +283,15 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn return $summarizer->groupByCurrencyId($journals, 'negative', false); } - public function sumCollectedExpenses(array $expenses, Carbon $start, Carbon $end, bool $convertToPrimary = false): array + public function sumCollectedExpenses(array $expenses, Carbon $start, Carbon $end, TransactionCurrency $transactionCurrency, bool $convertToPrimary = false): array { Log::debug(sprintf('Start of %s.', __METHOD__)); $summarizer = new TransactionSummarizer($this->user); - // 2025-04-21 overrule "convertToPrimary" because in this particular view, we never want to do this. $summarizer->setConvertToPrimary($convertToPrimary); // filter $journals by range. - $expenses = array_filter($expenses, static function (array $expense) use ($start, $end): bool { - return $expense['date']->between($start, $end); + $expenses = array_filter($expenses, static function (array $expense) use ($start, $end, $transactionCurrency): bool { + return $expense['date']->between($start, $end) && $expense['currency_id'] === $transactionCurrency->id; }); return $summarizer->groupByCurrencyId($expenses, 'negative', false); diff --git a/app/Repositories/Budget/OperationsRepositoryInterface.php b/app/Repositories/Budget/OperationsRepositoryInterface.php index 487ae5a26b..0f58e73b64 100644 --- a/app/Repositories/Budget/OperationsRepositoryInterface.php +++ b/app/Repositories/Budget/OperationsRepositoryInterface.php @@ -74,7 +74,7 @@ interface OperationsRepositoryInterface bool $convertToPrimary = false ): array; - public function sumCollectedExpenses(array $expenses, Carbon $start, Carbon $end, bool $convertToPrimary = false): array; + public function sumCollectedExpenses(array $expenses, Carbon $start, Carbon $end, TransactionCurrency $transactionCurrency, bool $convertToPrimary = false): array; public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null): array; } diff --git a/app/Support/JsonApi/Enrichments/AvailableBudgetEnrichment.php b/app/Support/JsonApi/Enrichments/AvailableBudgetEnrichment.php index 0500ad2863..9071339ced 100644 --- a/app/Support/JsonApi/Enrichments/AvailableBudgetEnrichment.php +++ b/app/Support/JsonApi/Enrichments/AvailableBudgetEnrichment.php @@ -38,16 +38,16 @@ use Illuminate\Support\Facades\Log; class AvailableBudgetEnrichment implements EnrichmentInterface { - private User $user; - private UserGroup $userGroup; - private TransactionCurrency $primaryCurrency; - private bool $convertToPrimary = false; - private array $ids = []; - private Collection $collection; - private array $spentInBudgets = []; - private array $spentOutsideBudgets = []; - private array $pcSpentInBudgets = []; - private array $pcSpentOutsideBudgets = []; + private User $user; + private UserGroup $userGroup; + private TransactionCurrency $primaryCurrency; + private bool $convertToPrimary = false; + private array $ids = []; + private Collection $collection; + private array $spentInBudgets = []; + private array $spentOutsideBudgets = []; + private array $pcSpentInBudgets = []; + private array $pcSpentOutsideBudgets = []; private readonly NoBudgetRepositoryInterface $noBudgetRepository; private readonly OperationsRepositoryInterface $opsRepository; private readonly BudgetRepositoryInterface $repository; @@ -58,8 +58,8 @@ class AvailableBudgetEnrichment implements EnrichmentInterface public function __construct() { - $this->primaryCurrency = Amount::getPrimaryCurrency(); - $this->convertToPrimary = Amount::convertToPrimary(); + $this->primaryCurrency = Amount::getPrimaryCurrency(); + $this->convertToPrimary = Amount::convertToPrimary(); $this->noBudgetRepository = app(NoBudgetRepositoryInterface::class); $this->opsRepository = app(OperationsRepositoryInterface::class); $this->repository = app(BudgetRepositoryInterface::class); @@ -86,7 +86,7 @@ class AvailableBudgetEnrichment implements EnrichmentInterface #[\Override] public function setUser(User $user): void { - $this->user = $user; + $this->user = $user; $this->setUserGroup($user->userGroup); } @@ -107,25 +107,28 @@ class AvailableBudgetEnrichment implements EnrichmentInterface $this->ids = array_unique($this->ids); } - public function setStart(?Carbon $start): void + private function collectSpentInfo(): void { - $this->start = $start; - } + $start = $this->collection->min('start_date'); + $end = $this->collection->max('end_date'); + $allActive = $this->repository->getActiveBudgets(); + $spentInBudgets = $this->opsRepository->collectExpenses($start, $end, null, $allActive, null); + $spentOutsideBudgets = $this->noBudgetRepository->collectExpenses($start, $end, null, null, null); + foreach ($this->collection as $availableBudget) { + $id = (int) $availableBudget->id; + $filteredSpentInBudgets = $this->opsRepository->sumCollectedExpenses($spentInBudgets, $availableBudget->start_date, $availableBudget->end_date, $availableBudget->transactionCurrency, false); + $filteredSpentOutsideBudgets = $this->opsRepository->sumCollectedExpenses($spentOutsideBudgets, $availableBudget->start_date, $availableBudget->end_date, $availableBudget->transactionCurrency, false); + $this->spentInBudgets[$id] = array_values($filteredSpentInBudgets); + $this->spentOutsideBudgets[$id] = array_values($filteredSpentOutsideBudgets); + + if (true === $this->convertToPrimary) { + $pcFilteredSpentInBudgets = $this->opsRepository->sumCollectedExpenses($spentInBudgets, $availableBudget->start_date, $availableBudget->end_date, $availableBudget->transactionCurrency, true); + $pcFilteredSpentOutsideBudgets = $this->opsRepository->sumCollectedExpenses($spentOutsideBudgets, $availableBudget->start_date, $availableBudget->end_date, $availableBudget->transactionCurrency, true); + $this->pcSpentInBudgets[$id] = array_values($pcFilteredSpentInBudgets); + $this->pcSpentOutsideBudgets[$id] = array_values($pcFilteredSpentOutsideBudgets); + } - public function setEnd(?Carbon $end): void - { - $this->end = $end; - } - private function collectSpentInfo(): void { - $start = $this->collection->min('start_date'); - $end = $this->collection->max('end_date'); - $allActive = $this->repository->getActiveBudgets(); - $spentInBudgets = $this->opsRepository->collectExpenses($start, $end, null, $allActive, null); - foreach($this->collection as $availableBudget) { - $filteredSpentInBudgets = $this->opsRepository->sumCollectedExpenses($spentInBudgets, $availableBudget->start_date, $availableBudget->end_date, $this->convertToPrimary); - $id = (int) $availableBudget->id; - $this->spentInBudgets[$id] = array_values($filteredSpentInBudgets); // filter arrays on date. // send them to sumCollection thing. // save. @@ -144,9 +147,10 @@ class AvailableBudgetEnrichment implements EnrichmentInterface $id = (int) $item->id; $meta = [ 'spent_in_budgets' => $spentInsideBudgets[$id] ?? [], - 'spent_outside_budgets' => $spentOutsideBudgets[$id] ?? [], 'pc_spent_in_budgets' => $pcSpentInBudgets[$id] ?? [], - 'pc_spent_outside_budgets' => $pcSpentOutsideBudgets ?? [], + + 'spent_outside_budgets' => $spentOutsideBudgets[$id] ?? [], + 'pc_spent_outside_budgets' => $pcSpentOutsideBudgets[$id] ?? [], ]; $item->meta = $meta; return $item; diff --git a/app/Transformers/AvailableBudgetTransformer.php b/app/Transformers/AvailableBudgetTransformer.php index 648dac8d17..600a4c48e4 100644 --- a/app/Transformers/AvailableBudgetTransformer.php +++ b/app/Transformers/AvailableBudgetTransformer.php @@ -26,9 +26,6 @@ namespace FireflyIII\Transformers; use FireflyIII\Models\AvailableBudget; use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\Repositories\Budget\NoBudgetRepositoryInterface; -use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; use FireflyIII\Support\Facades\Amount; /** @@ -36,22 +33,16 @@ use FireflyIII\Support\Facades\Amount; */ class AvailableBudgetTransformer extends AbstractTransformer { - private readonly bool $convertToPrimary; - private readonly TransactionCurrency $primary; - private readonly NoBudgetRepositoryInterface $noBudgetRepository; - private readonly OperationsRepositoryInterface $opsRepository; - private readonly BudgetRepositoryInterface $repository; + private readonly bool $convertToPrimary; + private readonly TransactionCurrency $primary; /** * CurrencyTransformer constructor. */ public function __construct() { - $this->repository = app(BudgetRepositoryInterface::class); - $this->opsRepository = app(OperationsRepositoryInterface::class); - $this->noBudgetRepository = app(NoBudgetRepositoryInterface::class); - $this->primary = Amount::getPrimaryCurrency(); - $this->convertToPrimary = Amount::convertToPrimary(); + $this->primary = Amount::getPrimaryCurrency(); + $this->convertToPrimary = Amount::convertToPrimary(); } /** @@ -59,7 +50,6 @@ class AvailableBudgetTransformer extends AbstractTransformer */ public function transform(AvailableBudget $availableBudget): array { - $this->repository->setUser($availableBudget->user); $currency = $availableBudget->transactionCurrency; $amount = app('steam')->bcround($availableBudget->amount, $currency->decimal_places); $pcAmount = null; @@ -68,7 +58,7 @@ class AvailableBudgetTransformer extends AbstractTransformer $pcAmount = app('steam')->bcround($availableBudget->native_amount, $this->primary->decimal_places); } - $data = [ + $data = [ 'id' => (string) $availableBudget->id, 'created_at' => $availableBudget->created_at->toAtomString(), 'updated_at' => $availableBudget->updated_at->toAtomString(), @@ -100,28 +90,8 @@ class AvailableBudgetTransformer extends AbstractTransformer ], ], ]; - $start = $this->parameters->get('start'); - $end = $this->parameters->get('end'); - if (null !== $start && null !== $end) { - $data['old_spent_in_budgets'] = $this->getSpentInBudgets(); - $data['old_spent_no_budget'] = $this->spentOutsideBudgets(); - } - return $data; } - private function getSpentInBudgets(): array - { - $allActive = $this->repository->getActiveBudgets(); - $sums = $this->opsRepository->sumExpenses($this->parameters->get('start'), $this->parameters->get('end'), null, $allActive); - return array_values($sums); - } - - private function spentOutsideBudgets(): array - { - $sums = $this->noBudgetRepository->sumExpenses($this->parameters->get('start'), $this->parameters->get('end')); - - return array_values($sums); - } }