diff --git a/app/Generator/Report/Audit/MonthReportGenerator.php b/app/Generator/Report/Audit/MonthReportGenerator.php index a0aea0c9df..b920ab172e 100644 --- a/app/Generator/Report/Audit/MonthReportGenerator.php +++ b/app/Generator/Report/Audit/MonthReportGenerator.php @@ -137,9 +137,12 @@ class MonthReportGenerator implements ReportGeneratorInterface ; $journals = $collector->getExtractedJournals(); $journals = array_reverse($journals, true); - // this call is correct. - Log::debug(sprintf('getAuditReport: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); - $dayBeforeBalance = Steam::finalAccountBalance($account, $date); + + Log::debug(sprintf('getAuditReport: Call accountsBalancesOptimized with date/time "%s"', $date->toIso8601String())); + // 2025-10-08 replace with accountsBalancesOptimized. + // $dayBeforeBalance = Steam::finalAccountBalance($account, $date); + $dayBeforeBalance = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id]; + $startBalance = $dayBeforeBalance['balance']; $primaryCurrency = app('amount')->getPrimaryCurrencyByUserGroup($account->user->userGroup); $currency = $accountRepository->getAccountCurrency($account) ?? $primaryCurrency; @@ -176,12 +179,14 @@ class MonthReportGenerator implements ReportGeneratorInterface // call is correct. Log::debug(sprintf('getAuditReport end: Call finalAccountBalance with date/time "%s"', $this->end->toIso8601String())); + // 2025-10-08 replace with accountsBalancesOptimized: return [ 'journals' => $journals, 'currency' => $currency, 'exists' => 0 !== count($journals), 'end' => $this->end->isoFormat((string) trans('config.month_and_day_moment_js', [], $locale)), - 'endBalance' => Steam::finalAccountBalance($account, $this->end)['balance'], + // 'endBalance' => Steam::finalAccountBalance($account, $this->end)['balance'], + 'endBalance' => Steam::accountsBalancesOptimized(new Collection()->push($account), $this->end)[$account->id]['balance'], 'dayBefore' => $date->isoFormat((string) trans('config.month_and_day_moment_js', [], $locale)), 'dayBeforeBalance' => $dayBeforeBalance, ]; diff --git a/app/Helpers/Collector/Extensions/AccountCollection.php b/app/Helpers/Collector/Extensions/AccountCollection.php index d56ee1de4b..837c353b41 100644 --- a/app/Helpers/Collector/Extensions/AccountCollection.php +++ b/app/Helpers/Collector/Extensions/AccountCollection.php @@ -62,12 +62,13 @@ trait AccountCollection if (null === $account) { continue; } + + // 2025-10-08 replace with accountsBalancesOptimized // the balance must be found BEFORE the transaction date. - // so sub one second. This is not perfect, but works well enough. - $date = clone $transaction['date']; - $date->subSecond(); - Log::debug(sprintf('accountBalanceIs: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); - $balance = Steam::finalAccountBalance($account, $date); + // so inclusive = false + Log::debug(sprintf('accountBalanceIs: Call accountsBalancesOptimized with date/time "%s"', $transaction['date']->toIso8601String())); + $balance = Steam::accountsBalancesOptimized(new Collection()->push($account), $transaction['date'], convertToPrimary: null, inclusive: false)[$account->id]; + // $balance = Steam::finalAccountBalance($account, $date); $result = bccomp((string) $balance['balance'], $value); Log::debug(sprintf('"%s" vs "%s" is %d', $balance['balance'], $value, $result)); diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index cee8c1c158..33da0dac0e 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -39,6 +39,7 @@ use FireflyIII\User; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; use Illuminate\Routing\Redirector; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; use Illuminate\View\View; @@ -113,13 +114,20 @@ class ReconcileController extends Controller $start->startOfDay(); $end->endOfDay(); - $startDate = clone $start; - $startDate->subDay()->endOfDay(); // this is correct, subday endofday ends at 23:59:59 +// $startDate = clone $start; +// $startDate->subDay()->endOfDay(); // this is correct, subday endofday ends at 23:59:59 // both are validated and are correct. - Log::debug(sprintf('reconcile: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String())); - Log::debug(sprintf('reconcile2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); - $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); - $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); +// Log::debug(sprintf('reconcile: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String())); +// Log::debug(sprintf('reconcile2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); +// $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); +// $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); + + // 2025-10-08 replace with accountsBalancesOptimized + // no longer need to do subday->endofday on $start, set inclusive = false for the same effect. + $startBalance = Steam::bcround(Steam::accountsBalancesOptimized(new Collection()->push($account), $start, convertToPrimary: null, inclusive: false)[$account->id]['balance'], $currency->decimal_places); + $endBalance = Steam::bcround(Steam::accountsBalancesOptimized(new Collection()->push($account), $end)[$account->id]['balance'], $currency->decimal_places); + + $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); $subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]); diff --git a/app/Http/Controllers/Account/ShowController.php b/app/Http/Controllers/Account/ShowController.php index 9b1a6922f6..bee687a89c 100644 --- a/app/Http/Controllers/Account/ShowController.php +++ b/app/Http/Controllers/Account/ShowController.php @@ -169,8 +169,9 @@ class ShowController extends Controller $now = $end; } - Log::debug(sprintf('show: Call finalAccountBalance with date/time "%s"', $now->toIso8601String())); - $balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $now), $account, $this->convertToPrimary, $accountCurrency); + // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized. + $balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $now)[$account->id]; + // $balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $now), $account, $this->convertToPrimary, $accountCurrency); return view( 'accounts.show', @@ -237,8 +238,11 @@ class ShowController extends Controller $chartUrl = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); $showAll = true; // correct - Log::debug(sprintf('showAll: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); - $balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $end), $account, $this->convertToPrimary, $accountCurrency); + Log::debug(sprintf('showAll: Call accountsBalancesOptimized with date/time "%s"', $end->toIso8601String())); + + // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized. + // $balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $end), $account, $this->convertToPrimary, $accountCurrency); + $balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $end)[$account->id]; return view( 'accounts.show', diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index 527f6daefb..81309854b7 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -522,9 +522,9 @@ class AccountController extends Controller $range = Steam::filterAccountBalances($range, $account, $this->convertToPrimary, $accountCurrency); Log::debug('Get and filter balance for entire range end'); // temp, get end balance. - Log::debug(sprintf('period: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); - Steam::finalAccountBalance($account, $end); - Log::debug('END temp get end balance done'); +// Log::debug(sprintf('period: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); +// Steam::finalAccountBalance($account, $end); +// Log::debug('END temp get end balance done'); $previous = array_values($range)[0]; $accountCurrency ??= $this->primaryCurrency; // do this AFTER getting the balances. diff --git a/app/Http/Controllers/Json/ReconcileController.php b/app/Http/Controllers/Json/ReconcileController.php index 3d88bb0a88..b2d33c7fe9 100644 --- a/app/Http/Controllers/Json/ReconcileController.php +++ b/app/Http/Controllers/Json/ReconcileController.php @@ -197,10 +197,16 @@ class ReconcileController extends Controller $currency = $this->accountRepos->getAccountCurrency($account) ?? $this->primaryCurrency; // correct - Log::debug(sprintf('transactions: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String())); - Log::debug(sprintf('transactions2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); - $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); - $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); + Log::debug(sprintf('transactions: Call accountsBalancesOptimized with date/time "%s"', $startDate->toIso8601String())); + Log::debug(sprintf('transactions2: Call accountsBalancesOptimized with date/time "%s"', $end->toIso8601String())); + + // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized +// $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); +// $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); + + $startBalance = Steam::accountsBalancesOptimized(new Collection()->push($account), $startDate)[$account->id]; + $endBalance = Steam::accountsBalancesOptimized(new Collection()->push($account), $end)[$account->id]; + // get the transactions $selectionStart = clone $start; diff --git a/app/Http/Controllers/Transaction/ConvertController.php b/app/Http/Controllers/Transaction/ConvertController.php index bb5aa6f7d6..655aeeb594 100644 --- a/app/Http/Controllers/Transaction/ConvertController.php +++ b/app/Http/Controllers/Transaction/ConvertController.php @@ -37,6 +37,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Services\Internal\Update\JournalUpdateService; +use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Http\Controllers\ModelInformation; use FireflyIII\Transformers\TransactionGroupTransformer; @@ -45,6 +46,7 @@ use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Routing\Redirector; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; use Illuminate\View\View; @@ -228,11 +230,13 @@ class ConvertController extends Controller foreach ($accountList as $account) { $date = today()->endOfDay(); Log::debug(sprintf('getLiabilities: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); - $balance = Steam::finalAccountBalance($account, $date)['balance']; + // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized. + // $balance = Steam::finalAccountBalance($account, $date)['balance']; + $balance = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id]['balance'] ?? '0'; $currency = $this->accountRepository->getAccountCurrency($account) ?? $this->primaryCurrency; - $role = 'l_'.$account->accountType->type; - $key = (string) trans('firefly.opt_group_'.$role); - $grouped[$key][$account->id] = $account->name.' ('.app('amount')->formatAnything($currency, $balance, false).')'; + $role = sprintf('l_%s',$account->accountType->type); + $key = (string) trans(sprintf('firefly.opt_group_%s',$role)); + $grouped[$key][$account->id] = sprintf('%s (%s)', $account->name, Amount::formatAnything($currency, $balance, false)); } return $grouped; @@ -252,15 +256,18 @@ class ConvertController extends Controller foreach ($accountList as $account) { $date = today()->endOfDay(); Log::debug(sprintf('getAssetAccounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); - $balance = Steam::finalAccountBalance($account, $date)['balance']; + // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized. + // $balance = Steam::finalAccountBalance($account, $date)['balance']; + $balance = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id]['balance'] ?? '0'; + $currency = $this->accountRepository->getAccountCurrency($account) ?? $this->primaryCurrency; $role = (string) $this->accountRepository->getMetaValue($account, 'account_role'); if ('' === $role) { $role = 'no_account_type'; } - $key = (string) trans('firefly.opt_group_'.$role); - $grouped[$key][$account->id] = $account->name.' ('.app('amount')->formatAnything($currency, $balance, false).')'; + $key = (string) trans(sprintf('firefly.opt_group_%s',$role)); + $grouped[$key][$account->id] = sprintf('%s (%s)', $account->name, Amount::formatAnything($currency, $balance, false)); } return $grouped; diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index 056825e7d8..5ee5617130 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -375,7 +375,9 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte { Log::debug(sprintf('leftOnAccount("%s","%s","%s")', $piggyBank->name, $account->name, $date->format('Y-m-d H:i:s'))); Log::debug(sprintf('leftOnAccount: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); - $balance = Steam::finalAccountBalance($account, $date)['balance']; + // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized. + $balance = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id]; + //$balance = Steam::finalAccountBalance($account, $date)['balance']; Log::debug(sprintf('Balance is: %s', $balance)); diff --git a/app/Support/Steam.php b/app/Support/Steam.php index df270a2a3c..4da915a0ee 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -122,6 +122,9 @@ class Steam return $result; } + /** + * Calls accountsBalancesOptimized for the given accounts and makes sure that inclusive is set to false, so it properly gets the balance of a range. + */ public function accountsBalancesInRange(Carbon $start, Carbon $end, Collection $accounts, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array { return [ @@ -281,6 +284,7 @@ class Steam } /** + * @deprecated * 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". * diff --git a/app/Support/Twig/General.php b/app/Support/Twig/General.php index 485dfe1bd9..9208875ed2 100644 --- a/app/Support/Twig/General.php +++ b/app/Support/Twig/General.php @@ -30,6 +30,7 @@ use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Search\OperatorQuerySearch; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Route; use League\CommonMark\GithubFlavoredMarkdownConverter; @@ -155,9 +156,12 @@ class General extends AbstractExtension } /** @var Carbon $date */ - $date = session('end', today(config('app.timezone'))->endOfMonth()); + $date = now(); Log::debug(sprintf('twig balance: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); - $info = Steam::finalAccountBalance($account, $date); + + // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized. + $info = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id]; + // $info = Steam::finalAccountBalance($account, $date); $currency = Steam::getAccountCurrency($account); $primary = Amount::getPrimaryCurrency(); $convertToPrimary = Amount::convertToPrimary();