diff --git a/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.js b/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.js index d11d8040b2..b13e46a0e7 100644 --- a/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.js +++ b/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.js @@ -1,8 +1,10 @@ // Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -// frappe.ui.form.on("Bank Party Mapper", { -// refresh(frm) { - -// }, -// }); +frappe.ui.form.on("Bank Party Mapper", { + refresh(frm) { + if (!frm.is_new()) { + frm.set_intro(__("Please avoid editing unless you are absolutely certain.")); + } + }, +}); diff --git a/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.json b/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.json index 4f5f6bfa88..ddc79f24a0 100644 --- a/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.json +++ b/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.json @@ -9,7 +9,7 @@ "party_type", "party", "column_break_wbna", - "bank_party_name_desc", + "bank_party_name", "bank_party_account_number", "bank_party_iban" ], @@ -47,14 +47,14 @@ "options": "party_type" }, { - "fieldname": "bank_party_name_desc", - "fieldtype": "Small Text", - "label": "Party Name/Desc (Bank Statement)" + "fieldname": "bank_party_name", + "fieldtype": "Data", + "label": "Party Name (Bank Statement)" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2023-04-03 10:11:31.384383", + "modified": "2023-04-04 14:27:23.450456", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Party Mapper", diff --git a/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.py b/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.py index d3a9a5e586..02e36b08fe 100644 --- a/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.py +++ b/erpnext/accounts/doctype/bank_party_mapper/bank_party_mapper.py @@ -1,9 +1,24 @@ # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -# import frappe +import frappe from frappe.model.document import Document class BankPartyMapper(Document): - pass + def on_update(self): + self.update_party_in_linked_transactions() + + def update_party_in_linked_transactions(self): + if self.is_new(): + return + + # Set updated party values in other linked bank transactions + bank_transaction = frappe.qb.DocType("Bank Transaction") + + frappe.qb.update(bank_transaction).set("party_type", self.party_type).set( + "party", self.party + ).where( + (bank_transaction.bank_party_mapper == self.name) + & ((bank_transaction.party_type != self.party_type) | (bank_transaction.party != self.party)) + ).run() diff --git a/erpnext/accounts/doctype/bank_transaction/auto_match_party.py b/erpnext/accounts/doctype/bank_transaction/auto_match_party.py index 3fbdc5f36b..9707f79a2a 100644 --- a/erpnext/accounts/doctype/bank_transaction/auto_match_party.py +++ b/erpnext/accounts/doctype/bank_transaction/auto_match_party.py @@ -49,11 +49,11 @@ class AutoMatchbyAccountIBAN: result = frappe.db.get_value( "Bank Party Mapper", filters={filter_field: self.get(filter_field)}, - fieldname=["party_type", "party"], + fieldname=["party_type", "party", "name"], ) if result: - party_type, party = result - return (party_type, party, None) + party_type, party, mapper_name = result + return (party_type, party, {"mapper_name": mapper_name}) return result @@ -89,33 +89,29 @@ class AutoMatchbyPartyDescription: def match(self): # Match by Customer, Supplier or Employee Name - # search bank party mapper by party and then description + # search bank party mapper by party # fuzzy search by customer/supplier & employee if not (self.bank_party_name or self.description): return None - result = self.match_party_name_desc_in_bank_party_mapper() + result = self.match_party_name_in_bank_party_mapper() if not result: result = self.match_party_name_desc_in_party() return result - def match_party_name_desc_in_bank_party_mapper(self): - """Check if match exists for party name or description in Bank Party Mapper""" + def match_party_name_in_bank_party_mapper(self): + """Check if match exists for party name in Bank Party Mapper""" result = None - or_filters = [] - if self.bank_party_name: - or_filters.append({"bank_party_name_desc": self.bank_party_name}) - - if self.description: - or_filters.append({"bank_party_name_desc": self.description}) + if not self.bank_party_name: + return mapper_res = frappe.get_all( "Bank Party Mapper", - or_filters=or_filters, - fields=["party_type", "party"], + filters={"bank_party_name": self.bank_party_name}, + fields=["party_type", "party", "name"], limit_page_length=1, ) if mapper_res: @@ -123,7 +119,7 @@ class AutoMatchbyPartyDescription: result = ( mapper_res["party_type"], mapper_res["party"], - None, + {"mapper_name": mapper_res["name"]}, ) return result @@ -157,7 +153,7 @@ class AutoMatchbyPartyDescription: party_name, score, index = result if score > 75: # Dont set description as a key in Bank Party Mapper due to its volatility - mapper = {"bank_party_name_desc": self.get(field)} if field == "bank_party_name" else None + mapper = {"bank_party_name": self.get(field)} if field == "bank_party_name" else None return ( party, party_name, diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json index 4139a9f6d5..d3dc5b5845 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json @@ -37,7 +37,8 @@ "column_break_3czf", "bank_party_name", "bank_party_account_number", - "bank_party_iban" + "bank_party_iban", + "bank_party_mapper" ], "fields": [ { @@ -214,7 +215,7 @@ { "fieldname": "bank_party_name", "fieldtype": "Data", - "label": "Party Name (Bank Statement)" + "label": "Party Name/Account Holder (Bank Statement)" }, { "fieldname": "bank_party_iban", @@ -225,11 +226,19 @@ "fieldname": "bank_party_account_number", "fieldtype": "Data", "label": "Party Account No. (Bank Statement)" + }, + { + "fieldname": "bank_party_mapper", + "fieldtype": "Link", + "hidden": 1, + "label": "Bank Party Mapper", + "options": "Bank Party Mapper", + "read_only": 1 } ], "is_submittable": 1, "links": [], - "modified": "2023-03-31 10:45:30.671309", + "modified": "2023-04-04 15:47:20.620006", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Transaction", diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 118705d0d3..a93882a5b3 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -35,6 +35,8 @@ class BankTransaction(StatusUpdater): self.update_allocations() self._saving_flag = False + self.set_in_bank_party_mapper() + def on_cancel(self): self.clear_linked_payment_entries(for_cancel=True) self.set_status(update=True) @@ -176,11 +178,28 @@ class BankTransaction(StatusUpdater): if not mapper: return + if mapper.get("mapper_name"): + # Transaction matched with a Bank party Mapper record + self.bank_party_mapper = mapper.get("mapper_name") # Link mapper to Bank Transaction + return + mapper_doc = frappe.get_doc( {"doctype": "Bank Party Mapper", "party_type": self.party_type, "party": self.party} ) mapper_doc.update(mapper) mapper_doc.insert() + self.bank_party_mapper = mapper_doc.name # Link mapper to Bank Transaction + + def set_in_bank_party_mapper(self): + """Set in Bank Party Mapper if Party Type & Party are manually changed after submit.""" + doc_before_update = self.get_doc_before_save() + party_type_changed = self.party_type and (doc_before_update.party_type != self.party_type) + party_changed = self.party and (doc_before_update.party != self.party) + + if (party_type_changed or party_changed) and self.bank_party_mapper: + mapper_doc = frappe.get_doc("Bank Party Mapper", self.bank_party_mapper) + mapper_doc.update({"party_type": self.party_type, "party": self.party}) + mapper_doc.save() @frappe.whitelist()