From 08a26b976ef8d94b800f3d3b2f8a0f37c8fd6c35 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 28 Sep 2024 18:35:20 +0200 Subject: [PATCH] Auto commit for release 'develop' on 2024-09-28 --- .../Models/AccountBalanceCalculator.php | 87 ++++++++++--------- app/Support/Twig/General.php | 26 +++--- changelog.md | 4 +- config/firefly.php | 40 ++++----- 4 files changed, 81 insertions(+), 76 deletions(-) diff --git a/app/Support/Models/AccountBalanceCalculator.php b/app/Support/Models/AccountBalanceCalculator.php index 2b1e8883d2..76d4ab9ac6 100644 --- a/app/Support/Models/AccountBalanceCalculator.php +++ b/app/Support/Models/AccountBalanceCalculator.php @@ -68,7 +68,7 @@ class AccountBalanceCalculator public static function recalculateForJournal(TransactionJournal $transactionJournal): void { Log::debug(__METHOD__); - $object = new self(); + $object = new self(); // recalculate the involved accounts: $accounts = new Collection(); @@ -82,34 +82,37 @@ class AccountBalanceCalculator { if (null === $notBefore) { Log::debug('getLatestBalance: no notBefore date, returning 0'); + return '0'; } Log::debug(sprintf('getLatestBalance: notBefore date is "%s", calculating', $notBefore->format('Y-m-d'))); - $query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->whereNull('transactions.deleted_at') - ->where('transaction_journals.transaction_currency_id', $currencyId) - ->whereNull('transaction_journals.deleted_at') + $query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->whereNull('transactions.deleted_at') + ->where('transaction_journals.transaction_currency_id', $currencyId) + ->whereNull('transaction_journals.deleted_at') // this order is the same as GroupCollector - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.order', 'ASC') - ->orderBy('transaction_journals.id', 'DESC') - ->orderBy('transaction_journals.description', 'DESC') - ->orderBy('transactions.amount', 'DESC') - ->where('transactions.account_id', $accountId); + ->orderBy('transaction_journals.date', 'DESC') + ->orderBy('transaction_journals.order', 'ASC') + ->orderBy('transaction_journals.id', 'DESC') + ->orderBy('transaction_journals.description', 'DESC') + ->orderBy('transactions.amount', 'DESC') + ->where('transactions.account_id', $accountId) + ; $notBefore->startOfDay(); $query->where('transaction_journals.date', '<', $notBefore); $first = $query->first(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount', 'transactions.balance_after']); $balance = $first->balance_after ?? '0'; Log::debug(sprintf('getLatestBalance: found balance: %s in transaction #%d', $balance, $first->id ?? 0)); + return $balance; } private function getAccountBalanceByAccount(int $account, int $currency): AccountBalance { - $query = AccountBalance::where('title', 'balance')->where('account_id', $account)->where('transaction_currency_id', $currency); + $query = AccountBalance::where('title', 'balance')->where('account_id', $account)->where('transaction_currency_id', $currency); - $entry = $query->first(); + $entry = $query->first(); if (null !== $entry) { // Log::debug(sprintf('Found account balance "balance" for account #%d and currency #%d: %s', $account, $currency, $entry->balance)); @@ -131,6 +134,7 @@ class AccountBalanceCalculator Log::debug('start of optimizedCalculation'); if (false === config('firefly.feature_flags.running_balance_column')) { Log::debug('optimizedCalculation is disabled, return.'); + return; } @@ -141,14 +145,15 @@ class AccountBalanceCalculator $balances = []; $count = 0; $query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->whereNull('transactions.deleted_at') - ->whereNull('transaction_journals.deleted_at') + ->whereNull('transactions.deleted_at') + ->whereNull('transaction_journals.deleted_at') // this order is the same as GroupCollector, but in the exact reverse. - ->orderBy('transaction_journals.date', 'asc') - ->orderBy('transaction_journals.order', 'desc') - ->orderBy('transaction_journals.id', 'asc') - ->orderBy('transaction_journals.description', 'asc') - ->orderBy('transactions.amount', 'asc'); + ->orderBy('transaction_journals.date', 'asc') + ->orderBy('transaction_journals.order', 'desc') + ->orderBy('transaction_journals.id', 'asc') + ->orderBy('transaction_journals.description', 'asc') + ->orderBy('transactions.amount', 'asc') + ; if ($accounts->count() > 0) { $query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray()); } @@ -157,7 +162,7 @@ class AccountBalanceCalculator $query->where('transaction_journals.date', '>=', $notBefore); } - $set = $query->get(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount']); + $set = $query->get(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount']); /** @var Transaction $entry */ foreach ($set as $entry) { @@ -166,8 +171,8 @@ class AccountBalanceCalculator $balances[$entry->account_id][$entry->transaction_currency_id] ??= $this->getLatestBalance($entry->account_id, $entry->transaction_currency_id, $notBefore); // before and after are easy: - $before = $balances[$entry->account_id][$entry->transaction_currency_id]; - $after = bcadd($before, $entry->amount); + $before = $balances[$entry->account_id][$entry->transaction_currency_id]; + $after = bcadd($before, $entry->amount); if (true === $entry->balance_dirty || $accounts->count() > 0) { // update the transaction: $entry->balance_before = $before; @@ -188,9 +193,9 @@ class AccountBalanceCalculator private function getAccountBalanceByJournal(string $title, int $account, int $journal, int $currency): AccountBalance { - $query = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_journal_id', $journal)->where('transaction_currency_id', $currency); + $query = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_journal_id', $journal)->where('transaction_currency_id', $currency); - $entry = $query->first(); + $entry = $query->first(); if (null !== $entry) { return $entry; } @@ -207,7 +212,7 @@ class AccountBalanceCalculator private function recalculateLatest(?Account $account): void { - $query = Transaction::groupBy(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']); + $query = Transaction::groupBy(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']); if (null !== $account) { $query->where('transactions.account_id', $account->id); @@ -228,11 +233,11 @@ class AccountBalanceCalculator $sumForeignAmount = '' === $sumForeignAmount ? '0' : $sumForeignAmount; // at this point SQLite may return scientific notation because why not. Terrible. - $sumAmount = app('steam')->floatalize($sumAmount); - $sumForeignAmount = app('steam')->floatalize($sumForeignAmount); + $sumAmount = app('steam')->floatalize($sumAmount); + $sumForeignAmount = app('steam')->floatalize($sumForeignAmount); // first create for normal currency: - $entry = $this->getAccountBalanceByAccount($account, $transactionCurrency); + $entry = $this->getAccountBalanceByAccount($account, $transactionCurrency); try { $entry->balance = bcadd((string) $entry->balance, $sumAmount); @@ -287,7 +292,7 @@ class AccountBalanceCalculator */ private function recalculateJournals(?Account $account, ?TransactionJournal $transactionJournal): void { - $query = Transaction::groupBy(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']); + $query = Transaction::groupBy(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']); $query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'); $query->orderBy('transaction_journals.date', 'asc'); $amounts = []; @@ -298,28 +303,28 @@ class AccountBalanceCalculator $query->where('transaction_journals.date', '>=', $transactionJournal->date); $amounts = $this->getStartAmounts($account, $transactionJournal); } - $result = $query->get(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id', \DB::raw('SUM(transactions.amount) as sum_amount'), \DB::raw('SUM(transactions.foreign_amount) as sum_foreign_amount')]); + $result = $query->get(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id', \DB::raw('SUM(transactions.amount) as sum_amount'), \DB::raw('SUM(transactions.foreign_amount) as sum_foreign_amount')]); /** @var \stdClass $row */ foreach ($result as $row) { - $account = (int) $row->account_id; - $transactionCurrency = (int) $row->transaction_currency_id; - $foreignCurrency = (int) $row->foreign_currency_id; - $sumAmount = (string) $row->sum_amount; - $sumForeignAmount = (string) $row->sum_foreign_amount; - $journalId = (int) $row->id; + $account = (int) $row->account_id; + $transactionCurrency = (int) $row->transaction_currency_id; + $foreignCurrency = (int) $row->foreign_currency_id; + $sumAmount = (string) $row->sum_amount; + $sumForeignAmount = (string) $row->sum_foreign_amount; + $journalId = (int) $row->id; // check for empty strings - $sumAmount = '' === $sumAmount ? '0' : $sumAmount; - $sumForeignAmount = '' === $sumForeignAmount ? '0' : $sumForeignAmount; + $sumAmount = '' === $sumAmount ? '0' : $sumAmount; + $sumForeignAmount = '' === $sumForeignAmount ? '0' : $sumForeignAmount; // new amounts: $amounts[$account][$transactionCurrency] = bcadd($amounts[$account][$transactionCurrency] ?? '0', $sumAmount); $amounts[$account][$foreignCurrency] = bcadd($amounts[$account][$foreignCurrency] ?? '0', $sumForeignAmount); // first create for normal currency: - $entry = self::getAccountBalanceByJournal('balance_after_journal', $account, $journalId, $transactionCurrency); - $entry->balance = $amounts[$account][$transactionCurrency]; + $entry = self::getAccountBalanceByJournal('balance_after_journal', $account, $journalId, $transactionCurrency); + $entry->balance = $amounts[$account][$transactionCurrency]; $entry->save(); // then do foreign amount, if present: diff --git a/app/Support/Twig/General.php b/app/Support/Twig/General.php index df88291480..a73fddaaec 100644 --- a/app/Support/Twig/General.php +++ b/app/Support/Twig/General.php @@ -72,16 +72,16 @@ class General extends AbstractExtension $info[] = app('steam')->balance($account, $date); } - $strings = []; + $strings = []; foreach ($info as $currencyId => $balance) { - if(0 === $currencyId) { + if (0 === $currencyId) { // not good code but OK /** @var AccountRepositoryInterface $accountRepos */ $accountRepos = app(AccountRepositoryInterface::class); $currency = $accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); - $strings[] = app('amount')->formatAnything($currency, $balance, false); + $strings[] = app('amount')->formatAnything($currency, $balance, false); } - if(0 !== $currencyId) { + if (0 !== $currencyId) { $strings[] = app('amount')->formatByCurrencyId($currencyId, $balance, false); } } @@ -102,15 +102,15 @@ class General extends AbstractExtension static function (int $size): string { // less than one GB, more than one MB if ($size < (1024 * 1024 * 2014) && $size >= (1024 * 1024)) { - return round($size / (1024 * 1024), 2) . ' MB'; + return round($size / (1024 * 1024), 2).' MB'; } // less than one MB if ($size < (1024 * 1024)) { - return round($size / 1024, 2) . ' KB'; + return round($size / 1024, 2).' KB'; } - return $size . ' bytes'; + return $size.' bytes'; } ); } @@ -132,7 +132,7 @@ class General extends AbstractExtension case 'application/pdf': return 'fa-file-pdf-o'; - // image + // image case 'image/png': case 'image/jpeg': case 'image/svg+xml': @@ -141,7 +141,7 @@ class General extends AbstractExtension case 'application/vnd.oasis.opendocument.image': return 'fa-file-image-o'; - // MS word + // MS word case 'application/msword': case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': case 'application/vnd.openxmlformats-officedocument.wordprocessingml.template': @@ -157,7 +157,7 @@ class General extends AbstractExtension case 'application/vnd.oasis.opendocument.text-master': return 'fa-file-word-o'; - // MS excel + // MS excel case 'application/vnd.ms-excel': case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': case 'application/vnd.openxmlformats-officedocument.spreadsheetml.template': @@ -168,7 +168,7 @@ class General extends AbstractExtension case 'application/vnd.oasis.opendocument.spreadsheet-template': return 'fa-file-excel-o'; - // MS powerpoint + // MS powerpoint case 'application/vnd.ms-powerpoint': case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': case 'application/vnd.openxmlformats-officedocument.presentationml.template': @@ -180,7 +180,7 @@ class General extends AbstractExtension case 'application/vnd.oasis.opendocument.presentation-template': return 'fa-file-powerpoint-o'; - // calc + // calc case 'application/vnd.sun.xml.draw': case 'application/vnd.sun.xml.draw.template': case 'application/vnd.stardivision.draw': @@ -316,7 +316,7 @@ class General extends AbstractExtension 'activeRoutePartialObjectType', static function ($context): string { [, $route, $objectType] = func_get_args(); - $activeObjectType = $context['objectType'] ?? false; + $activeObjectType = $context['objectType'] ?? false; if ($objectType === $activeObjectType && false !== stripos( diff --git a/changelog.md b/changelog.md index b60e5d2fec..4934999f3d 100644 --- a/changelog.md +++ b/changelog.md @@ -7,8 +7,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed -- #9275 -- #9278 +- [Issue 9275](https://github.com/firefly-iii/firefly-iii/issues/9275) (Long wait when editing a transaction) reported by @JC5 +- [Issue 9278](https://github.com/firefly-iii/firefly-iii/issues/9278) (Update to v6.1.20 changed Balance of Account) reported by @JeuJeus ## 6.1.20 - 2024-09-29 diff --git a/config/firefly.php b/config/firefly.php index 54c2595e48..2b77b77972 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -429,7 +429,7 @@ return [ 'transfers' => 'fa-exchange', ], - 'bindables' => [ + 'bindables' => [ // models 'account' => Account::class, 'attachment' => Attachment::class, @@ -487,7 +487,7 @@ return [ 'userGroupBill' => UserGroupBill::class, 'userGroup' => UserGroup::class, ], - 'rule-actions' => [ + 'rule-actions' => [ 'set_category' => SetCategory::class, 'clear_category' => ClearCategory::class, 'set_budget' => SetBudget::class, @@ -521,7 +521,7 @@ return [ // 'set_foreign_amount' => SetForeignAmount::class, // 'set_foreign_currency' => SetForeignCurrency::class, ], - 'context-rule-actions' => [ + 'context-rule-actions' => [ 'set_category', 'set_budget', 'add_tag', @@ -540,13 +540,13 @@ return [ 'convert_transfer', ], - 'test-triggers' => [ + 'test-triggers' => [ 'limit' => 10, 'range' => 200, ], // expected source types for each transaction type, in order of preference. - 'expected_source_types' => [ + 'expected_source_types' => [ 'source' => [ TransactionTypeModel::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], TransactionTypeEnum::DEPOSIT->value => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::REVENUE, AccountType::CASH], @@ -591,7 +591,7 @@ return [ TransactionTypeModel::LIABILITY_CREDIT => [AccountType::LIABILITY_CREDIT, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], ], ], - 'allowed_opposing_types' => [ + 'allowed_opposing_types' => [ 'source' => [ AccountType::ASSET => [ AccountType::ASSET, @@ -681,7 +681,7 @@ return [ ], ], // depending on the account type, return the allowed transaction types: - 'allowed_transaction_types' => [ + 'allowed_transaction_types' => [ 'source' => [ AccountType::ASSET => [ TransactionTypeModel::WITHDRAWAL, @@ -750,7 +750,7 @@ return [ ], // having the source + dest will tell you the transaction type. - 'account_to_transaction' => [ + 'account_to_transaction' => [ AccountType::ASSET => [ AccountType::ASSET => TransactionTypeModel::TRANSFER, AccountType::CASH => TransactionTypeModel::WITHDRAWAL, @@ -815,7 +815,7 @@ return [ ], // allowed source -> destination accounts. - 'source_dests' => [ + 'source_dests' => [ TransactionTypeModel::WITHDRAWAL => [ AccountType::ASSET => [AccountType::EXPENSE, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::CASH], AccountType::LOAN => [AccountType::EXPENSE, AccountType::CASH], @@ -854,7 +854,7 @@ return [ ], ], // if you add fields to this array, don't forget to update the export routine (ExportDataGenerator). - 'journal_meta_fields' => [ + 'journal_meta_fields' => [ // sepa 'sepa_cc', 'sepa_ct_op', @@ -888,28 +888,28 @@ return [ 'recurrence_count', 'recurrence_date', ], - 'webhooks' => [ + 'webhooks' => [ 'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3), ], - 'can_have_virtual_amounts' => [AccountType::ASSET], - 'can_have_opening_balance' => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], - 'dynamic_creation_allowed' => [ + 'can_have_virtual_amounts' => [AccountType::ASSET], + 'can_have_opening_balance' => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + 'dynamic_creation_allowed' => [ AccountType::EXPENSE, AccountType::REVENUE, AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION, AccountType::LIABILITY_CREDIT, ], - 'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], - 'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], - 'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'], + 'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], + 'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], + 'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'], // dynamic date ranges are as follows: - 'dynamic_date_ranges' => ['last7', 'last30', 'last90', 'last365', 'MTD', 'QTD', 'YTD'], + 'dynamic_date_ranges' => ['last7', 'last30', 'last90', 'last365', 'MTD', 'QTD', 'YTD'], // only used in v1 - 'allowed_sort_parameters' => ['order', 'name', 'iban'], + 'allowed_sort_parameters' => ['order', 'name', 'iban'], // preselected account lists possibilities: - 'preselected_accounts' => ['all', 'assets', 'liabilities'], + 'preselected_accounts' => ['all', 'assets', 'liabilities'], ];