test: Match by Account No, IBAN, Party Name, Desc and match correction
diff --git a/erpnext/accounts/doctype/bank_transaction/test_auto_match_party.py b/erpnext/accounts/doctype/bank_transaction/test_auto_match_party.py
new file mode 100644
index 0000000..86181c8
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_transaction/test_auto_match_party.py
@@ -0,0 +1,193 @@
+# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+from frappe.tests.utils import FrappeTestCase
+from frappe.utils import nowdate
+
+from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account
+
+
+class TestAutoMatchParty(FrappeTestCase):
+	@classmethod
+	def setUpClass(cls):
+		create_bank_account()
+		frappe.db.set_single_value("Accounts Settings", "enable_party_matching", 1)
+		return super().setUpClass()
+
+	@classmethod
+	def tearDownClass(cls):
+		frappe.db.set_single_value("Accounts Settings", "enable_party_matching", 0)
+
+	def test_match_by_account_number(self):
+		"""Test if transaction matches with existing (Bank Party Mapper) or new match."""
+		create_supplier_for_match(account_no="000000003716541159")
+		doc = create_bank_transaction(
+			withdrawal=1200,
+			transaction_id="562213b0ca1bf838dab8f2c6a39bbc3b",
+			account_no="000000003716541159",
+			iban="DE02000000003716541159",
+		)
+
+		self.assertEqual(doc.party_type, "Supplier")
+		self.assertEqual(doc.party, "John Doe & Co.")
+		self.assertTrue(doc.bank_party_mapper)
+
+		# Check if Bank Party Mapper is created to remember mapping
+		bank_party_mapper = frappe.get_doc("Bank Party Mapper", doc.bank_party_mapper)
+		self.assertEqual(bank_party_mapper.party, "John Doe & Co.")
+		self.assertEqual(bank_party_mapper.bank_party_account_number, "000000003716541159")
+		self.assertEqual(bank_party_mapper.bank_party_iban, "DE02000000003716541159")
+
+		# Check if created mapping is used for quick match
+		doc_2 = create_bank_transaction(
+			withdrawal=500,
+			transaction_id="602413b8ji8bf838fub8f2c6a39bah7y",
+			account_no="000000003716541159",
+		)
+		self.assertEqual(doc_2.party, "John Doe & Co.")
+		self.assertEqual(doc_2.bank_party_mapper, bank_party_mapper.name)
+
+	def test_match_by_iban(self):
+		create_supplier_for_match(iban="DE02000000003716541159")
+		doc = create_bank_transaction(
+			withdrawal=1200,
+			transaction_id="c5455a224602afaa51592a9d9250600d",
+			account_no="000000003716541159",
+			iban="DE02000000003716541159",
+		)
+
+		self.assertEqual(doc.party_type, "Supplier")
+		self.assertEqual(doc.party, "John Doe & Co.")
+		self.assertTrue(doc.bank_party_mapper)
+
+		bank_party_mapper = frappe.get_doc("Bank Party Mapper", doc.bank_party_mapper)
+		self.assertEqual(bank_party_mapper.party, "John Doe & Co.")
+		self.assertEqual(bank_party_mapper.bank_party_account_number, "000000003716541159")
+		self.assertEqual(bank_party_mapper.bank_party_iban, "DE02000000003716541159")
+
+	def test_match_by_party_name(self):
+		create_supplier_for_match(supplier_name="Jackson Ella W.")
+		doc = create_bank_transaction(
+			withdrawal=1200,
+			transaction_id="1f6f661f347ff7b1ea588665f473adb1",
+			party_name="Ella Jackson",
+			iban="DE04000000003716545346",
+		)
+		self.assertEqual(doc.party_type, "Supplier")
+		self.assertEqual(doc.party, "Jackson Ella W.")
+		self.assertTrue(doc.bank_party_mapper)
+
+		bank_party_mapper = frappe.get_doc("Bank Party Mapper", doc.bank_party_mapper)
+		self.assertEqual(bank_party_mapper.party, "Jackson Ella W.")
+		self.assertEqual(bank_party_mapper.bank_party_name, "Ella Jackson")
+		self.assertEqual(bank_party_mapper.bank_party_iban, None)
+
+		# Check if created mapping is used for quick match
+		doc_2 = create_bank_transaction(
+			withdrawal=500,
+			transaction_id="578313b8ji8bf838fub8f2c6a39bah7y",
+			party_name="Ella Jackson",
+			account_no="000000004316531152",
+		)
+		self.assertEqual(doc_2.party, "Jackson Ella W.")
+		self.assertEqual(doc_2.bank_party_mapper, bank_party_mapper.name)
+
+	def test_match_by_description(self):
+		create_supplier_for_match(supplier_name="Microsoft")
+		doc = create_bank_transaction(
+			description="Auftraggeber: microsoft payments Buchungstext: msft ..e3006b5hdy. ref. j375979555927627/5536",
+			withdrawal=1200,
+			transaction_id="8df880a2d09c3bed3fea358ca5168c5a",
+			party_name="",
+		)
+		self.assertEqual(doc.party_type, "Supplier")
+		self.assertEqual(doc.party, "Microsoft")
+		self.assertFalse(doc.bank_party_mapper)
+
+	def test_correct_match_after_submit(self):
+		"""Correct wrong mapping after submit. Test impact."""
+		# Similar named suppliers
+		create_supplier_for_match(supplier_name="Amazon")
+		create_supplier_for_match(supplier_name="Amazing Co.")
+
+		# Bank Transactions actually from "Amazon" that match better with "Amazing Co."
+		doc = create_bank_transaction(
+			description="visa06323202 amzn.com/bill 7,88eur1,5324711959 90.22. 1,62 87861003",
+			withdrawal=24.85,
+			transaction_id="3a1da4ee2dc5a980138d36ef5297cbd9",
+			party_name="Amazn Co.",
+		)
+		doc_2 = create_bank_transaction(
+			description="visa61268005 amzn.com/bill 22,345eur1,7654711959 89.23. 1,64 61268005",
+			withdrawal=80,
+			transaction_id="584314e459b00f792bfd569267efba6e",
+			party_name="Amazn Co.",
+		)
+
+		self.assertEqual(doc.party_type, "Supplier")
+		self.assertEqual(doc.party, "Amazing Co.")
+		self.assertTrue(doc.bank_party_mapper)
+		self.assertTrue(doc_2.bank_party_mapper, doc.bank_party_mapper)
+
+		bank_party_mapper = frappe.get_doc("Bank Party Mapper", doc.bank_party_mapper)
+		self.assertEqual(bank_party_mapper.party, "Amazing Co.")
+		self.assertEqual(bank_party_mapper.bank_party_name, "Amazn Co.")
+
+		# User corrects the value after submit to "Amazon"
+		doc.party = "Amazon"
+		doc.save()
+		bank_party_mapper.reload()
+		doc_2.reload()
+
+		# Mapping is edited and all transactions with this mapping are updated
+		self.assertEqual(bank_party_mapper.party, "Amazon")
+		self.assertEqual(bank_party_mapper.bank_party_name, "Amazn Co.")
+		self.assertEqual(doc_2.party, "Amazon")
+
+
+def create_supplier_for_match(supplier_name="John Doe & Co.", account_no=None, iban=None):
+	if frappe.db.exists("Supplier", supplier_name):
+		frappe.db.set_value("Supplier", supplier_name, {"bank_account_no": account_no, "iban": iban})
+		return
+
+	frappe.get_doc(
+		{
+			"doctype": "Supplier",
+			"supplier_name": supplier_name,
+			"supplier_group": "Services",
+			"supplier_type": "Company",
+			"bank_account_no": account_no,
+			"iban": iban,
+		}
+	).insert()
+
+
+def create_bank_transaction(
+	description=None,
+	withdrawal=0,
+	deposit=0,
+	transaction_id=None,
+	party_name=None,
+	account_no=None,
+	iban=None,
+):
+	doc = frappe.get_doc(
+		{
+			"doctype": "Bank Transaction",
+			"description": description or "1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G",
+			"date": nowdate(),
+			"withdrawal": withdrawal,
+			"deposit": deposit,
+			"currency": "INR",
+			"bank_account": "Checking Account - Citi Bank",
+			"transaction_id": transaction_id,
+			"bank_party_name": party_name,
+			"bank_party_account_number": account_no,
+			"bank_party_iban": iban,
+		}
+	).insert()
+	doc.submit()
+	doc.reload()
+
+	return doc