added mapping without party
This commit is contained in:
parent
7ced7d18a5
commit
fc34e5104b
|
|
@ -1442,7 +1442,7 @@ def _build_import_lookups(settings):
|
|||
for row in settings.transaction_mappings:
|
||||
if not row.paid_from or not row.paid_to:
|
||||
continue
|
||||
if not row.purpose_keyword and not row.counterparty:
|
||||
if not row.purpose_keyword and not row.counterparty and not row.counterparty_type:
|
||||
continue
|
||||
|
||||
keyword_lower = ""
|
||||
|
|
@ -1468,8 +1468,10 @@ def _build_import_lookups(settings):
|
|||
getattr(row, "payment_type", None) or "",
|
||||
cp_name,
|
||||
cp_voen,
|
||||
getattr(row, "counterparty_type", None) or "",
|
||||
getattr(row, "document_type", None) or "Payment Entry",
|
||||
getattr(row, "cost_center", None) or "",
|
||||
bool(getattr(row, "multi_currency", 0)),
|
||||
))
|
||||
|
||||
# Each key maps to a dict with optional "Customer" and "Supplier" entries.
|
||||
|
|
@ -1523,8 +1525,9 @@ def _import_one_transaction(txn_data, settings, purpose_rules, purpose_threshold
|
|||
both_rules = []
|
||||
purpose_only_rules = []
|
||||
counterparty_only_rules = []
|
||||
fallback_rules = []
|
||||
for rule in purpose_rules:
|
||||
keyword, pf, pt, rule_pt, cp_name, cp_voen, doc_type, rule_cc = rule
|
||||
keyword, pf, pt, rule_pt, cp_name, cp_voen, cp_type, doc_type, rule_cc, rule_mc = rule
|
||||
has_keyword = bool(keyword)
|
||||
has_cp = bool(cp_name or cp_voen)
|
||||
if has_keyword and has_cp:
|
||||
|
|
@ -1533,6 +1536,8 @@ def _import_one_transaction(txn_data, settings, purpose_rules, purpose_threshold
|
|||
purpose_only_rules.append(rule)
|
||||
elif has_cp:
|
||||
counterparty_only_rules.append(rule)
|
||||
elif cp_type:
|
||||
fallback_rules.append(rule)
|
||||
|
||||
def _counterparty_matches(cp_name, cp_voen):
|
||||
if cp_voen and contr_voen and cp_voen == contr_voen:
|
||||
|
|
@ -1543,45 +1548,63 @@ def _import_one_transaction(txn_data, settings, purpose_rules, purpose_threshold
|
|||
|
||||
def _match_purpose_rules(rules, check_counterparty):
|
||||
best_score = 0
|
||||
best_pf = best_pt = best_doc_type = best_cc = None
|
||||
for keyword, pf, pt, rule_pt, cp_name, cp_voen, doc_type, rule_cc in rules:
|
||||
best_pf = best_pt = best_doc_type = best_cc = best_mc = None
|
||||
for keyword, pf, pt, rule_pt, cp_name, cp_voen, cp_type, doc_type, rule_cc, rule_mc in rules:
|
||||
if rule_pt and rule_pt != payment_type:
|
||||
continue
|
||||
if check_counterparty and not _counterparty_matches(cp_name, cp_voen):
|
||||
continue
|
||||
if keyword:
|
||||
if keyword in purpose_lower:
|
||||
return pf, pt, doc_type, rule_cc
|
||||
return pf, pt, doc_type, rule_cc, rule_mc
|
||||
score = SequenceMatcher(None, purpose_lower, keyword).ratio()
|
||||
if score > best_score and score >= purpose_threshold:
|
||||
best_score = score
|
||||
best_pf, best_pt, best_doc_type, best_cc = pf, pt, doc_type, rule_cc
|
||||
best_pf, best_pt, best_doc_type, best_cc, best_mc = pf, pt, doc_type, rule_cc, rule_mc
|
||||
else:
|
||||
return pf, pt, doc_type, rule_cc
|
||||
return best_pf, best_pt, best_doc_type, best_cc
|
||||
return pf, pt, doc_type, rule_cc, rule_mc
|
||||
return best_pf, best_pt, best_doc_type, best_cc, best_mc
|
||||
|
||||
doc_type = "Payment Entry"
|
||||
cost_center = ""
|
||||
multi_currency = False
|
||||
|
||||
# Phase 1: rules with BOTH purpose keyword AND counterparty
|
||||
paid_from, paid_to, matched_doc_type, matched_cc = _match_purpose_rules(both_rules, check_counterparty=True)
|
||||
paid_from, paid_to, matched_doc_type, matched_cc, matched_mc = _match_purpose_rules(both_rules, check_counterparty=True)
|
||||
if matched_doc_type:
|
||||
doc_type = matched_doc_type
|
||||
cost_center = matched_cc or ""
|
||||
multi_currency = matched_mc or False
|
||||
|
||||
# Phase 2: rules with only purpose keyword
|
||||
if not paid_from or not paid_to:
|
||||
paid_from, paid_to, matched_doc_type, matched_cc = _match_purpose_rules(purpose_only_rules, check_counterparty=False)
|
||||
paid_from, paid_to, matched_doc_type, matched_cc, matched_mc = _match_purpose_rules(purpose_only_rules, check_counterparty=False)
|
||||
if matched_doc_type:
|
||||
doc_type = matched_doc_type
|
||||
cost_center = matched_cc or ""
|
||||
multi_currency = matched_mc or False
|
||||
|
||||
# Phase 3: rules with only counterparty
|
||||
if not paid_from or not paid_to:
|
||||
paid_from, paid_to, matched_doc_type, matched_cc = _match_purpose_rules(counterparty_only_rules, check_counterparty=True)
|
||||
paid_from, paid_to, matched_doc_type, matched_cc, matched_mc = _match_purpose_rules(counterparty_only_rules, check_counterparty=True)
|
||||
if matched_doc_type:
|
||||
doc_type = matched_doc_type
|
||||
cost_center = matched_cc or ""
|
||||
multi_currency = matched_mc or False
|
||||
|
||||
# Phase 4: fallback rules — counterparty_type only, no specific counterparty
|
||||
if not paid_from or not paid_to:
|
||||
inferred_cp_type = "Customer" if payment_type == "Receive" else "Supplier"
|
||||
for keyword, pf, pt, rule_pt, cp_name, cp_voen, cp_type, doc_type, rule_cc, rule_mc in fallback_rules:
|
||||
if rule_pt and rule_pt != payment_type:
|
||||
continue
|
||||
if cp_type and cp_type != inferred_cp_type:
|
||||
continue
|
||||
paid_from, paid_to = pf, pt
|
||||
doc_type = doc_type
|
||||
cost_center = rule_cc or ""
|
||||
multi_currency = rule_mc or False
|
||||
break
|
||||
|
||||
if not paid_from or not paid_to:
|
||||
return {
|
||||
|
|
@ -1633,6 +1656,8 @@ def _import_one_transaction(txn_data, settings, purpose_rules, purpose_threshold
|
|||
je.cheque_no = ref_no
|
||||
je.cheque_date = parsed_date
|
||||
je.user_remark = purpose
|
||||
if multi_currency:
|
||||
je.multi_currency = 1
|
||||
|
||||
# Party can only be set on Receivable/Payable accounts
|
||||
party_accounts = {"Receivable", "Payable"}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"paid_from",
|
||||
"paid_to",
|
||||
"cost_center",
|
||||
"multi_currency",
|
||||
"notes"
|
||||
],
|
||||
"fields": [
|
||||
|
|
@ -77,6 +78,13 @@
|
|||
"label": "Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "multi_currency",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Multi Currency"
|
||||
},
|
||||
{
|
||||
"fieldname": "notes",
|
||||
"fieldtype": "Data",
|
||||
|
|
@ -86,7 +94,7 @@
|
|||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-03-10 17:54:47.738883",
|
||||
"modified": "2026-03-12 16:52:06.237239",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Kapital Bank",
|
||||
"name": "Kapital Bank Transaction Mapping",
|
||||
|
|
|
|||
|
|
@ -203,6 +203,7 @@ def _find_mapping_for_txn(txn, transaction_mappings, purpose_text_cache):
|
|||
both_rules = []
|
||||
purpose_only_rules = []
|
||||
counterparty_only_rules = []
|
||||
fallback_rules = []
|
||||
|
||||
for row in transaction_mappings:
|
||||
if not row.paid_from or not row.paid_to:
|
||||
|
|
@ -219,6 +220,8 @@ def _find_mapping_for_txn(txn, transaction_mappings, purpose_text_cache):
|
|||
purpose_only_rules.append(row)
|
||||
elif has_counterparty:
|
||||
counterparty_only_rules.append(row)
|
||||
elif row.counterparty_type:
|
||||
fallback_rules.append(row)
|
||||
|
||||
def _purpose_matches(row):
|
||||
keyword_text = purpose_text_cache.get(row.purpose_keyword, "")
|
||||
|
|
@ -239,6 +242,12 @@ def _find_mapping_for_txn(txn, transaction_mappings, purpose_text_cache):
|
|||
if _counterparty_matches(row):
|
||||
return row
|
||||
|
||||
# Phase 4: fallback by counterparty_type
|
||||
inferred_cp_type = "Customer" if payment_type == "Receive" else "Supplier"
|
||||
for row in fallback_rules:
|
||||
if row.counterparty_type == inferred_cp_type:
|
||||
return row
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue