From c4e007f1eb82aab09581cb9bac10974a56bfe014 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 16 Jun 2026 00:03:41 +0530 Subject: [PATCH] fix(accounts): clear clearance date when amending reconciled voucher The framework ignores `no_copy` while amending, so a reconciled voucher carried a stale clearance date into its amendment even though the linked bank transaction gets unreconciled on cancellation. Reset it via a shared `before_insert` hook on AccountsController. Fixes #54909 (cherry picked from commit 1a8d73cbbe94bb372adc0dbfa144f7bb04ebc25b) # Conflicts: # erpnext/controllers/accounts_controller.py --- .../bank_transaction/test_bank_transaction.py | 30 ++++++++++++++++++ erpnext/controllers/accounts_controller.py | 31 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py index 4294c4462b1..05a9c055078 100644 --- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py @@ -115,6 +115,36 @@ class TestBankTransaction(FrappeTestCase): self.assertEqual(bank_transaction.unallocated_amount, 1700) self.assertEqual(bank_transaction.payment_entries, []) + # Amending a reconciled payment entry must not carry over its clearance date + def test_clearance_date_cleared_on_amend(self): + bank_transaction = frappe.get_doc( + "Bank Transaction", + dict(description="1512567 BG/000003025 OPSKATTUZWXXX AT776000000098709849 Herr G"), + ) + payment = frappe.get_doc("Payment Entry", dict(party="Mr G", paid_amount=1700)) + vouchers = json.dumps( + [ + { + "payment_doctype": "Payment Entry", + "payment_name": payment.name, + "amount": bank_transaction.unallocated_amount, + } + ] + ) + reconcile_vouchers(bank_transaction.name, vouchers) + + self.assertTrue(frappe.db.get_value("Payment Entry", payment.name, "clearance_date")) + + payment.reload() + payment.cancel() + + amended = frappe.copy_doc(payment) + amended.amended_from = payment.name + amended.docstatus = 0 + amended.insert() + + self.assertFalse(amended.clearance_date) + # Check if ERPNext can correctly filter a linked payments based on the debit/credit amount def test_debit_credit_output(self): bank_transaction = frappe.get_doc( diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 0d3f13dde8c..0a71583ddcd 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -139,7 +139,38 @@ class AccountsController(TransactionBase): "Sales Invoice", ) if self.doctype in relevant_docs: +<<<<<<< HEAD self.set_payment_schedule() +======= + from erpnext.accounts.services.payment_schedule import PaymentScheduleService + + PaymentScheduleService(self).set_payment_schedule() + + def before_insert(self): + self.clear_clearance_date_on_amend() + + def clear_clearance_date_on_amend(self): + """Drop the bank reconciliation clearance date copied over while amending. + + The framework copies `no_copy` fields when amending, so a reconciled + voucher would carry a stale clearance date into its amendment even though + the linked bank transaction gets unreconciled on cancellation. + """ + if not self.get("amended_from"): + return + + if self.meta.has_field("clearance_date"): + self.clearance_date = None + + for payment in self.get("payments") or []: + if payment.meta.has_field("clearance_date"): + payment.clearance_date = None + + def on_update(self): + from erpnext.controllers.taxes_and_totals import process_item_wise_tax_details + + process_item_wise_tax_details(self) +>>>>>>> 1a8d73cbbe (fix(accounts): clear clearance date when amending reconciled voucher) def remove_bundle_for_non_stock_invoices(self): has_sabb = False