feat: unreconcile on cancellation of bank transaction (#27109)

diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 31cfb2d..0544a46 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -21,6 +21,10 @@
 		self.update_allocations()
 		self.clear_linked_payment_entries()
 		self.set_status(update=True)
+	
+	def on_cancel(self):
+		self.clear_linked_payment_entries(for_cancel=True)
+		self.set_status(update=True)
 
 	def update_allocations(self):
 		if self.payment_entries:
@@ -41,21 +45,30 @@
 			frappe.db.set_value(self.doctype, self.name, "status", "Reconciled")
 
 		self.reload()
-
-	def clear_linked_payment_entries(self):
+	
+	def clear_linked_payment_entries(self, for_cancel=False):
 		for payment_entry in self.payment_entries:
 			if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
-				self.clear_simple_entry(payment_entry)
+				self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
 
 			elif payment_entry.payment_document == "Sales Invoice":
-				self.clear_sales_invoice(payment_entry)
+				self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
 
-	def clear_simple_entry(self, payment_entry):
-		frappe.db.set_value(payment_entry.payment_document, payment_entry.payment_entry, "clearance_date", self.date)
+	def clear_simple_entry(self, payment_entry, for_cancel=False):
+		clearance_date = self.date if not for_cancel else None
+		frappe.db.set_value(
+			payment_entry.payment_document, payment_entry.payment_entry,
+			"clearance_date", clearance_date)
 
-	def clear_sales_invoice(self, payment_entry):
-		frappe.db.set_value("Sales Invoice Payment", dict(parenttype=payment_entry.payment_document,
-			parent=payment_entry.payment_entry), "clearance_date", self.date)
+	def clear_sales_invoice(self, payment_entry, for_cancel=False):
+		clearance_date = self.date if not for_cancel else None
+		frappe.db.set_value(
+			"Sales Invoice Payment",
+			dict(
+				parenttype=payment_entry.payment_document,
+				parent=payment_entry.payment_entry
+			),
+			"clearance_date", clearance_date)
 
 def get_total_allocated_amount(payment_entry):
 	return frappe.db.sql("""
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction_list.js b/erpnext/accounts/doctype/bank_transaction/bank_transaction_list.js
index bff41d5..2585ee9 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction_list.js
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction_list.js
@@ -4,10 +4,12 @@
 frappe.listview_settings['Bank Transaction'] = {
 	add_fields: ["unallocated_amount"],
 	get_indicator: function(doc) {
-		if(flt(doc.unallocated_amount)>0) {
-			return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
+		if(doc.docstatus == 2) {
+			return [__("Cancelled"), "red", "docstatus,=,2"];
 		} else if(flt(doc.unallocated_amount)<=0) {
 			return [__("Reconciled"), "green", "unallocated_amount,=,0"];
+		} else if(flt(doc.unallocated_amount)>0) {
+			return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
 		}
 	}
 };
diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
index ce149f9..439d489 100644
--- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
@@ -25,7 +25,8 @@
 	def tearDownClass(cls):
 		for bt in frappe.get_all("Bank Transaction"):
 			doc = frappe.get_doc("Bank Transaction", bt.name)
-			doc.cancel()
+			if doc.docstatus == 1:
+				doc.cancel()
 			doc.delete()
 
 		# Delete directly in DB to avoid validation errors for countries not allowing deletion
@@ -57,6 +58,12 @@
 		clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
 		self.assertTrue(clearance_date is not None)
 
+		bank_transaction.reload()
+		bank_transaction.cancel()
+
+		clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
+		self.assertFalse(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("Bank Transaction", dict(description="Auszahlung Karte MC/000002916 AUTOMAT 698769 K002 27.10. 14:07"))
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index b1f89b0..7b24e50 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -86,7 +86,8 @@
 	],
 	"Bank Transaction": [
 		["Unreconciled", "eval:self.docstatus == 1 and self.unallocated_amount>0"],
-		["Reconciled", "eval:self.docstatus == 1 and self.unallocated_amount<=0"]
+		["Reconciled", "eval:self.docstatus == 1 and self.unallocated_amount<=0"],
+		["Cancelled", "eval:self.docstatus == 2"]
 	],
 	"POS Opening Entry": [
 		["Draft", None],