[FIX] account: reconcile payments against min date_maturity journal item
1. Create a payment term with: - 50% due now - balance due in 14 days 2. Validate an invoice with this payment term and partner Agrolait 3. Create a payment from Agrolait with the 50% due 4. Add this outstanding credit to the invoice It is reconciled with the balance due in 14 days instead of what is due now. Because of this e.g. the Aged Receivable report will show the customer being overdue with a payment. This issue was first fixed in 9.0 atadad192cc0. It was then reintroduced in saas-11.4 atd3d2612061. This commit adds a test to avoid regressions like this. To fix the issue this sorts journal items by their Due Date if there is one. Otherwise we use the date from the journal entry as before. Note that before this commit journal items were not sorted at all by the two 'sorted' statements. sorted returns a sorted recordset, it doesn't modify the recordset it's called on. opw-1906665
This commit is contained in:
committed by
De Paoli Quentin
parent
dc35de9d30
commit
b9e6adcaf7
@@ -862,8 +862,8 @@ class AccountMoveLine(models.Model):
|
||||
# Create list of debit and list of credit move ordered by date-currency
|
||||
debit_moves = self.filtered(lambda r: r.debit != 0 or r.amount_currency > 0)
|
||||
credit_moves = self.filtered(lambda r: r.credit != 0 or r.amount_currency < 0)
|
||||
debit_moves.sorted(key=lambda a: (a.date, a.currency_id))
|
||||
credit_moves.sorted(key=lambda a: (a.date, a.currency_id))
|
||||
debit_moves = debit_moves.sorted(key=lambda a: (a.date_maturity or a.date, a.currency_id))
|
||||
credit_moves = credit_moves.sorted(key=lambda a: (a.date_maturity or a.date, a.currency_id))
|
||||
# Compute on which field reconciliation should be based upon:
|
||||
field = self[0].account_id.currency_id and 'amount_residual_currency' or 'amount_residual'
|
||||
#if all lines share the same currency, use amount_residual_currency to avoid currency rounding error
|
||||
|
||||
@@ -974,3 +974,63 @@ class TestReconciliation(AccountingTestCase):
|
||||
# because they owe us still 50 CC.
|
||||
self.assertEqual(invoice_cust_1.state, 'open',
|
||||
'Invoice is in status %s' % invoice_cust_1.state)
|
||||
|
||||
def test_multiple_term_reconciliation_opw_1906665(self):
|
||||
'''Test that when registering a payment to an invoice with multiple
|
||||
payment term lines the reconciliation happens against the line
|
||||
with the earliest date_maturity
|
||||
'''
|
||||
|
||||
payment_term = self.env['account.payment.term'].create({
|
||||
'name': 'Pay in 2 installments',
|
||||
'line_ids': [
|
||||
# Pay 50% immediately
|
||||
(0, 0, {
|
||||
'value': 'percent',
|
||||
'value_amount': 50,
|
||||
}),
|
||||
# Pay the rest after 14 days
|
||||
(0, 0, {
|
||||
'value': 'balance',
|
||||
'days': 14,
|
||||
})
|
||||
],
|
||||
})
|
||||
|
||||
# can't use self.create_invoice because it validates and we need to set payment_term_id
|
||||
invoice = self.account_invoice_model.create({
|
||||
'partner_id': self.partner_agrolait_id,
|
||||
'payment_term_id': payment_term.id,
|
||||
'reference_type': 'none',
|
||||
'currency_id': self.currency_usd_id,
|
||||
'name': 'Multiple payment terms',
|
||||
'account_id': self.account_rcv.id,
|
||||
'type': 'out_invoice',
|
||||
'date_invoice': time.strftime('%Y') + '-07-01',
|
||||
})
|
||||
self.account_invoice_line_model.create({
|
||||
'product_id': self.product.id,
|
||||
'quantity': 1,
|
||||
'price_unit': 50,
|
||||
'invoice_id': invoice.id,
|
||||
'name': self.product.display_name,
|
||||
'account_id': self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id,
|
||||
})
|
||||
|
||||
invoice.action_invoice_open()
|
||||
|
||||
payment = self.env['account.payment'].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': 25,
|
||||
'currency_id': self.currency_usd_id,
|
||||
'journal_id': self.bank_journal_usd.id,
|
||||
})
|
||||
payment.post()
|
||||
|
||||
invoice.assign_outstanding_credit(payment.move_line_ids.filtered('credit').id)
|
||||
|
||||
receivable_lines = invoice.move_id.line_ids.filtered(lambda line: line.account_id == self.account_rcv).sorted('date_maturity')[0]
|
||||
self.assertTrue(receivable_lines.matched_credit_ids)
|
||||
|
||||
Reference in New Issue
Block a user