[FIX] account: fix "post at bank reconciliation" option of bank journals
Before that, with "post at bank reconciliation option" activated on bank journal, the following scenarii did not work as expected: 1. When creating an invoice, making two payments for it, and then matching only one of them with a bank statement => the invoice was marked as 'paid' while it should have staid 'in payment' until the second payment gets a bank statement. 2. When directly reconciling a bank statement with an invoice for its full amount => the invoice staid in "in payment" state, while it should have been "paid" [IMP] account: add tests for the aforementioned cases closes odoo/odoo#28428
This commit is contained in:
@@ -550,7 +550,8 @@ class AccountBankStatementLine(models.Model):
|
||||
aml_rec.payment_id.payment_date = self.date
|
||||
aml_rec.move_id.post()
|
||||
# We check the paid status of the invoices reconciled with this payment
|
||||
aml_rec.payment_id.reconciled_invoice_ids.filtered(lambda x: x.state == 'in_payment').write({'state': 'paid'})
|
||||
for invoice in aml_rec.payment_id.reconciled_invoice_ids:
|
||||
self._check_invoice_state(invoice)
|
||||
|
||||
# Create move line(s). Either matching an existing journal entry (eg. invoice), in which
|
||||
# case we reconcile the existing and the new move lines together, or being a write-off.
|
||||
@@ -639,6 +640,8 @@ class AccountBankStatementLine(models.Model):
|
||||
|
||||
(new_aml | counterpart_move_line).reconcile()
|
||||
|
||||
self._check_invoice_state(counterpart_move_line.invoice_id)
|
||||
|
||||
# Balance the move
|
||||
st_line_amount = -sum([x.balance for x in move.line_ids])
|
||||
aml_dict = self._prepare_reconciliation_move_line(move, st_line_amount)
|
||||
@@ -658,3 +661,7 @@ class AccountBankStatementLine(models.Model):
|
||||
|
||||
counterpart_moves.assert_balanced()
|
||||
return counterpart_moves
|
||||
|
||||
def _check_invoice_state(self, invoice):
|
||||
if invoice.state == 'in_payment' and all([payment.state == 'reconciled' for payment in invoice.mapped('payment_move_line_ids.payment_id')]):
|
||||
invoice.write({'state': 'paid'})
|
||||
|
||||
@@ -26,6 +26,19 @@ class TestBankStatementReconciliation(AccountingTestCase):
|
||||
self.assertEqual(prop[0]['id'], rcv_mv_line.id)
|
||||
|
||||
def test_full_reconcile(self):
|
||||
self._reconcile_invoice_with_statement(False)
|
||||
|
||||
def test_post_at_bank_rec_full_reconcile(self):
|
||||
""" Test the full reconciliation of a bank statement directly with an invoice.
|
||||
"""
|
||||
self._reconcile_invoice_with_statement(True)
|
||||
|
||||
def _reconcile_invoice_with_statement(self, post_at_bank_rec):
|
||||
""" Tests the reconciliation of an invoice with a bank statement, using
|
||||
the provided 'post at bank reconciliation' value for the bank journal
|
||||
where to generate the statement.
|
||||
"""
|
||||
self.bs_model.with_context(journal_type='bank')._default_journal().post_at_bank_reconciliation = post_at_bank_rec
|
||||
rcv_mv_line = self.create_invoice(100)
|
||||
st_line = self.create_statement_line(100)
|
||||
# reconcile
|
||||
@@ -47,6 +60,7 @@ class TestBankStatementReconciliation(AccountingTestCase):
|
||||
self.assertTrue(rcv_mv_line.reconciled)
|
||||
self.assertTrue(counterpart_mv_line.reconciled)
|
||||
self.assertEqual(counterpart_mv_line.matched_credit_ids, rcv_mv_line.matched_debit_ids)
|
||||
self.assertEqual(rcv_mv_line.invoice_id.state, 'paid', "The related invoice's state should now be 'paid'")
|
||||
|
||||
def test_reconcile_with_write_off(self):
|
||||
pass
|
||||
|
||||
@@ -507,14 +507,14 @@ class TestPayment(AccountingTestCase):
|
||||
self.assertTrue(invoice.move_id.line_ids.filtered(lambda l: l.account_id == self.account_receivable)[0].full_reconcile_id)
|
||||
|
||||
def test_post_at_bank_reconciliation_payment(self):
|
||||
# Create a new payment in a journal requiring the journal entries to be posted at bank reconciliation
|
||||
# Create two new payments in a journal requiring the journal entries to be posted at bank reconciliation
|
||||
post_at_bank_rec_journal = bank_journal_euro = self.env['account.journal'].create({
|
||||
'name': 'Bank',
|
||||
'type': 'bank',
|
||||
'code': 'COUCOU',
|
||||
'post_at_bank_rec': True,
|
||||
})
|
||||
payment = self.payment_model.create({'payment_type': 'inbound',
|
||||
payment_one = self.payment_model.create({'payment_type': 'inbound',
|
||||
'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id,
|
||||
'partner_type': 'customer',
|
||||
'partner_id': self.partner_agrolait.id,
|
||||
@@ -524,17 +524,48 @@ class TestPayment(AccountingTestCase):
|
||||
'writeoff_account_id': self.account_receivable.id,
|
||||
'journal_id': post_at_bank_rec_journal.id,
|
||||
})
|
||||
payment.post()
|
||||
payment_one.post()
|
||||
payment_two = self.payment_model.create({'payment_type': 'inbound',
|
||||
'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id,
|
||||
'partner_type': 'customer',
|
||||
'partner_id': self.partner_agrolait.id,
|
||||
'amount': 11,
|
||||
'payment_date': time.strftime('%Y') + '-12-15',
|
||||
'payment_difference_handling': 'reconcile',
|
||||
'writeoff_account_id': self.account_receivable.id,
|
||||
'journal_id': post_at_bank_rec_journal.id,
|
||||
})
|
||||
payment_two.post()
|
||||
|
||||
# Check the payment and move state
|
||||
self.assertEqual(payment.state, 'posted', "Payment shoud be in posted state.")
|
||||
self.assertEqual(payment.mapped('move_line_ids.move_id.state'), ['draft'], "A posted payment in a bank journal with the 'post at bank reconciliation' option activated should correspond to a draft account.move")
|
||||
# Check the payments and their move state
|
||||
self.assertEqual(payment_one.state, 'posted', "Payment one shoud be in posted state.")
|
||||
self.assertEqual(payment_one.mapped('move_line_ids.move_id.state'), ['draft'], "A posted payment (payment_one) in a bank journal with the 'post at bank reconciliation' option activated should correspond to a draft account.move")
|
||||
self.assertEqual(payment_two.state, 'posted', "Payment two shoud be in posted state.")
|
||||
self.assertEqual(payment_two.mapped('move_line_ids.move_id.state'), ['draft'], "A posted payment (payment_two) in a bank journal with the 'post at bank reconciliation' option activated should correspond to a draft account.move")
|
||||
|
||||
# Match the payment with a bank statement line
|
||||
bank_statement = self.reconcile(payment.move_line_ids.filtered(lambda x: x.account_id == post_at_bank_rec_journal.default_debit_account_id), 42)
|
||||
stmt_line_date = bank_statement.mapped('line_ids.date')
|
||||
# Reconcile the two payments with an invoice, whose full amount is equal to their sum
|
||||
invoice = self.create_invoice(amount=53, partner=self.partner_agrolait.id)
|
||||
(payment_one.move_line_ids + payment_two.move_line_ids + invoice.move_id.line_ids).filtered(lambda x: x.account_id.user_type_id.type == 'receivable').reconcile()
|
||||
|
||||
# Check the move has been posted properly
|
||||
self.assertEqual(payment.mapped('move_line_ids.move_id.state'), ['posted'], "After bank reconciliation, the payment's account.move should be posted.")
|
||||
self.assertEqual(payment.mapped('move_line_ids.move_id.date'), stmt_line_date, "After bank reconciliation, the payment's account.move should share the same date as the bank statement.")
|
||||
self.assertEqual([payment.payment_date], stmt_line_date, "After bank reconciliation, the payment should share the same date as the bank statement.")
|
||||
self.assertTrue(invoice.reconciled, "Invoice should have been reconciled with the payments")
|
||||
self.assertEqual(invoice.state, 'in_payment', "Invoice should be in 'in payment' state")
|
||||
|
||||
# Match the first payment with a bank statement line
|
||||
bank_statement_one = self.reconcile(payment_one.move_line_ids.filtered(lambda x: x.account_id.user_type_id.type == 'liquidity'), 42)
|
||||
stmt_line_date_one = bank_statement_one.mapped('line_ids.date')
|
||||
|
||||
self.assertEqual(payment_one.mapped('move_line_ids.move_id.state'), ['posted'], "After bank reconciliation, payment one's account.move should be posted.")
|
||||
self.assertEqual(payment_one.mapped('move_line_ids.move_id.date'), stmt_line_date_one, "After bank reconciliation, payment one's account.move should share the same date as the bank statement.")
|
||||
self.assertEqual([payment_one.payment_date], stmt_line_date_one, "After bank reconciliation, payment one should share the same date as the bank statement.")
|
||||
self.assertEqual(invoice.state, 'in_payment', "The invoice should still be 'in payment', not all its payments are reconciled with a statement")
|
||||
|
||||
# Match the second payment with a bank statement line
|
||||
bank_statement_two = self.reconcile(payment_two.move_line_ids.filtered(lambda x: x.account_id.user_type_id.type == 'liquidity'), 42)
|
||||
stmt_line_date_two = bank_statement_two.mapped('line_ids.date')
|
||||
|
||||
self.assertEqual(payment_two.mapped('move_line_ids.move_id.state'), ['posted'], "After bank reconciliation, payment two's account.move should be posted.")
|
||||
self.assertEqual(payment_two.mapped('move_line_ids.move_id.date'), stmt_line_date_two, "After bank reconciliation, payment two's account.move should share the same date as the bank statement.")
|
||||
self.assertEqual([payment_two.payment_date], stmt_line_date_two, "After bank reconciliation, payment two should share the same date as the bank statement.")
|
||||
|
||||
# The invoice should now be paid
|
||||
self.assertEqual(invoice.state, 'paid', "Invoice should be in 'paid' state after having reconciled the two payments with a bank statement")
|
||||
|
||||
Reference in New Issue
Block a user