Files
firefly-iii/app/Support/JsonApi/Enrichments/BudgetLimitEnrichment.php

159 lines
5.9 KiB
PHP
Raw Normal View History

2025-08-03 17:42:07 +02:00
<?php
declare(strict_types=1);
2025-08-03 17:42:07 +02:00
namespace FireflyIII\Support\JsonApi\Enrichments;
use Carbon\Carbon;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\Note;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\Budget\OperationsRepository;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
class BudgetLimitEnrichment implements EnrichmentInterface
{
private User $user;
private UserGroup $userGroup;
private Collection $collection;
private array $ids = [];
private array $notes = [];
private Carbon $start;
private Carbon $end;
private Collection $budgets;
private array $expenses = [];
private array $pcExpenses = [];
2025-08-07 19:37:36 +02:00
private array $currencyIds = [];
private array $currencies = [];
2025-08-03 17:42:07 +02:00
private bool $convertToPrimary = true;
private TransactionCurrency $primaryCurrency;
public function __construct()
{
$this->convertToPrimary = Amount::convertToPrimary();
$this->primaryCurrency = Amount::getPrimaryCurrency();
}
public function enrich(Collection $collection): Collection
{
$this->collection = $collection;
$this->collectIds();
2025-08-07 19:37:36 +02:00
$this->collectCurrencies();
2025-08-03 17:42:07 +02:00
$this->collectNotes();
$this->collectBudgets();
$this->appendCollectedData();
2025-08-03 17:42:07 +02:00
return $this->collection;
}
public function enrichSingle(array|Model $model): array|Model
2025-08-03 17:42:07 +02:00
{
Log::debug(__METHOD__);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();
}
public function setUser(User $user): void
{
$this->user = $user;
$this->userGroup = $user->userGroup;
}
public function setUserGroup(UserGroup $userGroup): void
{
$this->userGroup = $userGroup;
}
private function collectIds(): void
{
2025-08-16 06:02:26 +02:00
$this->start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
$this->end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth();
2025-08-03 17:42:07 +02:00
/** @var BudgetLimit $limit */
foreach ($this->collection as $limit) {
2025-08-07 19:37:36 +02:00
$id = (int)$limit->id;
$this->ids[] = $id;
if (0 !== (int)$limit->transaction_currency_id) {
$this->currencyIds[$id] = (int)$limit->transaction_currency_id;
}
2025-08-03 17:42:07 +02:00
}
2025-08-07 19:37:36 +02:00
$this->ids = array_unique($this->ids);
$this->currencyIds = array_unique($this->currencyIds);
2025-08-03 17:42:07 +02:00
}
private function collectNotes(): void
{
$notes = Note::query()->whereIn('noteable_id', $this->ids)
->whereNotNull('notes.text')
->where('notes.text', '!=', '')
->where('noteable_type', BudgetLimit::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
;
2025-08-03 17:42:07 +02:00
foreach ($notes as $note) {
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
}
Log::debug(sprintf('Enrich with %d note(s)', count($this->notes)));
}
private function appendCollectedData(): void
{
$this->collection = $this->collection->map(function (BudgetLimit $item) {
$id = (int)$item->id;
2025-08-07 19:37:36 +02:00
$currencyId = (int)$item->transaction_currency_id;
if (0 === $currencyId) {
$currencyId = $this->primaryCurrency->id;
}
2025-08-03 17:42:07 +02:00
$meta = [
'notes' => $this->notes[$id] ?? null,
'spent' => $this->expenses[$id] ?? [],
'pc_spent' => $this->pcExpenses[$id] ?? [],
2025-08-07 19:37:36 +02:00
'currency' => $this->currencies[$currencyId],
2025-08-03 17:42:07 +02:00
];
$item->meta = $meta;
2025-08-03 17:42:07 +02:00
return $item;
});
}
private function collectBudgets(): void
{
$budgetIds = $this->collection->pluck('budget_id')->unique()->toArray();
$this->budgets = Budget::whereIn('id', $budgetIds)->get();
$repository = app(OperationsRepository::class);
2025-08-03 17:42:07 +02:00
$repository->setUser($this->user);
$expenses = $repository->collectExpenses($this->start, $this->end, null, $this->budgets, null);
2025-08-03 17:42:07 +02:00
/** @var BudgetLimit $budgetLimit */
foreach ($this->collection as $budgetLimit) {
$id = (int)$budgetLimit->id;
$filteredExpenses = $repository->sumCollectedExpenses($expenses, $budgetLimit->start_date, $budgetLimit->end_date, $budgetLimit->transactionCurrency, false);
$this->expenses[$id] = array_values($filteredExpenses);
if (true === $this->convertToPrimary && $budgetLimit->transactionCurrency->id !== $this->primaryCurrency->id) {
$pcFilteredExpenses = $repository->sumCollectedExpenses($expenses, $budgetLimit->start_date, $budgetLimit->end_date, $budgetLimit->transactionCurrency, true);
$this->pcExpenses[$id] = array_values($pcFilteredExpenses);
}
if (true === $this->convertToPrimary && $budgetLimit->transactionCurrency->id === $this->primaryCurrency->id) {
2025-08-03 20:17:50 +02:00
$this->pcExpenses[$id] = $this->expenses[$id] ?? [];
2025-08-03 17:42:07 +02:00
}
}
}
2025-08-07 19:37:36 +02:00
private function collectCurrencies(): void
{
$this->currencies[$this->primaryCurrency->id] = $this->primaryCurrency;
$currencies = TransactionCurrency::whereIn('id', $this->currencyIds)->whereNot('id', $this->primaryCurrency->id)->get();
foreach ($currencies as $currency) {
$this->currencies[(int)$currency->id] = $currency;
}
}
2025-08-03 17:42:07 +02:00
}