mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-11 17:39:41 +00:00
Optimize currency search.
This commit is contained in:
@@ -29,11 +29,11 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Singleton\PreferencesSingleton;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use NumberFormatter;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
|
||||
/**
|
||||
* Class Amount.
|
||||
@@ -59,15 +59,15 @@ class Amount
|
||||
*/
|
||||
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string
|
||||
{
|
||||
$locale = Steam::getLocale();
|
||||
$rounded = Steam::bcround($amount, $decimalPlaces);
|
||||
$locale = Steam::getLocale();
|
||||
$rounded = Steam::bcround($amount, $decimalPlaces);
|
||||
$coloured ??= true;
|
||||
|
||||
$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
||||
$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
||||
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $symbol);
|
||||
$fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
|
||||
$fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
|
||||
$result = (string)$fmt->format((float)$rounded); // intentional float
|
||||
$result = (string)$fmt->format((float)$rounded); // intentional float
|
||||
|
||||
if (true === $coloured) {
|
||||
if (1 === bccomp($rounded, '0')) {
|
||||
@@ -85,7 +85,7 @@ class Amount
|
||||
|
||||
public function formatByCurrencyId(int $currencyId, string $amount, ?bool $coloured = null): string
|
||||
{
|
||||
$format = TransactionCurrency::find($currencyId);
|
||||
$format = $this->getTransactionCurrencyById($currencyId);
|
||||
|
||||
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
|
||||
}
|
||||
@@ -115,6 +115,40 @@ class Amount
|
||||
return (string)$amount;
|
||||
}
|
||||
|
||||
public function getTransactionCurrencyById(int $currencyId): TransactionCurrency
|
||||
{
|
||||
$instance = PreferencesSingleton::getInstance();
|
||||
$key = sprintf('transaction_currency_%d', $currencyId);
|
||||
/** @var TransactionCurrency|null $pref */
|
||||
$pref = $instance->getPreference($key);
|
||||
if (null !== $pref) {
|
||||
return $pref;
|
||||
}
|
||||
$currency = TransactionCurrency::find($currencyId);
|
||||
if (null === $currency) {
|
||||
throw new FireflyException(sprintf('Could not find a transaction currency with ID #%d', $currencyId));
|
||||
}
|
||||
$instance->setPreference($key, $currency);
|
||||
return $currency;
|
||||
}
|
||||
|
||||
public function getTransactionCurrencyByCode(string $code): TransactionCurrency
|
||||
{
|
||||
$instance = PreferencesSingleton::getInstance();
|
||||
$key = sprintf('transaction_currency_%s', $code);
|
||||
/** @var TransactionCurrency|null $pref */
|
||||
$pref = $instance->getPreference($key);
|
||||
if (null !== $pref) {
|
||||
return $pref;
|
||||
}
|
||||
$currency = TransactionCurrency::whereCode($code)->first();
|
||||
if (null === $currency) {
|
||||
throw new FireflyException(sprintf('Could not find a transaction currency with code "%s"', $code));
|
||||
}
|
||||
$instance->setPreference($key, $currency);
|
||||
return $currency;
|
||||
}
|
||||
|
||||
public function convertToPrimary(?User $user = null): bool
|
||||
{
|
||||
$instance = PreferencesSingleton::getInstance();
|
||||
@@ -129,8 +163,8 @@ class Amount
|
||||
|
||||
return $pref;
|
||||
}
|
||||
$key = sprintf('convert_to_primary_%d', $user->id);
|
||||
$pref = $instance->getPreference($key);
|
||||
$key = sprintf('convert_to_primary_%d', $user->id);
|
||||
$pref = $instance->getPreference($key);
|
||||
if (null === $pref) {
|
||||
$res = true === Preferences::getForUser($user, 'convert_to_primary', false)->data && true === config('cer.enabled');
|
||||
$instance->setPreference($key, $res);
|
||||
@@ -156,7 +190,7 @@ class Amount
|
||||
|
||||
public function getPrimaryCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
||||
{
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty('getPrimaryCurrencyByGroup');
|
||||
$cache->addProperty($userGroup->id);
|
||||
if ($cache->has()) {
|
||||
@@ -186,16 +220,16 @@ class Amount
|
||||
*/
|
||||
public function getAmountFromJournalObject(TransactionJournal $journal): string
|
||||
{
|
||||
$convertToPrimary = $this->convertToPrimary();
|
||||
$currency = $this->getPrimaryCurrency();
|
||||
$field = $convertToPrimary && $currency->id !== $journal->transaction_currency_id ? 'pc_amount' : 'amount';
|
||||
$convertToPrimary = $this->convertToPrimary();
|
||||
$currency = $this->getPrimaryCurrency();
|
||||
$field = $convertToPrimary && $currency->id !== $journal->transaction_currency_id ? 'pc_amount' : 'amount';
|
||||
|
||||
/** @var null|Transaction $sourceTransaction */
|
||||
$sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
if (null === $sourceTransaction) {
|
||||
return '0';
|
||||
}
|
||||
$amount = $sourceTransaction->{$field} ?? '0';
|
||||
$amount = $sourceTransaction->{$field} ?? '0';
|
||||
if ((int)$sourceTransaction->foreign_currency_id === $currency->id) {
|
||||
// use foreign amount instead!
|
||||
$amount = (string)$sourceTransaction->foreign_amount; // hard coded to be foreign amount.
|
||||
@@ -243,20 +277,20 @@ class Amount
|
||||
private function getLocaleInfo(): array
|
||||
{
|
||||
// get config from preference, not from translation:
|
||||
$locale = Steam::getLocale();
|
||||
$array = Steam::getLocaleArray($locale);
|
||||
$locale = Steam::getLocale();
|
||||
$array = Steam::getLocaleArray($locale);
|
||||
|
||||
setlocale(LC_MONETARY, $array);
|
||||
$info = localeconv();
|
||||
$info = localeconv();
|
||||
|
||||
// correct variables
|
||||
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');
|
||||
$info['p_cs_precedes'] = $this->getLocaleField($info, 'p_cs_precedes');
|
||||
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');
|
||||
$info['p_cs_precedes'] = $this->getLocaleField($info, 'p_cs_precedes');
|
||||
|
||||
$info['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space');
|
||||
$info['p_sep_by_space'] = $this->getLocaleField($info, 'p_sep_by_space');
|
||||
$info['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space');
|
||||
$info['p_sep_by_space'] = $this->getLocaleField($info, 'p_sep_by_space');
|
||||
|
||||
$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
||||
$fmt = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
||||
|
||||
$info['mon_decimal_point'] = $fmt->getSymbol(NumberFormatter::MONETARY_SEPARATOR_SYMBOL);
|
||||
$info['mon_thousands_sep'] = $fmt->getSymbol(NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL);
|
||||
@@ -288,11 +322,11 @@ class Amount
|
||||
|
||||
// there are five possible positions for the "+" or "-" sign (if it is even used)
|
||||
// pos_a and pos_e could be the ( and ) symbol.
|
||||
$posA = ''; // before everything
|
||||
$posB = ''; // before currency symbol
|
||||
$posC = ''; // after currency symbol
|
||||
$posD = ''; // before amount
|
||||
$posE = ''; // after everything
|
||||
$posA = ''; // before everything
|
||||
$posB = ''; // before currency symbol
|
||||
$posC = ''; // after currency symbol
|
||||
$posD = ''; // before amount
|
||||
$posE = ''; // after everything
|
||||
|
||||
// format would be (currency before amount)
|
||||
// AB%sC_D%vE
|
||||
@@ -334,9 +368,9 @@ class Amount
|
||||
}
|
||||
|
||||
if ($csPrecedes) {
|
||||
return $posA.$posB.'%s'.$posC.$space.$posD.'%v'.$posE;
|
||||
return $posA . $posB . '%s' . $posC . $space . $posD . '%v' . $posE;
|
||||
}
|
||||
|
||||
return $posA.$posD.'%v'.$space.$posB.'%s'.$posC.$posE;
|
||||
return $posA . $posD . '%v' . $space . $posB . '%s' . $posC . $posE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace FireflyIII\Support;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -61,7 +61,7 @@ class Balance
|
||||
foreach ($result as $entry) {
|
||||
$accountId = (int) $entry->account_id;
|
||||
$currencyId = (int) $entry->transaction_currency_id;
|
||||
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
|
||||
$currencies[$currencyId] ??= Amount::getTransactionCurrencyById($currencyId);
|
||||
$return[$accountId] ??= [];
|
||||
if (array_key_exists($currencyId, $return[$accountId])) {
|
||||
continue;
|
||||
|
||||
@@ -23,7 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\Binder;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Routing\Route;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
@@ -38,10 +40,12 @@ class CurrencyCode implements BinderInterface
|
||||
public static function routeBinder(string $value, Route $route): TransactionCurrency
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$currency = TransactionCurrency::where('code', trim($value))->first();
|
||||
if (null !== $currency) {
|
||||
return $currency;
|
||||
try {
|
||||
$currency = Amount::getTransactionCurrencyByCode(trim($value));
|
||||
} catch(FireflyException) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
return $currency;
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
|
||||
@@ -28,6 +28,7 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Navigation;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -184,7 +185,7 @@ class AccountBalanceGrouped
|
||||
if (array_key_exists($currencyId, $this->currencies)) {
|
||||
return $this->currencies[$currencyId];
|
||||
}
|
||||
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
||||
$this->currencies[$currencyId] = Amount::getTransactionCurrencyById($currencyId);
|
||||
|
||||
return $this->currencies[$currencyId];
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -264,7 +265,7 @@ class ExchangeRateConverter
|
||||
if ($cache->has()) {
|
||||
return (int) $cache->get();
|
||||
}
|
||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||
$euro = Amount::getTransactionCurrencyByCode('EUR');
|
||||
++$this->queryCount;
|
||||
if (null === $euro) {
|
||||
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Support\Http\Api;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SummaryBalanceGrouped
|
||||
@@ -110,7 +111,7 @@ class SummaryBalanceGrouped
|
||||
// transaction info:
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$amount = bcmul((string) $journal['amount'], $multiplier);
|
||||
$currency = $this->currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
|
||||
$currency = $this->currencies[$currencyId] ?? Amount::getTransactionCurrencyById($currencyId);
|
||||
$this->currencies[$currencyId] = $currency;
|
||||
$pcAmount = $converter->convert($currency, $this->default, $journal['date'], $amount);
|
||||
if ((int) $journal['foreign_currency_id'] === $this->default->id) {
|
||||
|
||||
@@ -38,8 +38,8 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
trait ValidatesUserGroupTrait
|
||||
{
|
||||
protected ?UserGroup $userGroup = null;
|
||||
protected ?User $user = null;
|
||||
protected UserGroup $userGroup;
|
||||
protected User $user;
|
||||
|
||||
/**
|
||||
* An "undocumented" filter
|
||||
|
||||
@@ -142,7 +142,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
$accountId = (int)$item->account_id;
|
||||
$currencyId = (int)$item->data;
|
||||
if (!array_key_exists($currencyId, $this->currencies)) {
|
||||
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
||||
$this->currencies[$currencyId] = Amount::getTransactionCurrencyById($currencyId);
|
||||
}
|
||||
// $this->accountCurrencies[$accountId] = $this->currencies[$currencyId];
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
$accountId = (int)$item->account_id;
|
||||
$currencyId = (int)$item->data;
|
||||
if (!array_key_exists($currencyId, $this->currencies)) {
|
||||
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
||||
$this->currencies[$currencyId] = Amount::getTransactionCurrencyById($currencyId);
|
||||
}
|
||||
$this->accountCurrencies[$accountId] = $this->currencies[$currencyId];
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
if ($this->convertToPrimary && null !== $entry->foreign_currency_id && (int)$entry->foreign_currency_id !== $this->primaryCurrency->id) {
|
||||
// TODO this is very database intensive.
|
||||
/** @var TransactionCurrency $foreignCurrency */
|
||||
$foreignCurrency = TransactionCurrency::find($entry->foreign_currency_id);
|
||||
$foreignCurrency = Amount::getTransactionCurrencyById($entry->foreign_currency_id);
|
||||
$array['pc_foreign_amount'] = $converter->convert($foreignCurrency, $this->primaryCurrency, $entry->date, $entry->amount);
|
||||
}
|
||||
$result[] = $array;
|
||||
|
||||
@@ -30,6 +30,7 @@ use FireflyIII\Models\AccountBalance;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -171,7 +172,7 @@ class AccountBalanceCalculator
|
||||
*/
|
||||
foreach ($currencies as $currencyId => $balance) {
|
||||
/** @var null|TransactionCurrency $currency */
|
||||
$currency = TransactionCurrency::find($currencyId);
|
||||
$currency = Amount::getTransactionCurrencyById($currencyId);
|
||||
if (null === $currency) {
|
||||
Log::error(sprintf('Could not find currency #%d, will not save account balance.', $currencyId));
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ class Steam
|
||||
$sumOfDay = $this->floatalize($sumOfDay);
|
||||
|
||||
// find currency of this entry, does not have to exist.
|
||||
$currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id);
|
||||
$currencies[$entry->transaction_currency_id] ??= Amount::getTransactionCurrencyById($entry->transaction_currency_id);
|
||||
|
||||
// make sure this $entry has its own $entryCurrency
|
||||
/** @var TransactionCurrency $entryCurrency */
|
||||
@@ -502,7 +502,7 @@ class Steam
|
||||
return null;
|
||||
}
|
||||
|
||||
return TransactionCurrency::find((int)$result->data);
|
||||
return Amount::getTransactionCurrencyById((int)$result->data);
|
||||
}
|
||||
|
||||
private function groupAndSumTransactions(array $array, string $group, string $field): array
|
||||
@@ -524,7 +524,7 @@ class Steam
|
||||
$singleton = PreferencesSingleton::getInstance();
|
||||
foreach ($others as $key => $amount) {
|
||||
$preference = $singleton->getPreference($key);
|
||||
$currency = $preference ?? TransactionCurrency::where('code', $key)->first();
|
||||
$currency = $preference ?? Amount::getTransactionCurrencyByCode($key);
|
||||
if (null === $currency) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -162,9 +162,9 @@ class AmountFormat extends AbstractExtension
|
||||
static function (string $amount, string $code, ?bool $coloured = null): string {
|
||||
$coloured ??= true;
|
||||
|
||||
/** @var null|TransactionCurrency $currency */
|
||||
$currency = TransactionCurrency::whereCode($code)->first();
|
||||
if (null === $currency) {
|
||||
try {
|
||||
$currency = Amount::getTransactionCurrencyByCode($code);
|
||||
} catch(FireflyException) {
|
||||
Log::error(sprintf('Could not find currency with code "%s". Fallback to primary currency.', $code));
|
||||
$currency = Amount::getPrimaryCurrency();
|
||||
Log::error(sprintf('Fallback currency is "%s".', $currency->code));
|
||||
|
||||
@@ -99,7 +99,7 @@ class General extends AbstractExtension
|
||||
}
|
||||
// for multi currency accounts.
|
||||
if ($usePrimary && $key !== $primary->code) {
|
||||
$strings[] = app('amount')->formatAnything(TransactionCurrency::where('code', $key)->first(), $balance, false);
|
||||
$strings[] = app('amount')->formatAnything(Amount::getTransactionCurrencyByCode($key), $balance, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user