Add observers for amounts.

This commit is contained in:
James Cole
2024-12-20 05:20:37 +01:00
parent 577d671a0c
commit 1a1baa5cda
10 changed files with 346 additions and 36 deletions

View File

@@ -0,0 +1,39 @@
<?php
/*
* Updated.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Events\Model\Account;
use FireflyIII\Models\Account;
use Illuminate\Queue\SerializesModels;
class Updated
{
use SerializesModels;
public Account $account;
public function __construct(Account $account)
{
$this->account = $account;
}
}

View File

@@ -26,6 +26,9 @@ namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log;
/** /**
* Class AccountObserver * Class AccountObserver
@@ -53,4 +56,37 @@ class AccountObserver
$account->notes()->delete(); $account->notes()->delete();
$account->locations()->delete(); $account->locations()->delete();
} }
public function created(Account $account): void
{
Log::debug('Observe "created" of an account.');
$this->updateNativeAmount($account);
}
public function updated(Account $account): void
{
Log::debug('Observe "updated" of an account.');
$this->updateNativeAmount($account);
}
private function updateNativeAmount(Account $account): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
$repository = app(AccountRepositoryInterface::class);
$currency = $repository->getAccountCurrency($account);
if (null !== $currency && $currency->id !== $userCurrency->id && '' !== (string) $account->virtual_balance && 0 !== bccomp($account->virtual_balance, '0')) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$account->native_virtual_balance = $converter->convert($currency, $userCurrency, today(), $account->virtual_balance);
}
if ('' === (string) $account->virtual_balance || ('' !== (string) $account->virtual_balance && 0 === bccomp($account->virtual_balance, '0'))) {
$account->virtual_balance = null;
$account->native_virtual_balance = null;
}
$account->saveQuietly();
Log::debug('Account native virtual balance is updated.');
}
} }

View File

@@ -0,0 +1,58 @@
<?php
/*
* AutoBudgetObserver.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\AutoBudget;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log;
class AutoBudgetObserver
{
public function updated(AutoBudget $autoBudget): void
{
Log::debug('Observe "updated" of an auto budget.');
$this->updateNativeAmount($autoBudget);
}
public function created(AutoBudget $autoBudget): void
{
Log::debug('Observe "created" of an auto budget.');
$this->updateNativeAmount($autoBudget);
}
private function updateNativeAmount(AutoBudget $autoBudget): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($autoBudget->budget->user->userGroup);
$autoBudget->native_amount =null;
if ($autoBudget->transactionCurrency->id !== $userCurrency->id) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$autoBudget->native_amount = $converter->convert($autoBudget->transactionCurrency, $userCurrency, today(), $autoBudget->amount);
}
$autoBudget->saveQuietly();
Log::debug('Auto budget native amount is updated.');
}
}

View File

@@ -0,0 +1,59 @@
<?php
/*
* AutoBudgetObserver.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\AutoBudget;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log;
class AvailableBudgetObserver
{
public function updated(AvailableBudget $availableBudget): void
{
Log::debug('Observe "updated" of an available budget.');
$this->updateNativeAmount($availableBudget);
}
public function created(AvailableBudget $availableBudget): void
{
Log::debug('Observe "created" of an available budget.');
$this->updateNativeAmount($availableBudget);
}
private function updateNativeAmount(AvailableBudget $availableBudget): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($availableBudget->user->userGroup);
$availableBudget->native_amount = null;
if ($availableBudget->transactionCurrency->id !== $userCurrency->id) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$availableBudget->native_amount = $converter->convert($availableBudget->transactionCurrency, $userCurrency, today(), $availableBudget->amount);
}
$availableBudget->saveQuietly();
Log::debug('Available budget native amount is updated.');
}
}

View File

@@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer; namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log;
/** /**
* Class BillObserver * Class BillObserver
@@ -38,4 +40,31 @@ class BillObserver
} }
$bill->notes()->delete(); $bill->notes()->delete();
} }
public function updated(Bill $bill): void
{
Log::debug('Observe "updated" of a bill.');
$this->updateNativeAmount($bill);
}
public function created(Bill $bill): void
{
Log::debug('Observe "created" of a bill.');
$this->updateNativeAmount($bill);
}
private function updateNativeAmount(Bill $bill): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($bill->user->userGroup);
$bill->native_amount_min = null;
$bill->native_amount_max = null;
if ($bill->transactionCurrency->id !== $userCurrency->id) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$bill->native_amount_min = $converter->convert($bill->transactionCurrency, $userCurrency, today(), $bill->amount_min);
$bill->native_amount_max = $converter->convert($bill->transactionCurrency, $userCurrency, today(), $bill->amount_max);
}
$bill->saveQuietly();
Log::debug('Bill native amounts are updated.');
}
} }

View File

@@ -0,0 +1,56 @@
<?php
/*
* BudgetLimitObserver.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log;
class BudgetLimitObserver
{
public function updated(BudgetLimit $budgetLimit): void
{
Log::debug('Observe "updated" of a budget limit.');
$this->updateNativeAmount($budgetLimit);
}
public function created(BudgetLimit $budgetLimit): void
{
Log::debug('Observe "created" of a budget limit.');
$this->updateNativeAmount($budgetLimit);
}
private function updateNativeAmount(BudgetLimit $budgetLimit): void
{
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($budgetLimit->budget->user->userGroup);
$budgetLimit->native_amount = null;
if ($budgetLimit->transactionCurrency->id !== $userCurrency->id) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$budgetLimit->native_amount = $converter->convert($budgetLimit->transactionCurrency, $userCurrency, today(), $budgetLimit->amount);
}
$budgetLimit->saveQuietly();
Log::debug('Bill native amounts are updated.');
}
}

View File

@@ -59,6 +59,8 @@ use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Events\WarnUserAboutBill; use FireflyIII\Events\WarnUserAboutBill;
use FireflyIII\Handlers\Observer\AccountObserver; use FireflyIII\Handlers\Observer\AccountObserver;
use FireflyIII\Handlers\Observer\AttachmentObserver; use FireflyIII\Handlers\Observer\AttachmentObserver;
use FireflyIII\Handlers\Observer\AutoBudgetObserver;
use FireflyIII\Handlers\Observer\AvailableBudgetObserver;
use FireflyIII\Handlers\Observer\BillObserver; use FireflyIII\Handlers\Observer\BillObserver;
use FireflyIII\Handlers\Observer\BudgetObserver; use FireflyIII\Handlers\Observer\BudgetObserver;
use FireflyIII\Handlers\Observer\CategoryObserver; use FireflyIII\Handlers\Observer\CategoryObserver;
@@ -75,6 +77,8 @@ use FireflyIII\Handlers\Observer\WebhookMessageObserver;
use FireflyIII\Handlers\Observer\WebhookObserver; use FireflyIII\Handlers\Observer\WebhookObserver;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Attachment; use FireflyIII\Models\Attachment;
use FireflyIII\Models\AutoBudget;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
@@ -262,6 +266,8 @@ class EventServiceProvider extends ServiceProvider
Attachment::observe(new AttachmentObserver()); Attachment::observe(new AttachmentObserver());
PiggyBank::observe(new PiggyBankObserver()); PiggyBank::observe(new PiggyBankObserver());
Account::observe(new AccountObserver()); Account::observe(new AccountObserver());
AvailableBudget::observe(new AvailableBudgetObserver());
AutoBudget::observe(new AutoBudgetObserver());
Bill::observe(new BillObserver()); Bill::observe(new BillObserver());
Budget::observe(new BudgetObserver()); Budget::observe(new BudgetObserver());
Category::observe(new CategoryObserver()); Category::observe(new CategoryObserver());

View File

@@ -33,7 +33,7 @@ use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups; use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
/** /**
@@ -59,9 +59,19 @@ trait ModifiesPiggyBanks
public function removeAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool public function removeAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool
{ {
$currentAmount = $this->getCurrentAmount($piggyBank, $account); $currentAmount = $this->getCurrentAmount($piggyBank, $account);
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot; $pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
$pivot->current_amount = bcsub($currentAmount, $amount); $pivot->current_amount = bcsub($currentAmount, $amount);
$pivot->native_current_amount = null;
// also update native_current_amount.
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
if ($userCurrency->id !== $piggyBank->transaction_currency_id) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $pivot->current_amount);
}
$pivot->save(); $pivot->save();
Log::debug('ChangedAmount: removeAmount [a]: Trigger change for negative amount.'); Log::debug('ChangedAmount: removeAmount [a]: Trigger change for negative amount.');
@@ -93,6 +103,16 @@ trait ModifiesPiggyBanks
$currentAmount = $this->getCurrentAmount($piggyBank, $account); $currentAmount = $this->getCurrentAmount($piggyBank, $account);
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot; $pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
$pivot->current_amount = bcadd($currentAmount, $amount); $pivot->current_amount = bcadd($currentAmount, $amount);
$pivot->native_current_amount = null;
// also update native_current_amount.
$userCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
if ($userCurrency->id !== $piggyBank->transaction_currency_id) {
$converter = new ExchangeRateConverter();
$converter->setIgnoreSettings(true);
$pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $pivot->current_amount);
}
$pivot->save(); $pivot->save();
Log::debug('ChangedAmount: addAmount [b]: Trigger change for positive amount.'); Log::debug('ChangedAmount: addAmount [b]: Trigger change for positive amount.');
@@ -120,8 +140,8 @@ trait ModifiesPiggyBanks
Log::debug(sprintf('Maximum amount: %s', $maxAmount)); Log::debug(sprintf('Maximum amount: %s', $maxAmount));
} }
$compare = bccomp($amount, $maxAmount); $compare = bccomp($amount, $maxAmount);
$result = $compare <= 0; $result = $compare <= 0;
Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true))); Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true)));
@@ -155,11 +175,11 @@ trait ModifiesPiggyBanks
public function setCurrentAmount(PiggyBank $piggyBank, string $amount): PiggyBank public function setCurrentAmount(PiggyBank $piggyBank, string $amount): PiggyBank
{ {
$repetition = $this->getRepetition($piggyBank); $repetition = $this->getRepetition($piggyBank);
if (null === $repetition) { if (null === $repetition) {
return $piggyBank; return $piggyBank;
} }
$max = $piggyBank->target_amount; $max = $piggyBank->target_amount;
if (1 === bccomp($amount, $max) && 0 !== bccomp($piggyBank->target_amount, '0')) { if (1 === bccomp($amount, $max) && 0 !== bccomp($piggyBank->target_amount, '0')) {
$amount = $max; $amount = $max;
} }
@@ -202,16 +222,15 @@ trait ModifiesPiggyBanks
public function setOrder(PiggyBank $piggyBank, int $newOrder): bool public function setOrder(PiggyBank $piggyBank, int $newOrder): bool
{ {
$oldOrder = $piggyBank->order; $oldOrder = $piggyBank->order;
// Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder)); // Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
if ($newOrder > $oldOrder) { if ($newOrder > $oldOrder) {
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id') ->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id) ->where('accounts.user_id', $this->user->id)
->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder) ->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id) ->where('piggy_banks.id', '!=', $piggyBank->id)
->distinct()->decrement('piggy_banks.order') ->distinct()->decrement('piggy_banks.order');
;
$piggyBank->order = $newOrder; $piggyBank->order = $newOrder;
Log::debug(sprintf('[1] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder)); Log::debug(sprintf('[1] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
@@ -220,12 +239,11 @@ trait ModifiesPiggyBanks
return true; return true;
} }
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id') ->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
->where('accounts.user_id', $this->user->id) ->where('accounts.user_id', $this->user->id)
->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder) ->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder)
->where('piggy_banks.id', '!=', $piggyBank->id) ->where('piggy_banks.id', '!=', $piggyBank->id)
->distinct()->increment('piggy_banks.order') ->distinct()->increment('piggy_banks.order');
;
$piggyBank->order = $newOrder; $piggyBank->order = $newOrder;
Log::debug(sprintf('[2] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder)); Log::debug(sprintf('[2] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
@@ -242,7 +260,7 @@ trait ModifiesPiggyBanks
return; return;
} }
$dbNote = $piggyBank->notes()->first(); $dbNote = $piggyBank->notes()->first();
if (null === $dbNote) { if (null === $dbNote) {
$dbNote = new Note(); $dbNote = new Note();
$dbNote->noteable()->associate($piggyBank); $dbNote->noteable()->associate($piggyBank);
@@ -253,14 +271,14 @@ trait ModifiesPiggyBanks
public function update(PiggyBank $piggyBank, array $data): PiggyBank public function update(PiggyBank $piggyBank, array $data): PiggyBank
{ {
$piggyBank = $this->updateProperties($piggyBank, $data); $piggyBank = $this->updateProperties($piggyBank, $data);
if (array_key_exists('notes', $data)) { if (array_key_exists('notes', $data)) {
$this->updateNote($piggyBank, (string)$data['notes']); $this->updateNote($piggyBank, (string) $data['notes']);
} }
// update the order of the piggy bank: // update the order of the piggy bank:
$oldOrder = $piggyBank->order; $oldOrder = $piggyBank->order;
$newOrder = (int)($data['order'] ?? $oldOrder); $newOrder = (int) ($data['order'] ?? $oldOrder);
if ($oldOrder !== $newOrder) { if ($oldOrder !== $newOrder) {
$this->setOrder($piggyBank, $newOrder); $this->setOrder($piggyBank, $newOrder);
} }
@@ -289,7 +307,7 @@ trait ModifiesPiggyBanks
// update using name: // update using name:
if (array_key_exists('object_group_title', $data)) { if (array_key_exists('object_group_title', $data)) {
$objectGroupTitle = (string)$data['object_group_title']; $objectGroupTitle = (string) $data['object_group_title'];
if ('' !== $objectGroupTitle) { if ('' !== $objectGroupTitle) {
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle); $objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
if (null !== $objectGroup) { if (null !== $objectGroup) {
@@ -305,7 +323,7 @@ trait ModifiesPiggyBanks
// try also with ID: // try also with ID:
if (array_key_exists('object_group_id', $data)) { if (array_key_exists('object_group_id', $data)) {
$objectGroupId = (int)($data['object_group_id'] ?? 0); $objectGroupId = (int) ($data['object_group_id'] ?? 0);
if (0 !== $objectGroupId) { if (0 !== $objectGroupId) {
$objectGroup = $this->findObjectGroupById($objectGroupId); $objectGroup = $this->findObjectGroupById($objectGroupId);
if (null !== $objectGroup) { if (null !== $objectGroup) {

View File

@@ -43,10 +43,16 @@ class ExchangeRateConverter
private bool $noPreparedRates = false; private bool $noPreparedRates = false;
private array $prepared = []; private array $prepared = [];
private int $queryCount = 0; private int $queryCount = 0;
private bool $ignoreSettings = false;
public function setIgnoreSettings(bool $ignoreSettings): void
{
$this->ignoreSettings = $ignoreSettings;
}
public function enabled(): bool public function enabled(): bool
{ {
return false !== config('cer.enabled'); return false !== config('cer.enabled') || true === $this->ignoreSettings;
} }
/** /**

View File

@@ -6,15 +6,18 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration { return new class extends Migration {
private array $tables = [ private array $tables = [
'accounts' => ['native_virtual_balance'], 'accounts' => ['native_virtual_balance'], // works.
'account_piggy_bank' => ['native_current_amount'], 'account_piggy_bank' => ['native_current_amount'], // works
'auto_budgets' => ['native_amount'], 'auto_budgets' => ['native_amount'], // works
'available_budgets' => ['native_amount'], 'available_budgets' => ['native_amount'], // works
'bills' => ['native_amount_min', 'native_amount_max'], 'bills' => ['native_amount_min', 'native_amount_max'], // works
'budget_limits' => ['native_amount'], 'budget_limits' => ['native_amount'], // works
'piggy_bank_events' => ['native_amount'], 'piggy_bank_events' => ['native_amount'],
'piggy_banks' => ['native_target_amount'], 'piggy_banks' => ['native_target_amount'],
'transactions' => ['native_amount'], 'transactions' => ['native_amount', 'native_foreign_amount'],
// TODO native currency changes, reset everything.
// button to recalculate all native amounts on selected pages?
]; ];