mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-22 10:49:59 +00:00
feat: add side-by-side defaults comparison view in item defaults grid (#55017)
* feat: add side-by-side defaults comparison view in item defaults grid * fix: coderabbit suggested changes * fix: change label of the fields * fix: description design
This commit is contained in:
@@ -101,3 +101,139 @@ frappe.ui.form.on("Item Group", {
|
||||
|
||||
page_name: frappe.utils.warn_page_name_change,
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Item Default", {
|
||||
form_render: function (frm, cdt, cdn) {
|
||||
if (!frm.fields_dict["item_group_defaults"]) return;
|
||||
|
||||
const row = locals[cdt][cdn];
|
||||
if (!row || !row.company) {
|
||||
Object.values(COMPANY_DEFAULTS_TO_VF).forEach((vf) => frappe.model.set_value(cdt, cdn, vf, ""));
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const $grid_row = frm.fields_dict["item_group_defaults"].grid.wrapper.find(
|
||||
`.grid-row[data-name="${cdn}"]`
|
||||
);
|
||||
$grid_row.find(".column-label").eq(1).text(__("Item Group Override"));
|
||||
}, 50);
|
||||
|
||||
const $grid_row = frm.fields_dict["item_group_defaults"].grid.wrapper.find(
|
||||
`.grid-row[data-name="${cdn}"]`
|
||||
);
|
||||
|
||||
if (!$grid_row.find(".item-defaults-desc").length) {
|
||||
$grid_row.find(".grid-form-body").prepend(`
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="item-defaults-desc" style="
|
||||
background: var(--control-bg);
|
||||
border-radius: var(--border-radius-sm);
|
||||
padding: 6px 6px 8px 14px;
|
||||
color: var(--text-muted);
|
||||
">
|
||||
${__(
|
||||
"Left column shows system-level defaults (Company / Stock Settings). Right column is where you set overrides for this item group."
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
populate_item_group_company_defaults(frm, cdt, cdn, row);
|
||||
},
|
||||
|
||||
company: function (frm, cdt, cdn) {
|
||||
if (!frm.fields_dict["item_group_defaults"]) return;
|
||||
|
||||
const row = locals[cdt][cdn];
|
||||
if (!row || !row.company) {
|
||||
Object.values(COMPANY_DEFAULTS_TO_VF).forEach((vf) => frappe.model.set_value(cdt, cdn, vf, ""));
|
||||
return;
|
||||
}
|
||||
|
||||
populate_item_group_company_defaults(frm, cdt, cdn, row);
|
||||
},
|
||||
});
|
||||
|
||||
const COMPANY_DEFAULTS_TO_VF = {
|
||||
default_warehouse: "vf_default_warehouse",
|
||||
default_inventory_account: "vf_default_inventory_account",
|
||||
buying_cost_center: "vf_buying_cost_center",
|
||||
selling_cost_center: "vf_selling_cost_center",
|
||||
expense_account: "vf_expense_account",
|
||||
income_account: "vf_income_account",
|
||||
default_provisional_account: "vf_default_provisional_account",
|
||||
purchase_expense_account: "vf_purchase_expense_account",
|
||||
default_cogs_account: "vf_default_cogs_account",
|
||||
deferred_expense_account: "vf_deferred_expense_account",
|
||||
deferred_revenue_account: "vf_deferred_revenue_account",
|
||||
default_price_list: "vf_default_price_list",
|
||||
default_discount_account: "vf_default_discount_account",
|
||||
default_supplier: "vf_default_supplier",
|
||||
purchase_expense_contra_account: "vf_purchase_expense_contra_account",
|
||||
};
|
||||
|
||||
const FIELD_DEFAULT_SOURCE = {
|
||||
default_warehouse: "Stock Settings",
|
||||
default_inventory_account: "Company",
|
||||
buying_cost_center: "Company",
|
||||
selling_cost_center: "Company",
|
||||
expense_account: "Company",
|
||||
income_account: "Company",
|
||||
default_provisional_account: "Company",
|
||||
purchase_expense_account: "Company",
|
||||
default_cogs_account: "Company",
|
||||
deferred_expense_account: "Company",
|
||||
deferred_revenue_account: "Company",
|
||||
default_price_list: null,
|
||||
default_discount_account: "Company",
|
||||
default_supplier: null,
|
||||
purchase_expense_contra_account: "Company",
|
||||
};
|
||||
|
||||
function populate_item_group_company_defaults(frm, cdt, cdn, row) {
|
||||
const company = row.company;
|
||||
|
||||
frappe.call({
|
||||
method: "erpnext.setup.doctype.item_group.item_group.get_company_resolved_defaults",
|
||||
args: { company: company },
|
||||
freeze: false,
|
||||
callback: function (r) {
|
||||
if (!r.message) return;
|
||||
|
||||
const current_row = locals[cdt][cdn];
|
||||
if (!current_row || current_row.company !== company) return;
|
||||
|
||||
const defaults = r.message;
|
||||
|
||||
Object.entries(COMPANY_DEFAULTS_TO_VF).forEach(([key, vf_field]) => {
|
||||
frappe.model.set_value(cdt, cdn, vf_field, defaults[key] || "—");
|
||||
});
|
||||
|
||||
setTimeout(() => update_item_group_vf_labels(frm, cdn, defaults), 50);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function update_item_group_vf_labels(frm, cdn, defaults) {
|
||||
const $grid_row = frm.fields_dict["item_group_defaults"].grid.wrapper.find(
|
||||
`.grid-row[data-name="${cdn}"]`
|
||||
);
|
||||
if (!$grid_row.length) return;
|
||||
|
||||
Object.entries(COMPANY_DEFAULTS_TO_VF).forEach(([key, vf_field]) => {
|
||||
const $label = $grid_row.find(`[data-fieldname="${vf_field}"]`).find(".control-label, label").first();
|
||||
if (!$label.length) return;
|
||||
|
||||
if (!$label.data("base-label")) {
|
||||
$label.data("base-label", $label.text().trim());
|
||||
}
|
||||
const base = $label.data("base-label");
|
||||
|
||||
const source = FIELD_DEFAULT_SOURCE[key];
|
||||
$label.text(source ? `${base} (${__(source)})` : base);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -94,3 +94,36 @@ def get_item_group_defaults(item, company):
|
||||
return row
|
||||
|
||||
return frappe._dict()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_company_resolved_defaults(company: str) -> dict:
|
||||
"""
|
||||
Returns effective default values for a company by checking:
|
||||
1. Company document
|
||||
2. Stock Settings (for warehouse fallback)
|
||||
3. Accounts Settings (for deferred account fallbacks)
|
||||
"""
|
||||
if not company:
|
||||
return {}
|
||||
|
||||
company_doc = frappe.get_cached_doc("Company", company)
|
||||
default_warehouse = frappe.db.get_single_value("Stock Settings", "default_warehouse")
|
||||
|
||||
return {
|
||||
"default_warehouse": default_warehouse,
|
||||
"default_inventory_account": company_doc.get("default_inventory_account"),
|
||||
"buying_cost_center": company_doc.get("cost_center"),
|
||||
"selling_cost_center": company_doc.get("cost_center"),
|
||||
"expense_account": company_doc.get("default_expense_account"),
|
||||
"income_account": company_doc.get("default_income_account"),
|
||||
"default_provisional_account": company_doc.get("default_provisional_account"),
|
||||
"purchase_expense_account": company_doc.get("purchase_expense_account"),
|
||||
"default_cogs_account": company_doc.get("default_expense_account"),
|
||||
"deferred_expense_account": company_doc.get("default_deferred_expense_account"),
|
||||
"deferred_revenue_account": company_doc.get("default_deferred_revenue_account"),
|
||||
"default_discount_account": company_doc.get("default_discount_account"),
|
||||
"purchase_expense_contra_account": company_doc.get("purchase_expense_contra_account"),
|
||||
"default_price_list": "",
|
||||
"default_supplier": "",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user