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