A lot less queries for the account transformer.

This commit is contained in:
James Cole
2025-02-15 16:51:13 +01:00
parent f755dd2d48
commit 90fc4b44f2
11 changed files with 321 additions and 154 deletions

View File

@@ -25,14 +25,20 @@ declare(strict_types=1);
namespace FireflyIII\Support\JsonApi\Enrichments;
use Carbon\Carbon;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Location;
use FireflyIII\Models\Note;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\UserGroup;
use FireflyIII\Support\Facades\Balance;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Model;
@@ -67,15 +73,21 @@ class AccountEnrichment implements EnrichmentInterface
private array $accountTypes;
private array $currencies;
private array $meta;
private array $openingBalances;
private array $notes;
private array $locations;
public function __construct()
{
$this->convertToNative = false;
$this->accountIds = [];
$this->openingBalances = [];
$this->currencies = [];
$this->accountTypeIds = [];
$this->accountTypes = [];
$this->meta = [];
$this->notes = [];
$this->locations = [];
// $this->repository = app(AccountRepositoryInterface::class);
// $this->currencyRepository = app(CurrencyRepositoryInterface::class);
// $this->start = null;
@@ -105,6 +117,8 @@ class AccountEnrichment implements EnrichmentInterface
$this->collectAccountIds();
$this->getAccountTypes();
$this->collectMetaData();
$this->collectLocations();
$this->collectOpeningBalances();
// $this->default = app('amount')->getNativeCurrency();
// $this->currencies = [];
// $this->balances = [];
@@ -156,23 +170,90 @@ class AccountEnrichment implements EnrichmentInterface
private function appendCollectedData(): void
{
$accountTypes = $this->accountTypes;
$meta = $this->meta;
$this->collection = $this->collection->map(function (Account $item) use ($accountTypes, $meta) {
$currencies = $this->currencies;
$notes = $this->notes;
$openingBalances = $this->openingBalances;
$locations = $this->locations;
$this->collection = $this->collection->map(function (Account $item) use ($accountTypes, $meta, $currencies, $notes, $openingBalances, $locations) {
$item->full_account_type = $accountTypes[(int) $item->account_type_id] ?? null;
$meta = [];
$accountMeta = [
'currency' => null,
'location' => [
'latitude' => null,
'longitude' => null,
'zoom_level' => null,
],
];
if (array_key_exists((int) $item->id, $meta)) {
foreach ($meta[(int) $item->id] as $name => $value) {
$meta[$name] = $value;
$accountMeta[$name] = $value;
}
}
$item->meta = $meta;
// also add currency, if present.
if (array_key_exists('currency_id', $accountMeta)) {
$currencyId = (int) $accountMeta['currency_id'];
$accountMeta['currency'] = $currencies[$currencyId];
}
// if notes, add notes.
if (array_key_exists($item->id, $notes)) {
$accountMeta['notes'] = $notes[$item->id];
}
// if opening balance, add opening balance
if (array_key_exists($item->id, $openingBalances)) {
$accountMeta['opening_balance_date'] = $openingBalances[$item->id]['date'];
$accountMeta['opening_balance_amount'] = $openingBalances[$item->id]['amount'];
}
// if location, add location:
if (array_key_exists($item->id, $locations)) {
$accountMeta['location'] = $locations[$item->id];
}
$item->meta = $accountMeta;
return $item;
});
}
private function collectOpeningBalances(): void
{
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setAccounts($this->collection)
->withAccountInformation()
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value]);
$journals = $collector->getExtractedJournals();
foreach ($journals as $journal) {
$this->openingBalances[(int) $journal['source_account_id']]
= [
'amount' => Steam::negative($journal['amount']),
'date' => $journal['date'],
];
$this->openingBalances[(int) $journal['destination_account_id']]
= [
'amount' => Steam::positive($journal['amount']),
'date' => $journal['date'],
];
}
}
private function collectLocations(): void {
$locations = Location::query()->whereIn('locatable_id', $this->accountIds)
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray();
foreach ($locations as $location) {
$this->locations[(int) $location['locatable_id']]
= [
'latitude' => (float) $location['latitude'],
'longitude' => (float) $location['longitude'],
'zoom_level' => (int) $location['zoom_level'],
];
}
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
}
/**
* TODO this method refers to a single-use method inside Steam that could be moved here.
*/
@@ -386,5 +467,17 @@ class AccountEnrichment implements EnrichmentInterface
$this->native = $native;
}
private function collectNotes(): void
{
$notes = Note::query()->whereIn('noteable_id', $this->accountIds)
->whereNotNull('notes.text')
->where('notes.text', '!=', '')
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
foreach ($notes as $note) {
$this->notes[(int) $note['noteable_id']] = (string) $note['text'];
}
Log::debug(sprintf('Enrich with %d note(s)', count($this->notes)));
}
}

View File

@@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Support\JsonApi\Enrichments;
use FireflyIII\Models\UserGroup;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
@@ -32,4 +34,11 @@ interface EnrichmentInterface
public function enrich(Collection $collection): Collection;
public function enrichSingle(Model|array $model): Model|array;
public function setUserGroup(UserGroup $userGroup): void;
public function setUser(User $user): void;
}

View File

@@ -29,6 +29,7 @@ use FireflyIII\Models\Attachment;
use FireflyIII\Models\Location;
use FireflyIII\Models\Note;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionJournalMeta;
use FireflyIII\Models\UserGroup;
@@ -80,7 +81,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface
return $this->collection;
}
#[\Override] public function enrichSingle(Model|array $model): Model|array
#[\Override] public function enrichSingle(Model|array $model): TransactionGroup|array
{
Log::debug(__METHOD__);
if(is_array($model)) {