[FIX] account: allows ungrouped batch payment with different payment terms

Steps to reproduce:
- Create two Bills with different payment terms with one having no "early_discount" such as '30% Now, Balance 60 Days'
- Select the Bills and click on Register Payment (make sure the payment is not grouped)

Issue:
Server Error

Cause:
We try to Register Payment for all the Bills at once, but the "early_discount" is not defined for all the Bills.
So, whenever there is a move with an early discount, the mode is always considered as "early_payment".
Therefore, we call `_get_invoice_counterpart_amls_for_early_payment_discount` with an empty list since there is no early discount
https://github.com/odoo/odoo/blob/0ffaaebfa5c25c4bf71fb0e02288767dbfac959d/addons/account/wizard/account_payment_register.py#L750-L755
https://github.com/odoo/odoo/blob/0ffaaebfa5c25c4bf71fb0e02288767dbfac959d/addons/account/wizard/account_payment_register.py#L760

Causing the "local variable 'aml' referenced before assignment" error.

Solution:
We only iterate through moves belonging to the batch. This way, we avoid setting the mode to "early_payment" and entering the confition.

opw-3378445

closes odoo/odoo#132113

X-original-commit: 9bba9576d3365500a5c1eda0cfd57457fd999878
Signed-off-by: Laurent Smet (las) <las@odoo.com>
Signed-off-by: Yolann Sabaux (yosa) <yosa@odoo.com>
This commit is contained in:
Yolann Sabaux
2023-08-17 09:21:02 +02:00
parent 1e77837bf5
commit f5da45537a
2 changed files with 91 additions and 1 deletions
@@ -24,6 +24,17 @@ class TestAccountEarlyPaymentDiscount(AccountTestInvoicingCommon):
})]
})
cls.pay_term_net_30_days = cls.env['account.payment.term'].create({
'name': 'Net 30 days',
'line_ids': [
(0, 0, {
'value_amount': 100,
'value': 'percent',
'nb_days': 30,
}),
],
})
def assert_tax_totals(self, document, expected_values):
main_keys_to_ignore = {
'formatted_amount_total', 'formatted_amount_untaxed', 'display_tax_base', 'subtotals_order'}
@@ -691,3 +702,82 @@ class TestAccountEarlyPaymentDiscount(AccountTestInvoicingCommon):
}) for price_unit, quantity, taxes in line_create_vals
]
})
def test_register_payment_batch_with_discount_and_without_discount(self):
"""
Test that a batch payment, that is
- not grouped
- with invoices having different payment terms (1 with discount, 1 without)
-> will not crash
"""
out_invoice_1 = self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2019-01-01',
'invoice_date': '2019-01-01',
'partner_id': self.partner_a.id,
'currency_id': self.currency_data['currency'].id,
'invoice_line_ids': [Command.create({'product_id': self.product_a.id, 'price_unit': 1000.0, 'tax_ids': []})],
'invoice_payment_term_id': self.pay_term_net_30_days.id,
})
out_invoice_2 = self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2019-01-01',
'invoice_date': '2019-01-01',
'partner_id': self.partner_a.id,
'currency_id': self.currency_data['currency'].id,
'invoice_line_ids': [Command.create({'product_id': self.product_a.id, 'price_unit': 2000.0, 'tax_ids': []})],
'invoice_payment_term_id': self.early_pay_10_percents_10_days.id,
})
(out_invoice_1 + out_invoice_2).action_post()
active_ids = (out_invoice_1 + out_invoice_2).ids
payments = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=active_ids).create({
'payment_date': '2019-01-01', 'group_payment': False
})._create_payments()
self.assertTrue(all(payments.mapped('is_reconciled')))
self.assertRecordValues(payments.line_ids.sorted('balance'), [
{'amount_currency': -2000.0},
{'amount_currency': -1000.0},
{'amount_currency': 200.0},
{'amount_currency': 1000},
{'amount_currency': 1800},
])
def test_register_payment_batch_without_discount(self):
"""
Test that a batch payment, that is
- not grouped
- with invoices having the same payment terms (without discount)
-> will not crash
"""
out_invoice_1 = self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2019-01-01',
'invoice_date': '2019-01-01',
'partner_id': self.partner_a.id,
'currency_id': self.currency_data['currency'].id,
'invoice_line_ids': [Command.create({'product_id': self.product_a.id, 'price_unit': 1000.0, 'tax_ids': []})],
'invoice_payment_term_id': self.pay_term_net_30_days.id,
})
out_invoice_2 = self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2019-01-01',
'invoice_date': '2019-01-01',
'partner_id': self.partner_a.id,
'currency_id': self.currency_data['currency'].id,
'invoice_line_ids': [Command.create({'product_id': self.product_a.id, 'price_unit': 2000.0, 'tax_ids': []})],
'invoice_payment_term_id': self.pay_term_net_30_days.id,
})
(out_invoice_1 + out_invoice_2).action_post()
active_ids = (out_invoice_1 + out_invoice_2).ids
payments = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=active_ids).create({
'payment_date': '2019-01-01', 'group_payment': False
})._create_payments()
self.assertTrue(all(payments.mapped('is_reconciled')))
self.assertRecordValues(payments.line_ids.sorted('balance'), [
{'amount_currency': -2000.0},
{'amount_currency': -1000.0},
{'amount_currency': 1000.0},
{'amount_currency': 2000},
])
@@ -500,7 +500,7 @@ class AccountPaymentRegister(models.TransientModel):
self.ensure_one()
amount = 0.0
mode = False
moves = self.line_ids.move_id
moves = batch_result['lines'].mapped('move_id')
for move in moves:
if early_payment_discount and move._is_eligible_for_early_payment_discount(move.currency_id, self.payment_date):
amount += move.invoice_payment_term_id._get_amount_due_after_discount(move.amount_total, move.amount_tax)#todo currencies