mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
[FIX] account_payment_order: Grouped partial reconcile
When using a mode with "Group Transactions in Payment Orders" in a payment order with multiple bills from the same supplier, if e.g. the first bill's payment amount is reduced, the reduction was applied to the last bill instead of the specified one.
This commit is contained in:
@@ -417,15 +417,42 @@ class AccountPaymentOrder(models.Model):
|
||||
return action
|
||||
|
||||
def generated2uploaded(self):
|
||||
"""Post payments and reconcile against source journal items
|
||||
|
||||
Partially reconcile payments that don't match their source journal items,
|
||||
then reconcile the rest in one go.
|
||||
"""
|
||||
self.payment_ids.action_post()
|
||||
# Perform the reconciliation of payments and source journal items
|
||||
for payment in self.payment_ids:
|
||||
(
|
||||
payment.payment_line_ids.move_line_id
|
||||
+ payment.move_id.line_ids.filtered(
|
||||
payment_move_line_id = payment.move_id.line_ids.filtered(
|
||||
lambda x: x.account_id == payment.destination_account_id
|
||||
)
|
||||
).reconcile()
|
||||
apr = self.env["account.partial.reconcile"]
|
||||
excl_pay_lines = self.env["account.payment.line"]
|
||||
for line in payment.payment_line_ids:
|
||||
if not line.move_line_id:
|
||||
continue
|
||||
if line.amount_currency != -line.move_line_id.amount_residual_currency:
|
||||
if line.move_line_id.amount_residual_currency < 0:
|
||||
debit_move_id = payment_move_line_id.id
|
||||
credit_move_id = line.move_line_id.id
|
||||
else:
|
||||
debit_move_id = line.move_line_id.id
|
||||
credit_move_id = payment_move_line_id.id
|
||||
apr.create(
|
||||
{
|
||||
"debit_move_id": debit_move_id,
|
||||
"credit_move_id": credit_move_id,
|
||||
"amount": abs(line.amount_company_currency),
|
||||
"debit_amount_currency": abs(line.amount_currency),
|
||||
"credit_amount_currency": abs(line.amount_currency),
|
||||
}
|
||||
)
|
||||
excl_pay_lines |= line
|
||||
pay_lines = payment.payment_line_ids - excl_pay_lines
|
||||
if pay_lines:
|
||||
(pay_lines.move_line_id + payment_move_line_id).reconcile()
|
||||
self.write(
|
||||
{"state": "uploaded", "date_uploaded": fields.Date.context_today(self)}
|
||||
)
|
||||
|
||||
@@ -305,6 +305,62 @@ class TestPaymentOrderOutbound(TestPaymentOrderOutboundBase):
|
||||
fields.Date.context_today(outbound_order),
|
||||
)
|
||||
|
||||
def test_partial_reconciliation(self):
|
||||
"""
|
||||
Confirm both supplier invoices
|
||||
Add invoices to payment order
|
||||
Reduce payment amount of first invoice from 100 to 80
|
||||
Take payment order all the way to uploaded
|
||||
Confirm 80 reconciled with first, not second invoice
|
||||
|
||||
generated2uploaded() does partial reconciliation of non-matching
|
||||
line amounts before running .reconcile() against the remaining
|
||||
matching line amounts.
|
||||
"""
|
||||
# Open both invoices
|
||||
self.invoice.action_post()
|
||||
self.invoice_02.action_post()
|
||||
|
||||
# Add to payment order using the wizard
|
||||
self.env["account.invoice.payment.line.multi"].with_context(
|
||||
active_model="account.move",
|
||||
active_ids=self.invoice.ids + self.invoice_02.ids,
|
||||
).create({}).run()
|
||||
|
||||
payment_order = self.env["account.payment.order"].search(self.domain)
|
||||
self.assertEqual(len(payment_order), 1)
|
||||
|
||||
payment_order.write({"journal_id": self.bank_journal.id})
|
||||
|
||||
self.assertEqual(len(payment_order.payment_line_ids), 2)
|
||||
self.assertFalse(payment_order.payment_ids)
|
||||
|
||||
# Reduce payment of first invoice from 100 to 80
|
||||
first_payment_line, second_payment_line = payment_order.payment_line_ids
|
||||
first_payment_line.write({"amount_currency": 80.0})
|
||||
|
||||
# Open payment order
|
||||
payment_order.draft2open()
|
||||
|
||||
# Confirm single payment (grouped - two invoices one partner)
|
||||
self.assertEqual(payment_order.payment_count, 1)
|
||||
|
||||
# Generate and upload
|
||||
payment_order.open2generated()
|
||||
payment_order.generated2uploaded()
|
||||
|
||||
self.assertEqual(payment_order.state, "uploaded")
|
||||
with self.assertRaises(UserError):
|
||||
payment_order.unlink()
|
||||
|
||||
# Confirm payments were reconciled against correct invoices
|
||||
self.assertEqual(first_payment_line.amount_currency, 80.0)
|
||||
self.assertEqual(
|
||||
first_payment_line.move_line_id.amount_residual_currency, -20.0
|
||||
)
|
||||
self.assertEqual(second_payment_line.amount_currency, 100.0)
|
||||
self.assertEqual(second_payment_line.move_line_id.amount_residual_currency, 0.0)
|
||||
|
||||
def test_supplier_refund(self):
|
||||
"""
|
||||
Confirm the supplier invoice
|
||||
|
||||
Reference in New Issue
Block a user