Odoo18-Base/addons/account/tests/test_account_payment_duplicate.py
2025-01-06 10:57:38 +07:00

169 lines
8.5 KiB
Python

from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestAccountPaymentDuplicateMoves(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.company = cls.company_data['company']
cls.receivable = cls.company_data['default_account_receivable']
cls.payable = cls.company_data['default_account_payable']
cls.bank_journal = cls.company_data['default_journal_bank']
cls.comp_curr = cls.company_data['currency']
cls.payment_in = cls.env['account.payment'].create({
'amount': 50.0,
'payment_type': 'inbound',
'partner_id': cls.partner_a.id,
'destination_account_id': cls.receivable.id,
})
cls.payment_out = cls.env['account.payment'].create({
'amount': 50.0,
'payment_type': 'outbound',
'partner_id': cls.partner_a.id,
'destination_account_id': cls.payable.id,
})
cls.out_invoice_1 = cls.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2017-01-01',
'invoice_date': '2017-01-01',
'partner_id': cls.partner_a.id,
'invoice_line_ids': [(0, 0, {'product_id': cls.product_a.id, 'price_unit': 50.0, 'tax_ids': []})],
})
cls.in_invoice_1 = cls.env['account.move'].create({
'move_type': 'in_invoice',
'date': '2017-01-01',
'invoice_date': '2017-01-01',
'partner_id': cls.partner_a.id,
'invoice_line_ids': [(0, 0, {'product_id': cls.product_a.id, 'price_unit': 50.0, 'tax_ids': []})],
})
cls.out_invoice_2 = cls.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2017-01-01',
'invoice_date': '2017-01-01',
'partner_id': cls.partner_a.id,
'invoice_line_ids': [(0, 0, {'product_id': cls.product_a.id, 'price_unit': 20.0, 'tax_ids': []})],
})
(cls.out_invoice_1 + cls.out_invoice_2 + cls.in_invoice_1).action_post()
def test_duplicate_payments(self):
""" Ensure duplicated payments are computed correctly for both inbound and outbound payments.
For it to be a duplicate, the partner, the date and the amount must be the same.
"""
payment_in_1 = self.payment_in
payment_out_1 = self.payment_out
# Different type but same partner, amount and date, no duplicate
self.assertRecordValues(payment_in_1, [{'duplicate_payment_ids': []}])
# Create duplicate payments
payment_in_2 = payment_in_1.copy(default={'date': payment_in_1.date})
payment_out_2 = payment_out_1.copy(default={'date': payment_out_1.date})
# Inbound payment finds duplicate inbound payment, not the outbound payment with same information
self.assertRecordValues(payment_in_2, [{
'duplicate_payment_ids': [payment_in_1.id],
}])
# Outbound payment finds duplicate outbound duplicate, not the inbound payment with same information
self.assertRecordValues(payment_out_2, [{
'duplicate_payment_ids': [payment_out_1.id],
}])
# Different date but same amount and same partner, no duplicate
payment_out_3 = payment_out_1.copy(default={'date': '2023-12-31'})
self.assertRecordValues(payment_out_3, [{'duplicate_payment_ids': []}])
# Different amount but same partner and same date, no duplicate
payment_out_4 = self.env['account.payment'].create({
'amount': 60.0,
'payment_type': 'outbound',
'partner_id': self.partner_a.id,
'destination_account_id': self.payable.id,
})
self.assertRecordValues(payment_out_4, [{'duplicate_payment_ids': []}])
# Different partner but same amount and same date, no duplicate
payment_out_5 = self.env['account.payment'].create({
'amount': 50.0,
'payment_type': 'outbound',
'partner_id': self.partner_b.id,
'destination_account_id': self.payable.id,
})
self.assertRecordValues(payment_out_5, [{'duplicate_payment_ids': []}])
def test_in_payment_multiple_duplicate_inbound_batch(self):
""" Ensure duplicated payments are computed correctly when updated in batch,
where payments are all of a single payment type
"""
payment_1 = self.payment_in
payment_2 = payment_1.copy(default={'date': payment_1.date})
payment_3 = payment_1.copy(default={'date': payment_1.date})
payments = payment_1 + payment_2 + payment_3
self.assertRecordValues(payments, [
{'duplicate_payment_ids': (payment_2 + payment_3).ids},
{'duplicate_payment_ids': (payment_1 + payment_3).ids},
{'duplicate_payment_ids': (payment_1 + payment_2).ids},
])
def test_in_payment_multiple_duplicate_multiple_journals(self):
""" Ensure duplicated payments are computed correctly when updated in batch,
with inbound and outbound payments with different journals
"""
payment_in_1 = self.payment_in
payment_out_1 = self.payment_out
# Create a different journals with a different outstanding account
bank_journal_B = self.bank_journal.copy()
bank_journal_B.inbound_payment_method_line_ids.payment_account_id = self.env['account.account'].create({
'name': 'Outstanding Payment Account B',
'code': 'OPAB',
'account_type': 'asset_current',
'reconcile': True,
})
# Create new payments in the second journal
payment_in_2 = payment_in_1.copy(default={'date': payment_in_1.date})
payment_in_2.journal_id = bank_journal_B
payment_out_2 = payment_out_1.copy(default={'date': payment_out_1.date})
payment_out_2.journal_id = bank_journal_B
payments = payment_in_1 + payment_out_1 + payment_in_2 + payment_out_2
self.assertRecordValues(payments, [
{'duplicate_payment_ids': [payment_in_2.id]},
{'duplicate_payment_ids': [payment_out_2.id]},
{'duplicate_payment_ids': [payment_in_1.id]},
{'duplicate_payment_ids': [payment_out_1.id]},
])
def test_register_payment_different_payment_types(self):
""" Test that payment wizard correctly calculates duplicate_payment_ids """
payment_1 = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=self.out_invoice_1.ids).create({'payment_date': self.payment_in.date})
payment_2 = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=self.in_invoice_1.ids).create({'payment_date': self.payment_out.date})
existing_payment_in = self.payment_in
existing_payment_out = self.payment_out
# Payment wizards flag unreconciled existing payments of the same payment type only
self.assertRecordValues(payment_1, [{'duplicate_payment_ids': [existing_payment_in.id]}])
self.assertRecordValues(payment_2, [{'duplicate_payment_ids': [existing_payment_out.id]}])
def test_register_payment_single_batch_duplicate_payments(self):
""" Test that duplicate_payment_ids is correctly calculated for single batches """
payment_1 = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=self.out_invoice_1.ids).create({'payment_date': self.payment_in.date})
payment_2 = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=self.out_invoice_2.ids).create({'payment_date': self.out_invoice_2.date})
active_ids = (self.out_invoice_1 + self.out_invoice_2).ids
combined_payments = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=active_ids).create({
'amount': 50.0, # amount can be changed manually
'group_payment': True,
'payment_difference_handling': 'open',
'payment_method_line_id': self.inbound_payment_method_line.id,
})
existing_payment = self.payment_in
self.assertRecordValues(payment_1, [{'duplicate_payment_ids': [existing_payment.id]}])
self.assertRecordValues(payment_2, [{'duplicate_payment_ids': []}]) # different amount, not a duplicate
# Combined payments does not show payment_1 as duplicate because payment_1 is reconciled
self.assertRecordValues(combined_payments, [{'duplicate_payment_ids': [existing_payment.id]}])