From 16219df38e6def1a1dee8dfaf4dee565cf7ef1d4 Mon Sep 17 00:00:00 2001 From: "Thomas Lefebvre (thle)" Date: Wed, 5 Oct 2022 11:44:15 +0000 Subject: [PATCH] [FIX] account: overwrite journal accounts of a payment Steps to reproduce: - create two journals, A and B, which have the default accounts defined in the payment method manual in "outstanding receipts accounts". - create a payment with a journal A; - duplicate the draft of the payment (because it is not possible to change a journal if it was posted before); - select the journal B and save (or confirm) - The journal is changed, but the default journal B accounts are not applied. Issue: Despite the payment is in draft and has not been posted before, move_line accounts do not change with the journal selected for the move. Cause: When a payment is duplicate, records are save in the database. Modify the journal en then save will trigger the write method of the payment model (and not the create). During this method, we begin to find the move lines which correspond to liquidity, counterpart and writeoff lines. Unfortunately, the line corresponding to the old journal will be detected as a writeoff and not as a liquidity line (because the journal has changed). This fault will cause a balance error in the rest of the procedure. Solution: Take into account the case where writeoffs are detected when there is no liquidity line (and no counterpart line). In this case, force the no writeoff line. Generate the correct ORM commands taking in consideration if the line exist (1: update) or not (0: create). opw-2998031 closes odoo/odoo#103496 X-original-commit: cf277b2685a72e0a8ca44c4a59331136a722fbed Signed-off-by: Laurent Smet Signed-off-by: Lefebvre Thomas (thle) --- addons/account/models/account_payment.py | 8 +- addons/account/tests/test_account_payment.py | 93 ++++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py index 2da2c0e0453..ba2e31a9b36 100644 --- a/addons/account/models/account_payment.py +++ b/addons/account/models/account_payment.py @@ -824,7 +824,7 @@ class AccountPayment(models.Model): if not any(field_name in changed_fields for field_name in ( 'date', 'amount', 'payment_type', 'partner_type', 'payment_reference', 'is_internal_transfer', - 'currency_id', 'partner_id', 'destination_account_id', 'partner_bank_id', + 'currency_id', 'partner_id', 'destination_account_id', 'partner_bank_id', 'journal_id' )): return @@ -835,7 +835,7 @@ class AccountPayment(models.Model): # This allows to create a new payment with custom 'line_ids'. write_off_line_vals = [] - if writeoff_lines: + if liquidity_lines and counterpart_lines and writeoff_lines: write_off_line_vals.append({ 'name': writeoff_lines[0].name, 'account_id': writeoff_lines[0].account_id.id, @@ -848,8 +848,8 @@ class AccountPayment(models.Model): line_vals_list = pay._prepare_move_line_default_vals(write_off_line_vals=write_off_line_vals) line_ids_commands = [ - (1, liquidity_lines.id, line_vals_list[0]), - (1, counterpart_lines.id, line_vals_list[1]), + Command.update(liquidity_lines.id, line_vals_list[0]) if liquidity_lines else Command.create(line_vals_list[0]), + Command.update(counterpart_lines.id, line_vals_list[1]) if counterpart_lines else Command.create(line_vals_list[1]) ] for line in writeoff_lines: diff --git a/addons/account/tests/test_account_payment.py b/addons/account/tests/test_account_payment.py index a9adc9319d5..3b44fa87999 100644 --- a/addons/account/tests/test_account_payment.py +++ b/addons/account/tests/test_account_payment.py @@ -198,6 +198,99 @@ class TestAccountPayment(AccountTestInvoicingCommon): }, ]) + def test_payment_move_sync_update_journal_custom_accounts(self): + """The objective is to edit the journal of a payment in order to check if the accounts are updated.""" + + company = self.company_data['company'] + # Create two different inbound accounts + outstanding_payment_A = company.account_journal_payment_debit_account_id + outstanding_payment_B = company.account_journal_payment_debit_account_id.copy() + # Create two different journals with a different account + journal_A = self.company_data['default_journal_bank'] + journal_A.inbound_payment_method_line_ids.payment_account_id = outstanding_payment_A + journal_B = self.company_data['default_journal_bank'].copy() + journal_B.inbound_payment_method_line_ids.payment_account_id = outstanding_payment_B + + # Fill the form payment + pay_form = Form(self.env['account.payment'].with_context(default_journal_id=self.company_data['default_journal_bank'].id)) + pay_form.amount = 50.0 + pay_form.payment_type = 'inbound' + pay_form.partner_id = self.partner_a + pay_form.journal_id = journal_A + # Save the form (to create move and move line) + payment = pay_form.save() + + # Check the payment + self.assertRecordValues(payment, [{ + 'amount': 50.0, + 'payment_type': 'inbound', + 'partner_type': 'customer', + 'payment_reference': False, + 'is_reconciled': False, + 'currency_id': self.company_data['currency'].id, + 'partner_id': self.partner_a.id, + 'journal_id': journal_A.id + }]) + self.assertRecordValues(payment.move_id, [{ + 'currency_id': self.company_data['currency'].id, + 'partner_id': self.partner_a.id, + 'journal_id': journal_A.id, + }]) + self.assertRecordValues(payment.line_ids.sorted('balance'), [ + { + 'debit': 0.0, + 'credit': 50.0, + 'amount_currency': -50.0, + 'currency_id': self.company_data['currency'].id, + 'account_id': self.company_data['default_account_receivable'].id, + }, + { + 'debit': 50.0, + 'credit': 0.0, + 'amount_currency': 50.0, + 'currency_id': self.company_data['currency'].id, + 'account_id': outstanding_payment_A.id, + }, + ]) + + # Change the journal on the form + pay_form.journal_id = journal_B + # Save the form (to write move and move line) + payment = pay_form.save() + + # Check the payment + self.assertRecordValues(payment, [{ + 'amount': 50.0, + 'payment_type': 'inbound', + 'partner_type': 'customer', + 'payment_reference': False, + 'is_reconciled': False, + 'currency_id': self.company_data['currency'].id, + 'partner_id': self.partner_a.id, + 'journal_id': journal_B.id + }]) + self.assertRecordValues(payment.move_id, [{ + 'currency_id': self.company_data['currency'].id, + 'partner_id': self.partner_a.id, + 'journal_id': journal_B.id, + }]) + self.assertRecordValues(payment.line_ids.sorted('balance'), [ + { + 'debit': 0.0, + 'credit': 50.0, + 'amount_currency': -50.0, + 'currency_id': self.company_data['currency'].id, + 'account_id': self.company_data['default_account_receivable'].id, + }, + { + 'debit': 50.0, + 'credit': 0.0, + 'amount_currency': 50.0, + 'currency_id': self.company_data['currency'].id, + 'account_id': outstanding_payment_B.id, + }, + ]) + def test_payment_move_sync_onchange(self): pay_form = Form(self.env['account.payment'].with_context(