From de354bc1168b9e93ff51920a9a6f8a9bd4972a4d Mon Sep 17 00:00:00 2001 From: Sendipad Date: Fri, 6 Mar 2026 00:54:48 +0300 Subject: [PATCH 1/3] Add Party Master defaults for dimensions --- uph/party/controllers/party.py | 3 +++ .../doctype/party_master/party_master.json | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/uph/party/controllers/party.py b/uph/party/controllers/party.py index 35508d6e..d6f3bc72 100644 --- a/uph/party/controllers/party.py +++ b/uph/party/controllers/party.py @@ -868,6 +868,9 @@ def _pm_default_contact(doctype, name): "territory": "territory", "default_currency": "currency", "tax_category": "tax_category", + "default_cost_center": "cost_center", + "default_project": "project", + "default_party_analytic_accounting": "party_analytic_accounting", } if party_type == "Customer": diff --git a/uph/party/doctype/party_master/party_master.json b/uph/party/doctype/party_master/party_master.json index e42e8ca1..ec69f168 100644 --- a/uph/party/doctype/party_master/party_master.json +++ b/uph/party/doctype/party_master/party_master.json @@ -74,6 +74,8 @@ "default_currency", "default_price_list", "payment_terms", + "default_cost_center", + "default_project", "section_break_internal_accounting", "is_internal_party", "represents_company", @@ -96,6 +98,7 @@ "market_segment", "section_break_analytics", "enforce_party_analaytic_accounting_selection", + "default_party_analytic_accounting", "dashboard_tab", "portal_users", "section_break_system_logs", @@ -554,6 +557,18 @@ "label": "Default Payment Terms Template", "options": "Payment Terms Template" }, + { + "fieldname": "default_cost_center", + "fieldtype": "Link", + "label": "Default Cost Center", + "options": "Cost Center" + }, + { + "fieldname": "default_project", + "fieldtype": "Link", + "label": "Default Project", + "options": "Project" + }, { "fieldname": "section_break_internal_accounting", "fieldtype": "Section Break", @@ -693,6 +708,12 @@ "fieldtype": "Check", "label": "Enforce Party Analaytic Accounting Selection" }, + { + "fieldname": "default_party_analytic_accounting", + "fieldtype": "Link", + "label": "Default Party Analytic Accounting", + "options": "Party Analytic Accounting" + }, { "fieldname": "portal_users_tab", "fieldtype": "Tab Break", From de23e70dd191b9a51079cb705ed8058431ce1488 Mon Sep 17 00:00:00 2001 From: Sendipad Date: Fri, 6 Mar 2026 01:14:08 +0300 Subject: [PATCH 2/3] Apply party master defaults in child rows --- uph/party/controllers/party.py | 30 ++++++++++++++++ uph/public/js/utils/party.js | 64 ++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/uph/party/controllers/party.py b/uph/party/controllers/party.py index d6f3bc72..820e4d7b 100644 --- a/uph/party/controllers/party.py +++ b/uph/party/controllers/party.py @@ -682,6 +682,36 @@ def get_party_master_details_with_parties(party_master, party_type=None): return {"party_master": pm_doc, "parties": parties} +@frappe.whitelist() +def get_party_master_defaults(party_type=None, party=None, party_master=None): + """Return Party Master defaults mapped to transactional fields.""" + if not party_master and party_type and party: + party_master = frappe.db.get_value(party_type, party, "party_master") + + if not party_master or not frappe.db.exists("Party Master", party_master): + return {} + + defaults = frappe.db.get_value( + "Party Master", + party_master, + ["default_cost_center", "default_project", "default_party_analytic_accounting"], + as_dict=1, + ) + + if not defaults: + return {} + + out = {} + if defaults.get("default_cost_center"): + out["cost_center"] = defaults["default_cost_center"] + if defaults.get("default_project"): + out["project"] = defaults["default_project"] + if defaults.get("default_party_analytic_accounting"): + out["party_analytic_accounting"] = defaults["default_party_analytic_accounting"] + + return out + + @frappe.whitelist() def allow_duplicate_submission(doctype, docname): settings = frappe.get_cached_doc("Party Master Settings") diff --git a/uph/public/js/utils/party.js b/uph/public/js/utils/party.js index 578019ca..6cc3ab1f 100644 --- a/uph/public/js/utils/party.js +++ b/uph/public/js/utils/party.js @@ -372,16 +372,66 @@ uph.party = { // Child table handler for party field change on_party_field_change_in_child: function (frm, row) { - if (row.party_master && row.party_master !== "") return; const party_type = row.party_type; const party = row.party; if (!party_type || !party) return; - frappe.db.get_value(party_type, party, "party_master", (r) => { - if (r?.party_master) { - frappe.model.set_value(row.doctype, row.name, "party_master", r.party_master); - const fieldname = frm.pm_on_child_fieldname; - if (fieldname) frm.refresh_field(fieldname); - } + if (!row.party_master) { + frappe.db.get_value(party_type, party, "party_master", (r) => { + if (r?.party_master) { + frappe.model.set_value(row.doctype, row.name, "party_master", r.party_master); + const fieldname = frm.pm_on_child_fieldname; + if (fieldname) frm.refresh_field(fieldname); + } + }); + } + + this.apply_party_master_defaults_to_child(frm, row); + }, + + apply_party_master_defaults_to_child: function (frm, row) { + if (!row || !row.party_type || !row.party) return; + + const cdt = row.doctype; + const cdn = row.name; + + const can_set_cost_center = frappe.meta.has_field(cdt, "cost_center"); + const can_set_project = frappe.meta.has_field(cdt, "project"); + const can_set_party_analytic_accounting = frappe.meta.has_field( + cdt, + "party_analytic_accounting", + ); + + if (!can_set_cost_center && !can_set_project && !can_set_party_analytic_accounting) return; + + frappe.call({ + method: "uph.party.controllers.party.get_party_master_defaults", + args: { + party_type: row.party_type, + party: row.party, + party_master: row.party_master, + }, + callback: function (r) { + if (!r.message) return; + const current = locals[cdt]?.[cdn] || row; + if (can_set_cost_center && r.message.cost_center && !current.cost_center) { + frappe.model.set_value(cdt, cdn, "cost_center", r.message.cost_center); + } + if (can_set_project && r.message.project && !current.project) { + frappe.model.set_value(cdt, cdn, "project", r.message.project); + } + if ( + can_set_party_analytic_accounting && + r.message.party_analytic_accounting && + !current.party_analytic_accounting + ) { + frappe.model.set_value( + cdt, + cdn, + "party_analytic_accounting", + r.message.party_analytic_accounting, + ); + } + }, }); }, From b4ebbddf5034e2857fcc1f62b4758a4b7993750e Mon Sep 17 00:00:00 2001 From: Sendipad Date: Fri, 6 Mar 2026 01:26:00 +0300 Subject: [PATCH 3/3] Add queries for party master defaults --- uph/party/doctype/party_master/party_master.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/uph/party/doctype/party_master/party_master.js b/uph/party/doctype/party_master/party_master.js index 950128f5..a473cf98 100644 --- a/uph/party/doctype/party_master/party_master.js +++ b/uph/party/doctype/party_master/party_master.js @@ -106,6 +106,24 @@ frappe.ui.form.on("Party Master", { filters: { party_master: frm.doc.name }, })); + frm.set_query("default_cost_center", () => { + const filters = { is_group: 0 }; + if (frm.doc.represents_company) { + filters.company = frm.doc.represents_company; + } + return { filters }; + }); + + frm.set_query("default_project", () => ({ + query: "erpnext.controllers.queries.get_project_name", + filters: frm.doc.represents_company ? { company: frm.doc.represents_company } : {}, + })); + + frm.set_query("default_party_analytic_accounting", () => ({ + query: "uph.party.controllers.queries.get_party_analytic_accounting_filtered", + filters: { party_master: frm.doc.name }, + })); + frm.toggle_display("roles", frm.doc.has_secondary_role_party === 1); render_relationships(frm); },