Clean up some code surrounding account balances.

This commit is contained in:
James Cole
2025-10-08 06:44:48 +02:00
parent d91d30c8f0
commit ec08485c2b
4 changed files with 95 additions and 157 deletions

View File

@@ -130,55 +130,4 @@ class NetWorth implements NetWorthInterface
$this->accountRepository->setUserGroup($userGroup); $this->accountRepository->setUserGroup($userGroup);
} }
#[Deprecated]
public function sumNetWorthByCurrency(Carbon $date): array
{
/**
* Collect accounts
*/
$accounts = $this->getAccounts();
$return = [];
Log::debug(sprintf('SumNetWorth: accountsBalancesOptimized("%s")', $date->format('Y-m-d H:i:s')));
$balances = Steam::accountsBalancesOptimized($accounts, $date);
foreach ($accounts as $account) {
$currency = $this->accountRepository->getAccountCurrency($account);
$balance = $balances[$account->id]['balance'] ?? '0';
// always subtract virtual balance.
$virtualBalance = $account->virtual_balance;
if ('' !== $virtualBalance) {
$balance = bcsub($balance, (string) $virtualBalance);
}
$return[$currency->id] ??= [
'id' => (string) $currency->id,
'name' => $currency->name,
'symbol' => $currency->symbol,
'code' => $currency->code,
'decimal_places' => $currency->decimal_places,
'sum' => '0',
];
$return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], (string) $balance);
}
return $return;
}
private function getAccounts(): Collection
{
$accounts = $this->accountRepository->getAccountsByType(
[AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value]
);
$filtered = new Collection();
/** @var Account $account */
foreach ($accounts as $account) {
if (1 === (int) $this->accountRepository->getMetaValue($account, 'include_net_worth')) {
$filtered->push($account);
}
}
return $filtered;
}
} }

View File

@@ -50,11 +50,4 @@ interface NetWorthInterface
public function setUserGroup(UserGroup $userGroup): void; public function setUserGroup(UserGroup $userGroup): void;
/**
* TODO move to repository
*
* Same as above but cleaner function with less dependencies.
*/
#[Deprecated]
public function sumNetWorthByCurrency(Carbon $date): array;
} }

View File

@@ -38,6 +38,7 @@ use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Controllers\DateCalculation; use FireflyIII\Support\Http\Controllers\DateCalculation;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/** /**
* Class BoxController. * Class BoxController.
@@ -165,7 +166,7 @@ class BoxController extends Controller
$allAccounts = $accountRepository->getActiveAccountsByType( $allAccounts = $accountRepository->getActiveAccountsByType(
[AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value] [AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value]
); );
app('log')->debug(sprintf('Found %d accounts.', $allAccounts->count())); Log::debug(sprintf('Found %d accounts.', $allAccounts->count()));
// filter list on preference of being included. // filter list on preference of being included.
$filtered = $allAccounts->filter( $filtered = $allAccounts->filter(
@@ -173,7 +174,7 @@ class BoxController extends Controller
$includeNetWorth = $accountRepository->getMetaValue($account, 'include_net_worth'); $includeNetWorth = $accountRepository->getMetaValue($account, 'include_net_worth');
$result = null === $includeNetWorth || '1' === $includeNetWorth; $result = null === $includeNetWorth || '1' === $includeNetWorth;
if (false === $result) { if (false === $result) {
app('log')->debug(sprintf('Will not include "%s" in net worth charts.', $account->name)); Log::debug(sprintf('Will not include "%s" in net worth charts.', $account->name));
} }
return $result; return $result;

View File

@@ -40,7 +40,6 @@ use Illuminate\Support\Str;
use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface; use Psr\Container\NotFoundExceptionInterface;
use ValueError; use ValueError;
use function Safe\parse_url; use function Safe\parse_url;
use function Safe\preg_replace; use function Safe\preg_replace;
@@ -51,7 +50,7 @@ class Steam
{ {
public function accountsBalancesOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null, bool $inclusive = true): array public function accountsBalancesOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null, bool $inclusive = true): array
{ {
Log::debug(sprintf('accountsBalancesOptimized: Called for %d account(s) with date/time "%s"', $accounts->count(), $date->toIso8601String())); Log::debug(sprintf('accountsBalancesOptimized: Called for %d account(s) with date/time "%s" (inclusive: %s)', $accounts->count(), $date->toIso8601String(), var_export($inclusive, true)));
$result = []; $result = [];
$convertToPrimary ??= Amount::convertToPrimary(); $convertToPrimary ??= Amount::convertToPrimary();
$primary ??= Amount::getPrimaryCurrency(); $primary ??= Amount::getPrimaryCurrency();
@@ -61,14 +60,12 @@ class Steam
$arrayOfSums = Transaction::whereIn('account_id', $accounts->pluck('id')->toArray()) $arrayOfSums = Transaction::whereIn('account_id', $accounts->pluck('id')->toArray())
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id') ->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
->where('transaction_journals.date', $inclusive ? '<=': '<', $date->format('Y-m-d H:i:s')) ->where('transaction_journals.date', $inclusive ? '<=' : '<', $date->format('Y-m-d H:i:s'))
->groupBy(['transactions.account_id', 'transaction_currencies.code']) ->groupBy(['transactions.account_id', 'transaction_currencies.code'])
->get(['transactions.account_id', 'transaction_currencies.code', DB::raw('SUM(transactions.amount) as sum_of_amount')])->toArray() ->get(['transactions.account_id', 'transaction_currencies.code', DB::raw('SUM(transactions.amount) as sum_of_amount')])->toArray();
;
/** @var Account $account */ /** @var Account $account */
foreach ($accounts as $account) { foreach ($accounts as $account) {
// this array is PER account, so we wait a bit before we change code here.
$return = [ $return = [
'pc_balance' => '0', 'pc_balance' => '0',
'balance' => '0', // this key is overwritten right away, but I must remember it is always created. 'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
@@ -76,7 +73,7 @@ class Steam
$currency = $currencies[$account->id]; $currency = $currencies[$account->id];
// second array // second array
$accountSum = array_filter($arrayOfSums, fn ($entry) => $entry['account_id'] === $account->id); $accountSum = array_filter($arrayOfSums, fn($entry) => $entry['account_id'] === $account->id);
if (0 === count($accountSum)) { if (0 === count($accountSum)) {
$result[$account->id] = $return; $result[$account->id] = $return;
@@ -152,10 +149,10 @@ class Steam
// Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision)); // Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
if (str_contains($number, '.')) { if (str_contains($number, '.')) {
if ('-' !== $number[0]) { if ('-' !== $number[0]) {
return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision); return bcadd($number, '0.' . str_repeat('0', $precision) . '5', $precision);
} }
return bcsub($number, '0.'.str_repeat('0', $precision).'5', $precision); return bcsub($number, '0.' . str_repeat('0', $precision) . '5', $precision);
} }
return $number; return $number;
@@ -284,7 +281,8 @@ class Steam
} }
/** /**
* Returns smaller than or equal to, so be careful with END OF DAY. * By default this method returns "smaller than or equal to", so be careful with END OF DAY.
* If you need end of day balance, use "inclusive = false".
* *
* Returns the balance of an account at exact moment given. Array with at least one value. * Returns the balance of an account at exact moment given. Array with at least one value.
* Always returns: * Always returns:
@@ -296,18 +294,17 @@ class Steam
* --> "pc_balance": balance in the user's primary currency, with all amounts converted to the primary currency. * --> "pc_balance": balance in the user's primary currency, with all amounts converted to the primary currency.
* "EUR": balance in EUR (or whatever currencies the account has balance in) * "EUR": balance in EUR (or whatever currencies the account has balance in)
*/ */
public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null, bool $inclusive = true): array
{ {
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty($date); $cache->addProperty($date);
if ($cache->has()) { if ($cache->has()) {
Log::debug(sprintf('CACHED finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s'))); Log::debug(sprintf('CACHED finalAccountBalance(#%d, %s, inclusive:%s)', $account->id, $date->format('Y-m-d H:i:s'), var_export($inclusive, true)));
return $cache->get();
// return $cache->get();
} }
// Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s'))); Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
if (null === $convertToPrimary) { if (null === $convertToPrimary) {
$convertToPrimary = Amount::convertToPrimary($account->user); $convertToPrimary = Amount::convertToPrimary($account->user);
} }
@@ -333,9 +330,8 @@ class Steam
$array = $account->transactions() $array = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id') ->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) ->where('transaction_journals.date', $inclusive ? '<=': '<', $date->format('Y-m-d H:i:s'))
->get(['transaction_currencies.code', 'transactions.amount'])->toArray() ->get(['transaction_currencies.code', 'transactions.amount'])->toArray();
;
$others = $this->groupAndSumTransactions($array, 'code', 'amount'); $others = $this->groupAndSumTransactions($array, 'code', 'amount');
// Log::debug('All balances are (joined)', $others); // Log::debug('All balances are (joined)', $others);
// if there is no request to convert, take this as "balance" and "pc_balance". // if there is no request to convert, take this as "balance" and "pc_balance".
@@ -442,8 +438,7 @@ class Steam
'transactions.transaction_currency_id', 'transactions.transaction_currency_id',
DB::raw('SUM(transactions.amount) AS sum_of_day'), DB::raw('SUM(transactions.amount) AS sum_of_day'),
] ]
) );
;
$currentBalance = $startBalance; $currentBalance = $startBalance;
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
@@ -550,7 +545,7 @@ class Steam
try { try {
$hostName = gethostbyaddr($ipAddress); $hostName = gethostbyaddr($ipAddress);
} catch (Exception $e) { } catch (Exception $e) {
app('log')->error($e->getMessage()); Log::error($e->getMessage());
$hostName = $ipAddress; $hostName = $ipAddress;
} }
@@ -765,7 +760,7 @@ class Steam
$current = $converter->convert($currency, $primary, $date, $amount); $current = $converter->convert($currency, $primary, $date, $amount);
Log::debug(sprintf('Convert %s %s to %s %s', $currency->code, $amount, $primary->code, $current)); Log::debug(sprintf('Convert %s %s to %s %s', $currency->code, $amount, $primary->code, $current));
} }
$total = bcadd((string) $current, $total); $total = bcadd((string)$current, $total);
} }
return $total; return $total;