feat: fall back to first leaf node when no group is configured + filter group fields
Creating customers/suppliers no longer requires a default Customer/ Supplier Group or Territory on Kapital Bank Settings — when none is set, the first leaf (non-group) node of the tree is used. A configured value is still validated (must exist and be a leaf), with a clear message. Also: the default-group / default-territory Link fields (and the matching mapping child-table fields) now filter to is_group=0 so a group node can't be selected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8d66f2101d
commit
853c01e3e9
|
|
@ -25,6 +25,25 @@ def _api_error_message(resp):
|
|||
return f"HTTP {resp.status_code}: {resp.text[:200]}"
|
||||
|
||||
|
||||
def _resolve_leaf_node(doctype, configured, label):
|
||||
"""Resolve `configured` to a valid leaf node of an NSM tree doctype
|
||||
(Customer Group / Supplier Group / Territory). Empty config falls back to
|
||||
the first leaf node so creation works without a default set.
|
||||
|
||||
Returns (value, error_message). On success error_message is None.
|
||||
"""
|
||||
if configured:
|
||||
if not frappe.db.exists(doctype, configured):
|
||||
return None, f"{label} '{configured}' does not exist."
|
||||
if frappe.db.get_value(doctype, configured, "is_group"):
|
||||
return None, f"{label} '{configured}' is a group node — pick a leaf (non-group) {label}."
|
||||
return configured, None
|
||||
leaf = frappe.db.get_value(doctype, {"is_group": 0}, "name", order_by="lft asc")
|
||||
if not leaf:
|
||||
return None, f"No non-group {label} exists. Create one first."
|
||||
return leaf, None
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# REGISTRY LOADERS (fetch from Kapital Bank → save to local DocTypes)
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
|
@ -658,22 +677,21 @@ def create_unmapped_customers(settings_name=None):
|
|||
if not unmapped:
|
||||
return {"success": True, "created_count": 0, "message": "No unmapped customers in table to create"}
|
||||
|
||||
# Validate config upfront — clearer than ERPNext's errors thrown deep inside
|
||||
# party creation ("Could not find Customer Group" / "Cannot select a Group type").
|
||||
# Resolve group / territory per row upfront — empty config falls back to
|
||||
# the first leaf node, so creation works without a default set, and bad
|
||||
# config surfaces a clear message instead of an ERPNext error mid-create.
|
||||
resolved = []
|
||||
for mapping, _kb_customer in unmapped:
|
||||
group = mapping.customer_group or doc.default_customer_group
|
||||
if not group or not frappe.db.exists("Customer Group", group):
|
||||
return {"success": False, "message": "Set a Default Customer Group on Kapital Bank Settings (or a Customer Group on each customer mapping row) before creating customers."}
|
||||
if frappe.db.get_value("Customer Group", group, "is_group"):
|
||||
return {"success": False, "message": f"Customer Group '{group}' is a group node — pick a leaf (non-group) Customer Group."}
|
||||
territory = mapping.territory or doc.default_territory
|
||||
if not territory or not frappe.db.exists("Territory", territory):
|
||||
return {"success": False, "message": "Set a Default Territory on Kapital Bank Settings (or a Territory on each customer mapping row) before creating customers."}
|
||||
if frappe.db.get_value("Territory", territory, "is_group"):
|
||||
return {"success": False, "message": f"Territory '{territory}' is a group node — pick a leaf (non-group) Territory."}
|
||||
cg, err = _resolve_leaf_node("Customer Group", mapping.customer_group or doc.default_customer_group, "Customer Group")
|
||||
if err:
|
||||
return {"success": False, "message": err}
|
||||
terr, err = _resolve_leaf_node("Territory", mapping.territory or doc.default_territory, "Territory")
|
||||
if err:
|
||||
return {"success": False, "message": err}
|
||||
resolved.append((cg, terr))
|
||||
|
||||
created = 0
|
||||
for mapping, kb_customer in unmapped:
|
||||
for (mapping, kb_customer), (customer_group, territory) in zip(unmapped, resolved):
|
||||
try:
|
||||
customer_name = kb_customer.customer_name
|
||||
if frappe.db.exists("Customer", {"customer_name": customer_name}):
|
||||
|
|
@ -682,8 +700,8 @@ def create_unmapped_customers(settings_name=None):
|
|||
party = frappe.new_doc("Customer")
|
||||
party.customer_name = customer_name
|
||||
party.customer_type = "Company"
|
||||
party.customer_group = mapping.customer_group or doc.default_customer_group
|
||||
party.territory = mapping.territory or doc.default_territory
|
||||
party.customer_group = customer_group
|
||||
party.territory = territory
|
||||
|
||||
if kb_customer.tax_id:
|
||||
party.tax_id = kb_customer.tax_id
|
||||
|
|
@ -739,15 +757,15 @@ def create_unmapped_suppliers(settings_name=None):
|
|||
if not unmapped:
|
||||
return {"success": True, "created_count": 0, "message": "No unmapped suppliers in table to create"}
|
||||
|
||||
resolved = []
|
||||
for mapping, _kb_supplier in unmapped:
|
||||
group = mapping.supplier_group or doc.default_supplier_group
|
||||
if not group or not frappe.db.exists("Supplier Group", group):
|
||||
return {"success": False, "message": "Set a Default Supplier Group on Kapital Bank Settings (or a Supplier Group on each supplier mapping row) before creating suppliers."}
|
||||
if frappe.db.get_value("Supplier Group", group, "is_group"):
|
||||
return {"success": False, "message": f"Supplier Group '{group}' is a group node — pick a leaf (non-group) Supplier Group."}
|
||||
sg, err = _resolve_leaf_node("Supplier Group", mapping.supplier_group or doc.default_supplier_group, "Supplier Group")
|
||||
if err:
|
||||
return {"success": False, "message": err}
|
||||
resolved.append(sg)
|
||||
|
||||
created = 0
|
||||
for mapping, kb_supplier in unmapped:
|
||||
for (mapping, kb_supplier), supplier_group in zip(unmapped, resolved):
|
||||
try:
|
||||
supplier_name = kb_supplier.supplier_name
|
||||
if frappe.db.exists("Supplier", {"supplier_name": supplier_name}):
|
||||
|
|
@ -756,7 +774,7 @@ def create_unmapped_suppliers(settings_name=None):
|
|||
party = frappe.new_doc("Supplier")
|
||||
party.supplier_name = supplier_name
|
||||
party.supplier_type = "Company"
|
||||
party.supplier_group = mapping.supplier_group or doc.default_supplier_group
|
||||
party.supplier_group = supplier_group
|
||||
|
||||
if kb_supplier.tax_id:
|
||||
party.tax_id = kb_supplier.tax_id
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
frappe.ui.form.on('Kapital Bank Settings', {
|
||||
setup(frm) {
|
||||
// Customer/Supplier Group and Territory must be leaf (non-group) nodes.
|
||||
const leaf = () => ({ filters: { is_group: 0 } });
|
||||
frm.set_query('default_customer_group', leaf);
|
||||
frm.set_query('default_supplier_group', leaf);
|
||||
frm.set_query('default_territory', leaf);
|
||||
frm.set_query('customer_group', 'customer_mappings', leaf);
|
||||
frm.set_query('territory', 'customer_mappings', leaf);
|
||||
frm.set_query('supplier_group', 'supplier_mappings', leaf);
|
||||
},
|
||||
|
||||
refresh(frm) {
|
||||
// ── Main: Load Data from Kapital Bank ────────────────────────────────
|
||||
frm.add_custom_button(__('Load Data'), () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue