[FIX] account: payment state when reconciling refund with bank statement
**Summary** Currently, if you create a credit note/refund and reconcile it directly with a statement line (without creating a payment), the credit note/refund ends up in the "reversed" payment state, whereas it should be "paid". **Setup** - Install `account_accountant` **Steps to reproduce** - create a credit note/refund and confirm it - create the corresponding bank statement line - reconcile those two Go back to the credit/refund not, you should see that its payment state is "reversed", instead of "paid". opw-3328830 closes odoo/odoo#127027 X-original-commit: 2dd3fa7d4d367e38baf529fdde5d18caa2f238cf Signed-off-by: Laurent Smet (las) <las@odoo.com> Signed-off-by: Séna Serge Nshimiyimana (sesn) <sesn@odoo.com>
This commit is contained in:
@@ -935,7 +935,8 @@ class AccountMove(models.Model):
|
||||
ARRAY_AGG(counterpart_move.move_type) AS counterpart_move_types,
|
||||
COALESCE(BOOL_AND(COALESCE(pay.is_matched, FALSE))
|
||||
FILTER (WHERE counterpart_move.payment_id IS NOT NULL), TRUE) AS all_payments_matched,
|
||||
BOOL_OR(COALESCE(BOOL(pay.id), FALSE)) as has_payment
|
||||
BOOL_OR(COALESCE(BOOL(pay.id), FALSE)) as has_payment,
|
||||
BOOL_OR(COALESCE(BOOL(counterpart_move.statement_line_id), FALSE)) as has_st_line
|
||||
FROM account_partial_reconcile part
|
||||
JOIN account_move_line source_line ON source_line.id = part.{source_field}_move_id
|
||||
JOIN account_account account ON account.id = source_line.account_id
|
||||
@@ -978,7 +979,7 @@ class AccountMove(models.Model):
|
||||
if payment_state_matters:
|
||||
|
||||
if currency.is_zero(invoice.amount_residual):
|
||||
if any(x['has_payment'] for x in reconciliation_vals):
|
||||
if any(x['has_payment'] or x['has_st_line'] for x in reconciliation_vals):
|
||||
|
||||
# Check if the invoice/expense entry is fully paid or 'in_payment'.
|
||||
if all(x['all_payments_matched'] for x in reconciliation_vals):
|
||||
|
||||
@@ -5,6 +5,7 @@ from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
from odoo.tests.common import Form
|
||||
from odoo.tests import tagged
|
||||
from odoo import fields, Command
|
||||
from odoo.osv import expression
|
||||
from odoo.exceptions import ValidationError, RedirectWarning
|
||||
from datetime import date
|
||||
|
||||
@@ -2149,6 +2150,13 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
self.assertEqual(move.invoice_date.strftime('%Y-%m-%d'), '2022-05-06')
|
||||
|
||||
def _assert_payment_move_state(self, move_type, amount, counterpart_values_list, payment_state):
|
||||
def assert_partial(line1, line2):
|
||||
partial = self.env['account.partial.reconcile'].search(expression.OR([
|
||||
[('debit_move_id', '=', line1.id), ('credit_move_id', '=', line2.id)],
|
||||
[('debit_move_id', '=', line2.id), ('credit_move_id', '=', line1.id)],
|
||||
]), limit=1)
|
||||
self.assertTrue(partial)
|
||||
|
||||
def create_move(move_type, amount, account=None):
|
||||
move_vals = {
|
||||
'move_type': move_type,
|
||||
@@ -2218,6 +2226,22 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
|
||||
reverse_move.action_post()
|
||||
|
||||
def create_statement_line(move, amount):
|
||||
statement_line = self.env['account.bank.statement.line'].create({
|
||||
'payment_ref': 'ref',
|
||||
'journal_id': self.company_data['default_journal_bank'].id,
|
||||
'amount': amount,
|
||||
'date': '2020-01-10',
|
||||
})
|
||||
_st_liquidity_lines, st_suspense_lines, _st_other_lines = statement_line\
|
||||
.with_context(skip_account_move_synchronization=True)\
|
||||
._seek_for_lines()
|
||||
line = move.line_ids.filtered(lambda line: line.account_type in ('asset_receivable', 'liability_payable'))
|
||||
|
||||
st_suspense_lines.account_id = line.account_id
|
||||
(st_suspense_lines + line).reconcile()
|
||||
assert_partial(st_suspense_lines, line)
|
||||
|
||||
move = create_move(move_type, amount)
|
||||
line = move.line_ids.filtered(lambda line: line.account_type in ('asset_receivable', 'liability_payable'))
|
||||
for counterpart_move_type, counterpart_amount in counterpart_values_list:
|
||||
@@ -2225,10 +2249,13 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
create_payment(move, counterpart_amount)
|
||||
elif counterpart_move_type == 'reverse':
|
||||
create_reverse(move, counterpart_amount)
|
||||
elif counterpart_move_type == 'statement_line':
|
||||
create_statement_line(move, counterpart_amount)
|
||||
else:
|
||||
counterpart_move = create_move(counterpart_move_type, counterpart_amount, account=line.account_id)
|
||||
counterpart_line = counterpart_move.line_ids.filtered(lambda x: x.account_id == line.account_id)
|
||||
(line + counterpart_line).reconcile()
|
||||
assert_partial(line, counterpart_line)
|
||||
|
||||
if payment_state == 'in_payment' and move._get_invoice_in_payment_state() == 'paid':
|
||||
payment_state = 'paid'
|
||||
@@ -2256,24 +2283,42 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
|
||||
('out_invoice', 1000.0, [('payment', 500.0)], 'partial'),
|
||||
('out_invoice', 1000.0, [('payment', 1000.0)], 'in_payment'),
|
||||
('out_invoice', 1000.0, [('statement_line', 500.0)], 'partial'),
|
||||
('out_invoice', 1000.0, [('statement_line', 1000.0)], 'paid'),
|
||||
('out_receipt', 1000.0, [('payment', 500.0)], 'partial'),
|
||||
('out_receipt', 1000.0, [('payment', 1000.0)], 'in_payment'),
|
||||
('out_receipt', 1000.0, [('statement_line', 500.0)], 'partial'),
|
||||
('out_receipt', 1000.0, [('statement_line', 1000.0)], 'paid'),
|
||||
('out_refund', 1000.0, [('payment', 500.0)], 'partial'),
|
||||
('out_refund', 1000.0, [('payment', 1000.0)], 'in_payment'),
|
||||
('out_refund', 1000.0, [('statement_line', -500.0)], 'partial'),
|
||||
('out_refund', 1000.0, [('statement_line', -1000.0)], 'paid'),
|
||||
('in_invoice', 1000.0, [('payment', 500.0)], 'partial'),
|
||||
('in_invoice', 1000.0, [('payment', 1000.0)], 'in_payment'),
|
||||
('in_invoice', 1000.0, [('statement_line', -500.0)], 'partial'),
|
||||
('in_invoice', 1000.0, [('statement_line', -1000.0)], 'paid'),
|
||||
('in_receipt', 1000.0, [('payment', 500.0)], 'partial'),
|
||||
('in_receipt', 1000.0, [('payment', 1000.0)], 'in_payment'),
|
||||
('in_receipt', 1000.0, [('statement_line', -500.0)], 'partial'),
|
||||
('in_receipt', 1000.0, [('statement_line', -1000.0)], 'paid'),
|
||||
('in_refund', 1000.0, [('payment', 500.0)], 'partial'),
|
||||
('in_refund', 1000.0, [('payment', 1000.0)], 'in_payment'),
|
||||
('in_refund', 1000.0, [('statement_line', 500.0)], 'partial'),
|
||||
('in_refund', 1000.0, [('statement_line', 1000.0)], 'paid'),
|
||||
('entry', 1000.0, [('payment', 500.0)], 'not_paid'),
|
||||
('entry', 1000.0, [('payment', 1000.0)], 'not_paid'),
|
||||
('entry', 1000.0, [('statement_line', 500.0)], 'not_paid'),
|
||||
('entry', 1000.0, [('statement_line', 1000.0)], 'not_paid'),
|
||||
|
||||
('out_invoice', 1000.0, [('out_refund', 500.0), ('payment', 500.0)], 'in_payment'),
|
||||
('out_invoice', 1000.0, [('out_refund', 500.0), ('payment', 400.0)], 'partial'),
|
||||
('out_invoice', 1000.0, [('out_refund', 500.0), ('statement_line', 500.0)], 'paid'),
|
||||
('out_invoice', 1000.0, [('out_refund', 500.0), ('statement_line', 400.0)], 'partial'),
|
||||
('out_invoice', 1000.0, [('entry', -1000.0)], 'paid'),
|
||||
('in_invoice', 1000.0, [('in_refund', 500.0), ('payment', 500.0)], 'in_payment'),
|
||||
('in_invoice', 1000.0, [('in_refund', 500.0), ('payment', 400.0)], 'partial'),
|
||||
('in_invoice', 1000.0, [('in_refund', 500.0), ('statement_line', -500.0)], 'paid'),
|
||||
('in_invoice', 1000.0, [('in_refund', 500.0), ('statement_line', -400.0)], 'partial'),
|
||||
('in_invoice', 1000.0, [('entry', 1000.0)], 'paid'),
|
||||
):
|
||||
with self.subTest(
|
||||
|
||||
Reference in New Issue
Block a user