From cf34b1e04af3331d958cdc5ac2f06e4a035012de Mon Sep 17 00:00:00 2001 From: "Florian(flg)" Date: Wed, 27 Jul 2022 08:42:33 +0000 Subject: [PATCH] [FIX] account: Remove useless check on bank statement button post. As we allow editing balances in processing state, we do not want to check balances before the validation of the bank statement (only in case of a bank journal). Commit about editing balances: 03f83eb87da00938b9d2df78651c1e06cf8a6d58 This fix split the _check_balance_end_real_same_as_computed into 2 functions. One to check "bank" bank statement and one to check "cash" bank statement. It allows to keep the same behavior for a "cash" bank statement when we post the bank statement, and having the right behavior for a "bank" bank statement. opw-2835728 closes odoo/odoo#97153 X-original-commit: 2d97efb4c84f647be3eb03f249c52b236bf00d55 Signed-off-by: Laurent Smet Signed-off-by: Florian Gilbert (flg) --- .../account/models/account_bank_statement.py | 82 +++++++++++-------- .../tests/test_account_bank_statement.py | 37 +++++++++ 2 files changed, 86 insertions(+), 33 deletions(-) diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index 3f0ae6d9f31..72fe904b39d 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -292,42 +292,58 @@ class AccountBankStatement(models.Model): st_line.currency_id = self.journal_id.currency_id or self.company_id.currency_id def _check_balance_end_real_same_as_computed(self): - ''' Check the balance_end_real (encoded manually by the user) is equals to the balance_end (computed by odoo). - In case of a cash statement, the different is set automatically to a profit/loss account. - ''' - for stmt in self: - if not stmt.currency_id.is_zero(stmt.difference): - if stmt.journal_type == 'cash': - st_line_vals = { - 'statement_id': stmt.id, - 'journal_id': stmt.journal_id.id, - 'amount': stmt.difference, - 'date': stmt.date, - } + """ Check the balance_end_real (encoded manually by the user) is equals to the balance_end (computed by odoo). """ + return self._check_cash_balance_end_real_same_as_computed() and self._check_bank_balance_end_real_same_as_computed() - if stmt.difference < 0.0: - if not stmt.journal_id.loss_account_id: - raise UserError(_('Please go on the %s journal and define a Loss Account. This account will be used to record cash difference.', stmt.journal_id.name)) + def _check_cash_balance_end_real_same_as_computed(self): + """ Check the balance_end_real (encoded manually by the user) is equals to the balance_end (computed by odoo). + For a cash statement, if there is a difference, the different is set automatically to a profit/loss account. + """ + for statement in self.filtered(lambda stmt: stmt.journal_type == 'cash'): + if not statement.currency_id.is_zero(statement.difference): + st_line_vals = { + 'statement_id': statement.id, + 'journal_id': statement.journal_id.id, + 'amount': statement.difference, + 'date': statement.date, + } - st_line_vals['payment_ref'] = _("Cash difference observed during the counting (Loss)") - st_line_vals['counterpart_account_id'] = stmt.journal_id.loss_account_id.id - else: - # statement.difference > 0.0 - if not stmt.journal_id.profit_account_id: - raise UserError(_('Please go on the %s journal and define a Profit Account. This account will be used to record cash difference.', stmt.journal_id.name)) + if statement.currency_id.compare_amounts(statement.difference, 0.0) < 0.0: + if not statement.journal_id.loss_account_id: + raise UserError(_( + "Please go on the %s journal and define a Loss Account. " + "This account will be used to record cash difference.", + statement.journal_id.name + )) - st_line_vals['payment_ref'] = _("Cash difference observed during the counting (Profit)") - st_line_vals['counterpart_account_id'] = stmt.journal_id.profit_account_id.id - - self.env['account.bank.statement.line'].create(st_line_vals) + st_line_vals['payment_ref'] = _("Cash difference observed during the counting (Loss)") + st_line_vals['counterpart_account_id'] = statement.journal_id.loss_account_id.id else: - balance_end_real = formatLang(self.env, stmt.balance_end_real, currency_obj=stmt.currency_id) - balance_end = formatLang(self.env, stmt.balance_end, currency_obj=stmt.currency_id) - raise UserError(_( - 'The ending balance is incorrect !\nThe expected balance (%(real_balance)s) is different from the computed one (%(computed_balance)s).', - real_balance=balance_end_real, - computed_balance=balance_end - )) + # statement.difference > 0.0 + if not statement.journal_id.profit_account_id: + raise UserError(_( + "Please go on the %s journal and define a Profit Account. " + "This account will be used to record cash difference.", + statement.journal_id.name + )) + + st_line_vals['payment_ref'] = _("Cash difference observed during the counting (Profit)") + st_line_vals['counterpart_account_id'] = statement.journal_id.profit_account_id.id + + self.env['account.bank.statement.line'].create(st_line_vals) + return True + + def _check_bank_balance_end_real_same_as_computed(self): + """ Check the balance_end_real (encoded manually by the user) is equals to the balance_end (computed by odoo). """ + for statement in self.filtered(lambda stmt: stmt.journal_type == 'bank'): + if not statement.currency_id.is_zero(statement.difference): + balance_end_real = formatLang(self.env, statement.balance_end_real, currency_obj=statement.currency_id) + balance_end = formatLang(self.env, statement.balance_end, currency_obj=statement.currency_id) + raise UserError(_( + 'The ending balance is incorrect !\nThe expected balance (%(real_balance)s) is different from the computed one (%(computed_balance)s).', + real_balance=balance_end_real, + computed_balance=balance_end + )) return True @api.ondelete(at_uninstall=False) @@ -398,7 +414,7 @@ class AccountBankStatement(models.Model): if any(statement.state != 'open' for statement in self): raise UserError(_("Only new statements can be posted.")) - self._check_balance_end_real_same_as_computed() + self._check_cash_balance_end_real_same_as_computed() for statement in self: if not statement.name: diff --git a/addons/account/tests/test_account_bank_statement.py b/addons/account/tests/test_account_bank_statement.py index 66ff7715f88..e200c8224d2 100644 --- a/addons/account/tests/test_account_bank_statement.py +++ b/addons/account/tests/test_account_bank_statement.py @@ -292,6 +292,43 @@ class TestAccountBankStatement(TestAccountBankStatementCommon): 'is_reconciled': True, }]) + def test_bank_statement_with_difference(self): + """ Test that a bank statement with difference could be posted but not validated. """ + bank_statement = self.env['account.bank.statement'].create({ + 'name': 'test_statement', + 'date': '2019-01-01', + 'journal_id': self.bank_journal_1.id, + 'balance_start': 10.0, + 'balance_end_real': 100.0, + 'balance_end': 10.0, + 'line_ids': [Command.create({ + 'date': fields.Date.to_date('2019-01-01'), + 'payment_ref': 'transaction_abc', + 'amount': 10, + 'partner_id': self.partner_a.id, + })] + }) + bank_statement.button_post() + # Check if the bank statement is well posted (No check on the balance as the balance could be edited after). + self.assertEqual(bank_statement.state, 'posted') + + # Check that the bank statement couldn't be validated with balance_end != balance_end_real + with self.assertRaises(UserError): + bank_statement.button_validate() + + # Check if we can validate the bank statement if balance_end == balance_end_real + bank_statement.balance_end_real = bank_statement.balance_end + + # Reconcile without the bank reconciliation widget since the widget is in enterprise. + statement_line = bank_statement.line_ids + st_liquidity_lines, st_suspense_lines, _st_other_lines = statement_line \ + .with_context(skip_account_move_synchronization=True) \ + ._seek_for_lines() + st_suspense_lines.account_id = st_liquidity_lines.account_id + (st_suspense_lines + st_liquidity_lines).reconcile() + + bank_statement.button_validate() + self.assertEqual(bank_statement.state, 'confirm') @tagged('post_install', '-at_install') class TestAccountBankStatementLine(TestAccountBankStatementCommon):