From 5f440c1b66e4c6052e1dc5f985fa11a575057ae4 Mon Sep 17 00:00:00 2001 From: Ali <010109ali@gmail.com> Date: Wed, 11 Mar 2026 18:38:46 +0400 Subject: [PATCH] changed the way that check works in brt --- .../client/bank_reconciliation_tool.js | 35 ++++++---- kapital_bank/mapping.py | 67 +++++++++++++++---- 2 files changed, 74 insertions(+), 28 deletions(-) diff --git a/kapital_bank/client/bank_reconciliation_tool.js b/kapital_bank/client/bank_reconciliation_tool.js index fbc120b..3115ac1 100644 --- a/kapital_bank/client/bank_reconciliation_tool.js +++ b/kapital_bank/client/bank_reconciliation_tool.js @@ -191,13 +191,12 @@ const KBBRTMapping = { reqd: 1, }, { - fieldname: "use_custom_purpose", + fieldname: "use_original_purpose", fieldtype: "Check", - label: __("Use custom purpose keyword"), + label: __("Use original description"), onchange: function () { - const on = d.get_value("use_custom_purpose"); - d.set_df_property("custom_purpose", "hidden", on ? 0 : 1); - d.set_df_property("custom_purpose", "reqd", on ? 1 : 0); + const on = d.get_value("use_original_purpose"); + d.set_df_property("custom_purpose", "hidden", on ? 1 : 0); d.get_field("custom_purpose").refresh(); }, }, @@ -205,8 +204,8 @@ const KBBRTMapping = { fieldname: "custom_purpose", fieldtype: "Data", label: __("Custom Purpose Keyword"), - hidden: 1, - description: __("All selected rows will be mapped with this purpose instead of their own description"), + hidden: 0, + description: __("Leave empty to map by party only. All rows will use this keyword instead of their own description."), }, { fieldname: "sec_accounts", fieldtype: "Section Break", label: __("GL Accounts") }, { @@ -225,9 +224,21 @@ const KBBRTMapping = { if (!values) return; let finalTxns = txns.slice(); - if (values.use_custom_purpose && (values.custom_purpose || "").trim()) { - const cp = values.custom_purpose.trim(); - finalTxns = txns.map(t => Object.assign({}, t, { purpose: cp })); + if (!values.use_original_purpose) { + const cp = (values.custom_purpose || "").trim(); + if (cp) { + finalTxns = txns.map(t => Object.assign({}, t, { purpose: cp })); + } else { + finalTxns = txns.map(t => Object.assign({}, t, { purpose: "" })); + if (finalTxns.every(t => !t.party)) { + frappe.msgprint({ + title: __("Validation Error"), + indicator: "red", + message: __("Either a purpose keyword or a party is required."), + }); + return; + } + } } KBBRTMapping.submitMappings(d, finalTxns, values.paid_from, values.paid_to, values.document_type, values.mode); @@ -241,11 +252,7 @@ const KBBRTMapping = { const $fi = $(`.${dtm._kb_scopeClass} .dt-row-filter input.dt-filter[data-name="Description"]`); const filterVal = ($fi.val() || "").trim(); if (filterVal) { - d.set_df_property("custom_purpose", "hidden", 0); - d.set_df_property("custom_purpose", "reqd", 1); - d.set_value("use_custom_purpose", 1); d.set_value("custom_purpose", filterVal); - d.get_field("custom_purpose").refresh(); } }, diff --git a/kapital_bank/mapping.py b/kapital_bank/mapping.py index bbb6328..39de095 100644 --- a/kapital_bank/mapping.py +++ b/kapital_bank/mapping.py @@ -21,35 +21,57 @@ def create_purpose_mappings(transactions, paid_from, paid_to, document_type="Pay if do_mappings: settings = frappe.get_single("Kapital Bank Settings") - existing = { + existing_purpose = { (row.purpose_keyword, row.payment_type) for row in settings.transaction_mappings if row.purpose_keyword and row.payment_type } + existing_party_only = { + (row.counterparty_type or "", row.counterparty or "", row.payment_type) + for row in settings.transaction_mappings + if not row.purpose_keyword and row.counterparty and row.payment_type + } # Deduplicate within batch; first occurrence wins for party info unique_purposes = {} + unique_parties = {} for txn in txn_list: purpose = (txn.get("purpose") or "").strip() - if not purpose: + party_type = (txn.get("party_type") or "").strip() + party = (txn.get("party") or "").strip() + payment_type = "Pay" if txn.get("drcr") == "D" else "Receive" + + if not purpose and not party: skipped_no_data += 1 continue - payment_type = "Pay" if txn.get("drcr") == "D" else "Receive" - key = (purpose, payment_type) - if key not in unique_purposes: - unique_purposes[key] = { - "count": 0, - # party_type is already "Customer"/"Supplier" from ERPNext BRT - "counterparty_type": (txn.get("party_type") or "").strip(), - "counterparty": (txn.get("party") or "").strip(), - } - unique_purposes[key]["count"] += 1 + + if purpose: + key = (purpose, payment_type) + if key not in unique_purposes: + unique_purposes[key] = { + "count": 0, + # party_type is already "Customer"/"Supplier" from ERPNext BRT + "counterparty_type": party_type, + "counterparty": party, + } + unique_purposes[key]["count"] += 1 + else: + # Party-only mapping (no purpose) + key = (party_type, party, payment_type) + if key not in unique_parties: + unique_parties[key] = { + "count": 0, + "counterparty_type": party_type, + "counterparty": party, + "payment_type": payment_type, + } + unique_parties[key]["count"] += 1 for (purpose_text, payment_type), data in unique_purposes.items(): purpose_name = _ensure_purpose(purpose_text) - if (purpose_name, payment_type) in existing: + if (purpose_name, payment_type) in existing_purpose: already_mapped += 1 continue @@ -62,7 +84,24 @@ def create_purpose_mappings(transactions, paid_from, paid_to, document_type="Pay "counterparty_type": data["counterparty_type"] or None, "counterparty": data["counterparty"] or None, }) - existing.add((purpose_name, payment_type)) + existing_purpose.add((purpose_name, payment_type)) + created_mappings += 1 + + for (party_type_k, party_k, payment_type), data in unique_parties.items(): + if (party_type_k, party_k, payment_type) in existing_party_only: + already_mapped += 1 + continue + + settings.append("transaction_mappings", { + "purpose_keyword": None, + "payment_type": payment_type, + "paid_from": paid_from, + "paid_to": paid_to, + "document_type": document_type, + "counterparty_type": data["counterparty_type"] or None, + "counterparty": data["counterparty"] or None, + }) + existing_party_only.add((party_type_k, party_k, payment_type)) created_mappings += 1 if created_mappings > 0: