From 5aab5502f0449c9026ec95dfd3d19477c82ebc59 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:43:57 +0530 Subject: [PATCH] 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 --- .../setup/doctype/item_group/item_group.js | 136 ++++++ .../setup/doctype/item_group/item_group.py | 33 ++ erpnext/stock/doctype/item/item.js | 152 +++++++ .../doctype/item_default/item_default.json | 419 ++++++++++++------ 4 files changed, 603 insertions(+), 137 deletions(-) diff --git a/erpnext/setup/doctype/item_group/item_group.js b/erpnext/setup/doctype/item_group/item_group.js index 6835be17ab7..fe9db5299f5 100644 --- a/erpnext/setup/doctype/item_group/item_group.js +++ b/erpnext/setup/doctype/item_group/item_group.js @@ -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(` +
+
+
+ ${__( + "Left column shows system-level defaults (Company / Stock Settings). Right column is where you set overrides for this item group." + )} +
+
+
+ `); + } + + 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); + }); +} diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 3b57a5852cc..e0dcdf996a7 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -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": "", + } diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 898708962a9..6dfe5009a07 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -6,6 +6,24 @@ frappe.provide("erpnext.item"); const SALES_DOCTYPES = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]; const PURCHASE_DOCTYPES = ["Purchase Order", "Purchase Receipt", "Purchase Invoice"]; +const virtual_field_map = { + default_warehouse: "vf_default_warehouse", + default_price_list: "vf_default_price_list", + default_discount_account: "vf_default_discount_account", + default_inventory_account: "vf_default_inventory_account", + buying_cost_center: "vf_buying_cost_center", + default_supplier: "vf_default_supplier", + expense_account: "vf_expense_account", + default_provisional_account: "vf_default_provisional_account", + purchase_expense_account: "vf_purchase_expense_account", + purchase_expense_contra_account: "vf_purchase_expense_contra_account", + selling_cost_center: "vf_selling_cost_center", + income_account: "vf_income_account", + default_cogs_account: "vf_default_cogs_account", + deferred_expense_account: "vf_deferred_expense_account", + deferred_revenue_account: "vf_deferred_revenue_account", +}; + frappe.ui.form.on("Item", { valuation_method(frm) { if (!frm.is_new() && frm.doc.valuation_method === "Moving Average") { @@ -346,6 +364,53 @@ frappe.ui.form.on("Item", { }, }); +frappe.ui.form.on("Item Default", { + form_render: function (frm, cdt, cdn) { + if (!frm.fields_dict["item_defaults"]) return; + + const row = locals[cdt][cdn]; + if (!row || !row.company) { + Object.values(virtual_field_map).forEach((vf) => frappe.model.set_value(cdt, cdn, vf, "")); + return; + } + + const $grid_row = frm.fields_dict["item_defaults"].grid.wrapper.find(`.grid-row[data-name="${cdn}"]`); + + if (!$grid_row.find(".item-defaults-desc").length) { + $grid_row.find(".grid-form-body").prepend(` +
+
+
+ ${__( + "Left column shows inherited defaults (Item Group → Company / Stock Settings). Right column is where you set overrides for this item only." + )} +
+
+
+ `); + } + + erpnext.item.populate_virtual_fields(frm, cdt, cdn, row); + }, + + company: function (frm, cdt, cdn) { + if (!frm.fields_dict["item_defaults"]) return; + + const row = locals[cdt][cdn]; + if (!row || !row.company) { + Object.values(virtual_field_map).forEach((vf) => frappe.model.set_value(cdt, cdn, vf, "")); + return; + } + erpnext.item.populate_virtual_fields(frm, cdt, cdn, row); + }, +}); + frappe.ui.form.on("Item Reorder", { reorder_levels_add: function (frm, cdt, cdn) { var row = frappe.get_doc(cdt, cdn); @@ -449,6 +514,93 @@ function render_serial_batch_banner(wrapper) { } $.extend(erpnext.item, { + populate_virtual_fields: function (frm, cdt, cdn, row) { + if (!frm.doc.item_group || !row.company) { + Object.values(virtual_field_map).forEach((vf) => frappe.model.set_value(cdt, cdn, vf, "")); + return; + } + + const company = row.company; + const item_group = frm.doc.item_group; + + frappe.call({ + method: "frappe.client.get", + args: { doctype: "Item Group", name: frm.doc.item_group }, + freeze: false, + callback: function (r) { + if (!r.message) return; + + const current_row = locals[cdt][cdn]; + if (!current_row || current_row.company !== company || frm.doc.item_group !== item_group) + return; + + const group_defaults = + (r.message.item_group_defaults || []).find((d) => d.company === company) || {}; + + // Set Item Group values immediately; collect fields that need company fallback + const needs_company_fallback = []; + Object.entries(virtual_field_map).forEach(([real_field, vf_field]) => { + if (group_defaults[real_field]) { + frappe.model.set_value(cdt, cdn, vf_field, group_defaults[real_field]); + } else { + frappe.model.set_value(cdt, cdn, vf_field, ""); + needs_company_fallback.push(real_field); + } + }); + + if (!needs_company_fallback.length) { + setTimeout(() => erpnext.item.update_vf_labels(frm, cdn, {}), 50); + return; + } + frappe.call({ + method: "erpnext.setup.doctype.item_group.item_group.get_company_resolved_defaults", + args: { company: company }, + freeze: false, + callback: function (cr) { + const current_row = locals[cdt][cdn]; + if ( + !current_row || + current_row.company !== company || + frm.doc.item_group !== item_group + ) + return; + + const company_defaults = cr.message || {}; + const from_company = {}; + + needs_company_fallback.forEach((real_field) => { + const val = company_defaults[real_field] || ""; + if (val) from_company[real_field] = val; + frappe.model.set_value(cdt, cdn, virtual_field_map[real_field], val || "—"); + }); + + setTimeout(() => erpnext.item.update_vf_labels(frm, cdn, from_company), 50); + }, + }); + }, + }); + }, + + update_vf_labels: function (frm, cdn, from_company) { + const $grid_row = frm.fields_dict["item_defaults"].grid.wrapper.find(`.grid-row[data-name="${cdn}"]`); + if (!$grid_row.length) return; + + Object.entries(virtual_field_map).forEach(([real_field, 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"); + + $label.text(from_company[real_field] ? `${base} (Company)` : `${base} (Item Group)`); + }); + }, + setup_queries: function (frm) { frm.fields_dict["item_defaults"].grid.get_field("expense_account").get_query = function ( doc, diff --git a/erpnext/stock/doctype/item_default/item_default.json b/erpnext/stock/doctype/item_default/item_default.json index b00644d51f2..da74d45eeb6 100644 --- a/erpnext/stock/doctype/item_default/item_default.json +++ b/erpnext/stock/doctype/item_default/item_default.json @@ -5,34 +5,60 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ + "company_section", "company", + "from_section", + "column_break_general", + "vf_default_warehouse", + "vf_default_price_list", + "vf_default_discount_account", + "vf_default_inventory_account", + "column_break_njfg", "default_warehouse", - "column_break_3", "default_price_list", "default_discount_account", "default_inventory_account", "inventory_account_currency", "purchase_defaults", + "column_break_purchase", + "vf_buying_cost_center", + "vf_default_supplier", + "vf_expense_account", + "vf_default_provisional_account", + "vf_purchase_expense_account", + "vf_purchase_expense_contra_account", + "column_break_ghzl", "buying_cost_center", "default_supplier", - "column_break_8", "expense_account", "default_provisional_account", - "column_break_cpif", "purchase_expense_account", "purchase_expense_contra_account", "selling_defaults", + "column_break_sales", + "vf_selling_cost_center", + "vf_income_account", + "column_break_ilsl", "selling_cost_center", - "column_break_12", "income_account", "cost_of_good_sold_section", + "column_break_cogs", + "vf_default_cogs_account", + "column_break_vnkl", "default_cogs_account", "deferred_accounting_defaults_section", + "column_break_deferred", + "vf_deferred_expense_account", + "vf_deferred_revenue_account", + "column_break_okiu", "deferred_expense_account", - "column_break_kwad", "deferred_revenue_account" ], "fields": [ + { + "fieldname": "company_section", + "fieldtype": "Section Break" + }, { "fieldname": "company", "fieldtype": "Link", @@ -46,157 +72,30 @@ "fieldname": "default_warehouse", "fieldtype": "Link", "in_list_view": 1, - "label": "Default Warehouse", + "label": "Warehouse", "options": "Warehouse", "search_index": 1 }, - { - "fieldname": "column_break_3", - "fieldtype": "Column Break" - }, { "description": "Default price list for buying or selling this item", "fieldname": "default_price_list", "fieldtype": "Link", "in_list_view": 1, - "label": "Default Price List", + "label": "Price List", "options": "Price List", "show_description_on_click": 1 }, - { - "fieldname": "purchase_defaults", - "fieldtype": "Section Break", - "label": "Purchase Defaults" - }, - { - "description": "Cost center used for tracking purchase expenses for this item", - "fieldname": "buying_cost_center", - "fieldtype": "Link", - "label": "Default Buying Cost Center", - "options": "Cost Center", - "show_description_on_click": 1 - }, - { - "description": "This supplier will be auto-selected in new purchase transactions", - "fieldname": "default_supplier", - "fieldtype": "Link", - "label": "Default Supplier", - "options": "Supplier" - }, - { - "fieldname": "column_break_8", - "fieldtype": "Column Break" - }, - { - "description": "Account where the cost of this item will be debited on purchase", - "fieldname": "expense_account", - "fieldtype": "Link", - "label": "Default Expense Account", - "options": "Account", - "show_description_on_click": 1 - }, - { - "fieldname": "selling_defaults", - "fieldtype": "Section Break", - "label": "Sales Defaults" - }, - { - "description": "Cost center used for tracking sales revenue for this item", - "fieldname": "selling_cost_center", - "fieldtype": "Link", - "label": "Default Selling Cost Center", - "options": "Cost Center", - "show_description_on_click": 1 - }, - { - "fieldname": "column_break_12", - "fieldtype": "Column Break" - }, - { - "description": "Account where revenue from selling this item will be credited", - "fieldname": "income_account", - "fieldtype": "Link", - "label": "Default Income Account", - "options": "Account", - "show_description_on_click": 1 - }, { "fieldname": "default_discount_account", "fieldtype": "Link", - "label": "Default Discount Account", - "options": "Account" - }, - { - "description": "Provisional liability account used for service items before invoice is received", - "fieldname": "default_provisional_account", - "fieldtype": "Link", - "label": "Default Provisional Account (Service)", - "options": "Account" - }, - { - "fieldname": "deferred_accounting_defaults_section", - "fieldtype": "Section Break", - "label": "Deferred Accounting Defaults" - }, - { - "depends_on": "eval: parent.enable_deferred_expense", - "description": "When you pay for something upfront (like annual insurance), the cost is held here and recognized gradually over time", - "fieldname": "deferred_expense_account", - "fieldtype": "Link", - "label": "Deferred Expense Account", - "options": "Account", - "show_description_on_click": 1 - }, - { - "depends_on": "eval: parent.enable_deferred_revenue", - "description": "Revenue received in advance (e.g. annual subscription) is held here and recognized gradually over time", - "fieldname": "deferred_revenue_account", - "fieldtype": "Link", - "label": "Deferred Revenue Account", - "options": "Account", - "show_description_on_click": 1 - }, - { - "fieldname": "column_break_kwad", - "fieldtype": "Column Break" - }, - { - "fieldname": "column_break_cpif", - "fieldtype": "Column Break" - }, - { - "fieldname": "cost_of_good_sold_section", - "fieldtype": "Section Break", - "label": "Cost of Goods Sold" - }, - { - "description": "Account where cost of goods sold will be posted when this item is sold", - "fieldname": "default_cogs_account", - "fieldtype": "Link", - "label": "Default COGS Account", - "options": "Account", - "show_description_on_click": 1 - }, - { - "description": "Account to record additional purchase expenses like freight or customs for this item", - "fieldname": "purchase_expense_account", - "fieldtype": "Link", - "label": "Purchase Expense Account", - "options": "Account", - "show_description_on_click": 1 - }, - { - "description": "Used to balance the books when recording extra purchase costs like freight or customs", - "fieldname": "purchase_expense_contra_account", - "fieldtype": "Link", - "label": "Purchase Expense Contra Account", + "label": "Discount Account", "options": "Account" }, { "description": "Stock account where inventory value for this item will be tracked", "fieldname": "default_inventory_account", "fieldtype": "Link", - "label": "Default Inventory Account", + "label": "Inventory Account", "options": "Account", "show_description_on_click": 1 }, @@ -207,11 +106,257 @@ "label": "Inventory Account Currency", "options": "Currency", "read_only": 1 + }, + { + "fieldname": "column_break_general", + "fieldtype": "Column Break", + "label": "Inherited Default" + }, + { + "fieldname": "vf_default_warehouse", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Warehouse" + }, + { + "fieldname": "vf_default_price_list", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Price List" + }, + { + "fieldname": "vf_default_discount_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Discount Account" + }, + { + "fieldname": "vf_default_inventory_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Inventory Account" + }, + { + "fieldname": "purchase_defaults", + "fieldtype": "Section Break", + "label": "Purchase Defaults" + }, + { + "description": "Cost center used for tracking purchase expenses for this item", + "fieldname": "buying_cost_center", + "fieldtype": "Link", + "label": "Buying Cost Center", + "options": "Cost Center", + "show_description_on_click": 1 + }, + { + "description": "This supplier will be auto-selected in new purchase transactions", + "fieldname": "default_supplier", + "fieldtype": "Link", + "label": "Supplier", + "options": "Supplier", + "show_description_on_click": 1 + }, + { + "description": "Account where the cost of this item will be debited on purchase", + "fieldname": "expense_account", + "fieldtype": "Link", + "label": "Expense Account", + "options": "Account", + "show_description_on_click": 1 + }, + { + "description": "Provisional liability account used for service items before invoice is received", + "fieldname": "default_provisional_account", + "fieldtype": "Link", + "label": "Provisional Account (Service)", + "options": "Account", + "show_description_on_click": 1 + }, + { + "description": "Account to record additional purchase expenses like freight or customs", + "fieldname": "purchase_expense_account", + "fieldtype": "Link", + "label": "Purchase Expense Account", + "options": "Account", + "show_description_on_click": 1 + }, + { + "description": "Used to balance the books when recording extra purchase costs", + "fieldname": "purchase_expense_contra_account", + "fieldtype": "Link", + "label": "Purchase Expense Contra Account", + "options": "Account", + "show_description_on_click": 1 + }, + { + "fieldname": "column_break_purchase", + "fieldtype": "Column Break" + }, + { + "fieldname": "vf_buying_cost_center", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Buying Cost Center" + }, + { + "fieldname": "vf_default_supplier", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Supplier" + }, + { + "fieldname": "vf_expense_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Expense Account" + }, + { + "fieldname": "vf_default_provisional_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Provisional Account (Service)" + }, + { + "fieldname": "vf_purchase_expense_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Purchase Expense Account" + }, + { + "fieldname": "vf_purchase_expense_contra_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Purchase Expense Contra Account" + }, + { + "fieldname": "selling_defaults", + "fieldtype": "Section Break", + "label": "Sales Defaults" + }, + { + "description": "Cost center used for tracking sales revenue for this item", + "fieldname": "selling_cost_center", + "fieldtype": "Link", + "label": "Selling Cost Center", + "options": "Cost Center", + "show_description_on_click": 1 + }, + { + "description": "Account where revenue from selling this item will be credited", + "fieldname": "income_account", + "fieldtype": "Link", + "label": "Income Account", + "options": "Account", + "show_description_on_click": 1 + }, + { + "fieldname": "column_break_sales", + "fieldtype": "Column Break" + }, + { + "fieldname": "vf_selling_cost_center", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Selling Cost Center" + }, + { + "fieldname": "vf_income_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Income Account" + }, + { + "fieldname": "cost_of_good_sold_section", + "fieldtype": "Section Break", + "label": "Cost of Goods Sold" + }, + { + "description": "Account where cost of goods sold will be posted when this item is sold", + "fieldname": "default_cogs_account", + "fieldtype": "Link", + "label": "COGS Account", + "options": "Account", + "show_description_on_click": 1 + }, + { + "fieldname": "column_break_cogs", + "fieldtype": "Column Break" + }, + { + "fieldname": "vf_default_cogs_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "COGS Account" + }, + { + "fieldname": "deferred_accounting_defaults_section", + "fieldtype": "Section Break", + "label": "Deferred Accounting Defaults" + }, + { + "depends_on": "eval: parent.enable_deferred_expense", + "fieldname": "deferred_expense_account", + "fieldtype": "Link", + "label": "Expense Account", + "options": "Account", + "show_description_on_click": 1 + }, + { + "depends_on": "eval: parent.enable_deferred_revenue", + "fieldname": "deferred_revenue_account", + "fieldtype": "Link", + "label": "Revenue Account", + "options": "Account", + "show_description_on_click": 1 + }, + { + "fieldname": "column_break_deferred", + "fieldtype": "Column Break" + }, + { + "depends_on": "eval: parent.enable_deferred_expense", + "fieldname": "vf_deferred_expense_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Deferred Expense Account" + }, + { + "depends_on": "eval: parent.enable_deferred_revenue", + "fieldname": "vf_deferred_revenue_account", + "fieldtype": "Read Only", + "is_virtual": 1, + "label": "Deferred Revenue Account" + }, + { + "fieldname": "column_break_njfg", + "fieldtype": "Column Break", + "label": "Item Override" + }, + { + "fieldname": "column_break_ghzl", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_ilsl", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_vnkl", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_okiu", + "fieldtype": "Column Break" + }, + { + "fieldname": "from_section", + "fieldtype": "Section Break" } ], "istable": 1, "links": [], - "modified": "2026-04-27 01:49:01.396845", + "modified": "2026-06-03 17:25:35.982082", "modified_by": "Administrator", "module": "Stock", "name": "Item Default",