From 0eb049cd85e5e2f7273c16f295b4d37f15b21e1c Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:44:55 +0530 Subject: [PATCH] fix(UX): Item master form cleanup (#54538) * fix: UI improvements for item form * fix: add descriptions and tooltips to all checkboxes * feat: show toast notification when item price is created * fix: do not use selling rate for opening stock entry * fix: add descriptions and tooltips to item default fields * fix(test): give valuation rate for opening stock entry creation * fix: moving naming series toggle before the return * refactor: more changes in the form UI (cherry picked from commit 43937acd8b60462be1cb38ccb0ac7e38c0141f98) --- .../test_bom_stock_analysis.py | 2 + erpnext/stock/doctype/item/item.js | 30 ++- erpnext/stock/doctype/item/item.json | 234 ++++++++++++------ erpnext/stock/doctype/item/item.py | 36 ++- .../item_customer_detail.json | 6 +- .../doctype/item_default/item_default.json | 45 +++- .../doctype/item_supplier/item_supplier.json | 10 +- .../uom_conversion_detail.json | 7 +- 8 files changed, 264 insertions(+), 106 deletions(-) diff --git a/erpnext/manufacturing/report/bom_stock_analysis/test_bom_stock_analysis.py b/erpnext/manufacturing/report/bom_stock_analysis/test_bom_stock_analysis.py index fd8a52afde0..70717377ff7 100644 --- a/erpnext/manufacturing/report/bom_stock_analysis/test_bom_stock_analysis.py +++ b/erpnext/manufacturing/report/bom_stock_analysis/test_bom_stock_analysis.py @@ -94,6 +94,7 @@ def create_items(): "is_stock_item": 1, "standard_rate": 100, "opening_stock": 100, + "valuation_rate": 100, "last_purchase_rate": 100, "item_defaults": [{"company": "_Test Company", "default_warehouse": "Stores - _TC"}], } @@ -103,6 +104,7 @@ def create_items(): "is_stock_item": 1, "standard_rate": 200, "opening_stock": 200, + "valuation_rate": 200, "last_purchase_rate": 200, "item_defaults": [{"company": "_Test Company", "default_warehouse": "Stores - _TC"}], } diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index b25fc06e2dd..c03199e4348 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -73,6 +73,7 @@ frappe.ui.form.on("Item", { }, }; }, + onload: function (frm) { erpnext.item.setup_queries(frm); if (frm.doc.variant_of) { @@ -127,6 +128,21 @@ frappe.ui.form.on("Item", { refresh: function (frm) { frm.trigger("toggle_has_serial_batch_fields"); + if (frappe.defaults.get_default("item_naming_by") != "Naming Series" || frm.doc.variant_of) { + frm.toggle_display("naming_series", false); + } else { + erpnext.toggle_naming_series(); + } + + frm.toggle_display(["standard_rate"], frappe.model.can_create("Item Price")); + + if (frm.is_new()) { + frm.toggle_display("disabled", false); + return; + } + + frm.toggle_display("disabled", true); + if (frm.doc.is_stock_item) { frm.add_custom_button( __("Stock Balance"), @@ -229,8 +245,6 @@ frappe.ui.form.on("Item", { __("Create") ); } - - // frm.page.set_inner_btn_group_as_primary(__('Create')); } if (frm.doc.variant_of) { frm.set_intro( @@ -241,12 +255,6 @@ frappe.ui.form.on("Item", { ); } - if (frappe.defaults.get_default("item_naming_by") != "Naming Series" || frm.doc.variant_of) { - frm.toggle_display("naming_series", false); - } else { - erpnext.toggle_naming_series(); - } - erpnext.item.edit_prices_button(frm); erpnext.item.toggle_attributes(frm); @@ -286,8 +294,6 @@ frappe.ui.form.on("Item", { }, }; }); - - frm.toggle_display(["standard_rate"], frappe.model.can_create("Item Price")); }, validate: function (frm) { @@ -661,10 +667,10 @@ $.extend(erpnext.item, { make_dashboard: function (frm) { if (frm.doc.__islocal) return; - // Show Stock Levels only if is_stock_item if (frm.doc.is_stock_item) { frappe.require("item-dashboard.bundle.js", function () { - const section = frm.dashboard.add_section("", __("Stock Levels")); + const section = frm.fields_dict["stock_levels_html"].$wrapper; + erpnext.item.item_dashboard = new erpnext.stock.ItemDashboard({ parent: section, item_code: frm.doc.name, diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 75dcd140474..1f2581a4981 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -18,30 +18,57 @@ "stock_uom", "column_break0", "disabled", - "allow_alternative_item", "is_stock_item", - "has_variants", "is_fixed_asset", "auto_create_assets", "is_grouped_asset", "asset_category", "asset_naming_series", + "section_break_zlmj", + "is_sales_item", + "allow_alternative_item", + "has_variants", + "column_break_kpmi", + "is_purchase_item", + "is_customer_provided_item", + "customer", "section_break_gjns", - "opening_stock", - "column_break_ixrh", "standard_rate", + "column_break_ixrh", + "opening_stock", "section_break_znra", "over_delivery_receipt_allowance", "column_break_wugd", "over_billing_allowance", "image", "section_break_11", - "description", "brand", + "description", + "accounting", + "section_break_wfkx", + "item_defaults", + "deferred_accounting_section", + "enable_deferred_expense", + "no_of_months_exp", + "column_break_9s9o", + "enable_deferred_revenue", + "no_of_months", + "uom_tab", "unit_of_measure_conversion", + "uom_conversion_details_column", + "uom_help_html", "uoms", - "dashboard_tab", + "item_tax_section_break", + "section_break_oilf", + "column_break_aytr", + "taxes", + "section_break_fxqz", + "purchase_tax_withholding_category", + "column_break_ltlb", + "sales_tax_withholding_category", "inventory_section", + "stock_levels_section", + "stock_levels_html", "inventory_valuation_section", "valuation_method", "column_break_cqdk", @@ -69,32 +96,20 @@ "column_break_37", "has_serial_no", "serial_no_series", - "defaults_tab", - "item_defaults", "variants_section", "variant_of", "variant_based_on", "attributes", - "accounting", - "deferred_accounting_section", - "enable_deferred_expense", - "no_of_months_exp", - "column_break_9s9o", - "enable_deferred_revenue", - "no_of_months", "purchasing_tab", "purchase_uom", "min_order_qty", "safety_stock", - "is_purchase_item", "purchase_details_cb", "lead_time_days", "last_purchase_rate", - "is_customer_provided_item", - "customer", "supplier_details", "delivered_by_supplier", - "column_break2", + "section_break_ylma", "supplier_items", "foreign_trade_details", "country_of_origin", @@ -103,24 +118,10 @@ "sales_details", "sales_uom", "grant_commission", - "is_sales_item", "column_break3", "max_discount", "customer_details", "customer_items", - "item_tax_section_break", - "section_break_oilf", - "column_break_aytr", - "taxes", - "section_break_fxqz", - "purchase_tax_withholding_category", - "column_break_ltlb", - "sales_tax_withholding_category", - "quality_tab", - "inspection_required_before_purchase", - "inspection_required_before_delivery", - "column_break_pxjh", - "quality_inspection_template", "manufacturing", "include_item_in_manufacturing", "is_sub_contracted_item", @@ -129,10 +130,16 @@ "production_capacity", "total_projected_qty", "section_break_xili", - "customer_code", - "column_break_vipt", "default_manufacturer_part_no", - "default_item_manufacturer" + "default_item_manufacturer", + "column_break_vipt", + "customer_code", + "quality_tab", + "inspection_required_before_purchase", + "inspection_required_before_delivery", + "column_break_pxjh", + "quality_inspection_template", + "dashboard_tab" ], "fields": [ { @@ -208,32 +215,38 @@ }, { "default": "0", + "description": "Disabled items cannot be selected in any transaction.", "fieldname": "disabled", "fieldtype": "Check", "label": "Disabled", - "search_index": 1 + "search_index": 1, + "show_description_on_click": 1 }, { "default": "0", + "description": "Allow substituting this item with an alternative from the Item Alternative list when stock is unavailable.", "fieldname": "allow_alternative_item", "fieldtype": "Check", - "label": "Allow Alternative Item" + "label": "Allow Alternative Item", + "show_description_on_click": 1 }, { "allow_in_quick_entry": 1, "bold": 1, "default": "1", - "depends_on": "eval:!doc.is_fixed_asset", + "description": "ERPNext will make a stock ledger entry for each transaction of this item. Keep unchecked for non-stock or service items.", "fieldname": "is_stock_item", "fieldtype": "Check", "in_list_view": 1, "label": "Maintain Stock", "oldfieldname": "is_stock_item", - "oldfieldtype": "Select" + "oldfieldtype": "Select", + "read_only_depends_on": "eval:doc.is_fixed_asset" }, { "default": "1", "depends_on": "eval:!doc.is_fixed_asset", + "description": "Enable for raw material items used in BOM. Uncheck for additional services like 'washing' used in manufacturing.", "fieldname": "include_item_in_manufacturing", "fieldtype": "Check", "label": "Include Item In Manufacturing" @@ -241,6 +254,7 @@ { "bold": 1, "depends_on": "eval:(doc.__islocal&&doc.is_stock_item && !doc.has_serial_no && !doc.has_batch_no)", + "description": "Used to create an opening Stock Entry with the Valuation Rate when the item is saved", "fieldname": "opening_stock", "fieldtype": "Float", "label": "Opening Stock" @@ -253,7 +267,8 @@ }, { "bold": 1, - "depends_on": "eval:doc.__islocal", + "depends_on": "eval:doc.__islocal && doc.is_sales_item", + "description": "Creates an Item Price automatically when the item is saved", "fieldname": "standard_rate", "fieldtype": "Currency", "label": "Standard Selling Rate" @@ -261,9 +276,11 @@ { "allow_in_quick_entry": 1, "default": "0", + "description": "Enable if this item is a company asset like machinery or furniture.", "fieldname": "is_fixed_asset", "fieldtype": "Check", - "label": "Is Fixed Asset" + "label": "Is Fixed Asset", + "read_only_depends_on": "eval:doc.is_stock_item" }, { "allow_in_quick_entry": 1, @@ -413,16 +430,12 @@ "options": "Item Reorder" }, { - "collapsible": 1, "fieldname": "unit_of_measure_conversion", - "fieldtype": "Section Break", - "label": "Units of Measure" + "fieldtype": "Section Break" }, { - "description": "Will also apply for variants", "fieldname": "uoms", "fieldtype": "Table", - "label": "UOMs", "oldfieldname": "uom_conversion_details", "oldfieldtype": "Table", "options": "UOM Conversion Detail" @@ -438,15 +451,18 @@ { "default": "0", "depends_on": "eval:doc.is_stock_item", + "description": "Track this item in batches. Cannot be changed after a stock transaction exists.", "fieldname": "has_batch_no", "fieldtype": "Check", "label": "Has Batch No", "oldfieldname": "has_batch_no", - "oldfieldtype": "Select" + "oldfieldtype": "Select", + "show_description_on_click": 1 }, { "default": "0", "depends_on": "has_batch_no", + "description": "Batch number will be auto-created in format AAAA.00001 if not specified in transactions. Leave blank to always enter batch numbers manually.", "fieldname": "create_new_batch", "fieldtype": "Check", "label": "Automatically Create New Batch" @@ -463,6 +479,7 @@ { "default": "0", "depends_on": "has_batch_no", + "description": "Batch number will be created based on expiry date. Expiry dates can be set in the Batch master.", "fieldname": "has_expiry_date", "fieldtype": "Check", "label": "Has Expiry Date" @@ -491,11 +508,13 @@ { "default": "0", "depends_on": "eval:doc.is_stock_item", + "description": "Track each unit with a unique serial number for warranty and return tracking. Cannot be changed after a stock transaction exists.", "fieldname": "has_serial_no", "fieldtype": "Check", "label": "Has Serial No", "oldfieldname": "has_serial_no", - "oldfieldtype": "Select" + "oldfieldtype": "Select", + "show_description_on_click": 1 }, { "depends_on": "has_serial_no", @@ -520,7 +539,8 @@ "fieldname": "has_variants", "fieldtype": "Check", "in_standard_filter": 1, - "label": "Has Variants" + "label": "Has Variants", + "show_description_on_click": 1 }, { "default": "Item Attribute", @@ -547,11 +567,15 @@ }, { "default": "1", + "description": "Allow this item to be used in purchase transactions.", "fieldname": "is_purchase_item", "fieldtype": "Check", - "label": "Allow Purchase" + "label": "Allow Purchase", + "read_only_depends_on": "eval: doc.is_customer_provided_item", + "show_description_on_click": 1 }, { + "depends_on": "eval: doc.is_purchase_item", "fieldname": "purchase_uom", "fieldtype": "Link", "label": "Default Purchase Unit of Measure", @@ -560,7 +584,7 @@ { "default": "0.00", "depends_on": "is_stock_item", - "description": "Minimum quantity should be as per Stock UOM", + "description": "Minimum quantity should be as per Stock UOM\n\n", "fieldname": "min_order_qty", "fieldtype": "Float", "label": "Minimum Order Qty", @@ -569,6 +593,7 @@ "oldfieldtype": "Currency" }, { + "description": "Minimum stock level to maintain as a buffer. Used to calculate recommended reorder level: Reorder Level = Safety Stock + (Average Daily Consumption \u00d7 Lead Time).", "fieldname": "safety_stock", "fieldtype": "Float", "label": "Safety Stock", @@ -588,6 +613,7 @@ "oldfieldtype": "Int" }, { + "description": "The rate at which this item was last purchased via a Purchase Invoice. Auto-updated by the system.", "fieldname": "last_purchase_rate", "fieldtype": "Float", "label": "Last Purchase Rate", @@ -599,9 +625,12 @@ }, { "default": "0", + "description": "Enable if this item is provided by a customer and received via Stock Entry.", "fieldname": "is_customer_provided_item", "fieldtype": "Check", - "label": "Is Customer Provided Item" + "label": "Is Customer Provided Item", + "read_only_depends_on": "eval: doc.is_purchase_item", + "show_description_on_click": 1 }, { "depends_on": "eval:doc.is_customer_provided_item", @@ -611,29 +640,24 @@ "options": "Customer" }, { - "collapsible": 1, "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "supplier_details", "fieldtype": "Section Break", + "hide_border": 1, "label": "Supplier Details" }, { "default": "0", + "description": "Enable for drop shipping - supplier delivers directly to the customer without passing through your warehouse.", "fieldname": "delivered_by_supplier", "fieldtype": "Check", "label": "Delivered by Supplier (Drop Ship)", "print_hide": 1 }, - { - "fieldname": "column_break2", - "fieldtype": "Column Break", - "oldfieldtype": "Column Break", - "width": "50%" - }, { "fieldname": "supplier_items", "fieldtype": "Table", - "label": "Supplier Items", + "label": "Item Supplier", "options": "Item Supplier" }, { @@ -660,6 +684,7 @@ }, { "collapsible": 1, + "depends_on": "eval: doc.is_sales_item", "fieldname": "sales_details", "fieldtype": "Tab Break", "label": "Sales", @@ -667,6 +692,7 @@ "options": "fa fa-tag" }, { + "depends_on": "eval: doc.is_sales_item", "fieldname": "sales_uom", "fieldtype": "Link", "label": "Default Sales Unit of Measure", @@ -674,9 +700,11 @@ }, { "default": "1", + "description": "Allow this item to be used in sales transactions.", "fieldname": "is_sales_item", "fieldtype": "Check", - "label": "Allow Sales" + "label": "Allow Sales", + "show_description_on_click": 1 }, { "fieldname": "column_break3", @@ -685,6 +713,7 @@ "width": "50%" }, { + "description": "Maximum discount % allowed when selling this item. Eg: if set to 20%, a discount greater than 20% cannot be applied in sales transactions.", "fieldname": "max_discount", "fieldtype": "Float", "label": "Max Discount (%)", @@ -693,6 +722,7 @@ }, { "default": "0", + "description": "Expense for this item will be recognized over a period of months. Eg: prepaid insurance or annual software license", "fieldname": "enable_deferred_revenue", "fieldtype": "Check", "label": "Enable Deferred Revenue" @@ -705,6 +735,7 @@ }, { "default": "0", + "description": "Income from this item will be recognized over a period of months instead of all at once. Eg: annual subscription paid upfront.", "fieldname": "enable_deferred_expense", "fieldtype": "Check", "label": "Enable Deferred Expense" @@ -716,7 +747,6 @@ "label": "No of Months (Expense)" }, { - "collapsible": 1, "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "customer_details", "fieldtype": "Section Break", @@ -748,17 +778,21 @@ }, { "default": "0", + "description": "A quality inspection must be completed before generating a Purchase Receipt for this item.", "fieldname": "inspection_required_before_purchase", "fieldtype": "Check", "label": "Inspection Required before Purchase", "oldfieldname": "inspection_required", - "oldfieldtype": "Select" + "oldfieldtype": "Select", + "show_description_on_click": 1 }, { "default": "0", + "description": "A quality inspection must be completed before generating a Delivery Note for this item.", "fieldname": "inspection_required_before_delivery", "fieldtype": "Check", - "label": "Inspection Required before Delivery" + "label": "Inspection Required before Delivery", + "show_description_on_click": 1 }, { "fieldname": "quality_inspection_template", @@ -789,6 +823,7 @@ }, { "default": "0", + "description": "Enable if a vendor manufactures this item for you. You can choose to provide them raw materials using the default BOM.", "fieldname": "is_sub_contracted_item", "fieldtype": "Check", "label": "Is Subcontracted Item", @@ -817,6 +852,7 @@ }, { "depends_on": "eval:!doc.__islocal && !doc.is_fixed_asset", + "description": "Percentage by which over-delivery or over-receipt is allowed against a Sales/Purchase Order for this item. If not set, value from Stock Settings will be used.", "fieldname": "over_delivery_receipt_allowance", "fieldtype": "Float", "label": "Over Delivery/Receipt Allowance (%)", @@ -825,6 +861,7 @@ }, { "depends_on": "eval:!doc.__islocal && !doc.is_fixed_asset", + "description": "Percentage by which over-billing is allowed against a Sales/Purchase Order for this item. If not set, value from Accounts Settings will be used.", "fieldname": "over_billing_allowance", "fieldtype": "Float", "label": "Over Billing Allowance (%)" @@ -834,7 +871,7 @@ "depends_on": "is_fixed_asset", "fieldname": "auto_create_assets", "fieldtype": "Check", - "label": "Auto Create Assets on Purchase" + "label": "Auto create assets on purchase" }, { "fieldname": "default_item_manufacturer", @@ -851,19 +888,24 @@ }, { "default": "1", + "description": "If enabled, sales from this item will be included in Sales Person and Sales Partner commission calculations", "fieldname": "grant_commission", "fieldtype": "Check", - "label": "Grant Commission" + "label": "Grant Commission", + "show_description_on_click": 1 }, { "default": "0", - "depends_on": "auto_create_assets", + "depends_on": "eval: doc.is_fixed_asset && doc.auto_create_assets", + "description": "Creates a single grouped asset instead of individual assets when purchased in bulk.", "fieldname": "is_grouped_asset", "fieldtype": "Check", - "label": "Create Grouped Asset" + "label": "Create Grouped Asset", + "show_description_on_click": 1 }, { "default": "0", + "description": "Allow stock to go below zero for this item, even if negative stock is disabled in Stock Settings.", "fieldname": "allow_negative_stock", "fieldtype": "Check", "label": "Allow Negative Stock" @@ -874,6 +916,7 @@ "label": "Inventory Settings" }, { + "depends_on": "eval: doc.is_purchase_item", "fieldname": "purchasing_tab", "fieldtype": "Tab Break", "label": "Purchasing" @@ -893,7 +936,7 @@ { "fieldname": "dashboard_tab", "fieldtype": "Tab Break", - "label": "Dashboard", + "label": "Connections", "show_dashboard": 1 }, { @@ -916,11 +959,6 @@ "fieldtype": "Int", "label": "Production Capacity" }, - { - "fieldname": "defaults_tab", - "fieldtype": "Tab Break", - "label": "Defaults" - }, { "fieldname": "section_break_znra", "fieldtype": "Section Break" @@ -988,6 +1026,50 @@ { "fieldname": "column_break_vipt", "fieldtype": "Column Break" + }, + { + "fieldname": "stock_levels_html", + "fieldtype": "HTML", + "label": "Stock Levels HTML", + "options": "
" + }, + { + "fieldname": "section_break_wfkx", + "fieldtype": "Section Break" + }, + { + "fieldname": "section_break_ylma", + "fieldtype": "Section Break" + }, + { + "fieldname": "uom_tab", + "fieldtype": "Tab Break", + "label": "UOM" + }, + { + "depends_on": "eval: !doc.__islocal && doc.is_stock_item", + "fieldname": "stock_levels_section", + "fieldtype": "Section Break", + "label": "Stock Levels" + }, + { + "fieldname": "uom_conversion_details_column", + "fieldtype": "Column Break", + "label": "UOM Conversion Details" + }, + { + "fieldname": "uom_help_html", + "fieldtype": "HTML", + "options": "