[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 <las@odoo.com>
Signed-off-by: Lefebvre Thomas (thle) <thle@odoo.com>
This commit is contained in:
Thomas Lefebvre (thle)
2022-10-19 13:11:50 +02:00
parent 390955b751
commit 16219df38e
2 changed files with 97 additions and 4 deletions
+4 -4
View File
@@ -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:
@@ -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(