From 1e60076ade54b37c67b25ba8f655d7eaddbf2dfe Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 2 Dec 2025 17:13:52 +0530 Subject: [PATCH] fix: UX for auto created material request via reorder --- erpnext/stock/doctype/item/item.js | 14 ++++++- .../doctype/item_reorder/item_reorder.json | 15 ++++++-- .../material_request/material_request.json | 9 ++++- .../material_request/material_request.py | 1 + .../material_request_item.json | 38 ++++++++++++++++++- .../material_request_item.py | 3 ++ erpnext/stock/doctype/warehouse/warehouse.py | 22 +++++++++++ erpnext/stock/reorder_item.py | 8 ++++ 8 files changed, 102 insertions(+), 8 deletions(-) diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 09f4c1710bd..466ab532d02 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -301,6 +301,14 @@ frappe.ui.form.on("Item Reorder", { var type = frm.doc.default_material_request_type; row.material_request_type = type == "Material Transfer" ? "Transfer" : type; }, + + warehouse_group(frm, cdt, cdn) { + let row = locals[cdt][cdn]; + + if (!row.warehouse_group) { + frappe.throw(__("Please select the Warehouse first")); + } + }, }); frappe.ui.form.on("Item Customer Detail", { @@ -474,8 +482,12 @@ $.extend(erpnext.item, { cdt, cdn ) { + let row = locals[cdt][cdn]; return { - filters: { is_group: 1 }, + query: "erpnext.stock.doctype.warehouse.warehouse.get_warehouses_for_reorder", + filters: { + warehouse: row.warehouse, + }, }; }; diff --git a/erpnext/stock/doctype/item_reorder/item_reorder.json b/erpnext/stock/doctype/item_reorder/item_reorder.json index e9742322418..a0b365cf601 100644 --- a/erpnext/stock/doctype/item_reorder/item_reorder.json +++ b/erpnext/stock/doctype/item_reorder/item_reorder.json @@ -7,21 +7,23 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "warehouse_group", "warehouse", + "warehouse_group", "warehouse_reorder_level", "warehouse_reorder_qty", "material_request_type" ], "fields": [ { + "columns": 3, "fieldname": "warehouse_group", "fieldtype": "Link", "in_list_view": 1, - "label": "Check in (group)", + "label": "Check Availability in Warehouse", "options": "Warehouse" }, { + "columns": 2, "fieldname": "warehouse", "fieldtype": "Link", "in_list_view": 1, @@ -30,18 +32,21 @@ "reqd": 1 }, { + "columns": 2, "fieldname": "warehouse_reorder_level", "fieldtype": "Float", "in_list_view": 1, "label": "Re-order Level" }, { + "columns": 2, "fieldname": "warehouse_reorder_qty", "fieldtype": "Float", "in_list_view": 1, "label": "Re-order Qty" }, { + "columns": 2, "fieldname": "material_request_type", "fieldtype": "Select", "in_list_view": 1, @@ -54,13 +59,15 @@ "in_create": 1, "istable": 1, "links": [], - "modified": "2024-03-27 13:09:55.227275", + "modified": "2025-12-02 16:02:23.254963", "modified_by": "Administrator", "module": "Stock", "name": "Item Reorder", + "naming_rule": "Random", "owner": "Administrator", "permissions": [], + "row_format": "Dynamic", "sort_field": "creation", "sort_order": "ASC", "states": [] -} \ No newline at end of file +} diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json index 3d125c376e0..02183bcfad3 100644 --- a/erpnext/stock/doctype/material_request/material_request.json +++ b/erpnext/stock/doctype/material_request/material_request.json @@ -13,6 +13,7 @@ "material_request_type", "customer", "company", + "auto_created_via_reorder", "column_break_2", "transaction_date", "schedule_date", @@ -362,13 +363,19 @@ "fieldtype": "Data", "is_virtual": 1, "label": "Last Scanned Warehouse" + }, + { + "default": "0", + "fieldname": "auto_created_via_reorder", + "fieldtype": "Check", + "label": "Auto Created (Reorder)" } ], "icon": "fa fa-ticket", "idx": 70, "is_submittable": 1, "links": [], - "modified": "2025-07-31 17:19:01.166208", + "modified": "2025-12-02 13:56:33.001436", "modified_by": "Administrator", "module": "Stock", "name": "Material Request", diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 6f12fd05ea7..ce2e0421d8e 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -39,6 +39,7 @@ class MaterialRequest(BuyingController): from erpnext.stock.doctype.material_request_item.material_request_item import MaterialRequestItem amended_from: DF.Link | None + auto_created_via_reorder: DF.Check buying_price_list: DF.Link | None company: DF.Link customer: DF.Link | None diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json index 7789ee52a60..51eca0d3892 100644 --- a/erpnext/stock/doctype/material_request_item/material_request_item.json +++ b/erpnext/stock/doctype/material_request_item/material_request_item.json @@ -59,6 +59,11 @@ "production_plan", "material_request_plan_item", "job_card_item", + "item_reorder_section", + "projected_on_hand", + "column_break_fdjh", + "reorder_level", + "reorder_qty", "section_break_46", "page_break" ], @@ -485,21 +490,50 @@ "options": "currency", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "item_reorder_section", + "fieldtype": "Section Break", + "label": "Item Reorder" + }, + { + "fieldname": "column_break_fdjh", + "fieldtype": "Column Break" + }, + { + "fieldname": "reorder_level", + "fieldtype": "Float", + "label": "Reorder Level", + "read_only": 1 + }, + { + "fieldname": "reorder_qty", + "fieldtype": "Float", + "label": "Reorder Qty", + "read_only": 1 + }, + { + "description": "If the reorder check is set at the Group warehouse level, the available quantity becomes the sum of the projected quantities of all its child warehouses.", + "fieldname": "projected_on_hand", + "fieldtype": "Float", + "label": "Projected On Hand", + "read_only": 1 } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2024-03-27 13:10:05.224712", + "modified": "2025-12-02 14:14:45.972664", "modified_by": "Administrator", "module": "Stock", "name": "Material Request Item", "naming_rule": "Random", "owner": "Administrator", "permissions": [], + "row_format": "Dynamic", "sort_field": "creation", "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.py b/erpnext/stock/doctype/material_request_item/material_request_item.py index d23d041f5f4..e36d4e66549 100644 --- a/erpnext/stock/doctype/material_request_item/material_request_item.py +++ b/erpnext/stock/doctype/material_request_item/material_request_item.py @@ -44,10 +44,13 @@ class MaterialRequestItem(Document): price_list_rate: DF.Currency production_plan: DF.Link | None project: DF.Link | None + projected_on_hand: DF.Float projected_qty: DF.Float qty: DF.Float rate: DF.Currency received_qty: DF.Float + reorder_level: DF.Float + reorder_qty: DF.Float sales_order: DF.Link | None sales_order_item: DF.Data | None schedule_date: DF.Date diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index 32f5e61d9a5..c2c553457b0 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -295,3 +295,25 @@ def apply_warehouse_filter(query, sle, filters): query = query.where(ExistsCriterion(child_query)) return query + + +@frappe.whitelist() +@frappe.validate_and_sanitize_search_inputs +def get_warehouses_for_reorder(doctype, txt, searchfield, start, page_len, filters): + filters = frappe._dict(filters or {}) + + if filters.warehouse and not frappe.db.exists("Warehouse", filters.warehouse): + frappe.throw(_("Warehouse {0} does not exist").format(filters.warehouse)) + + doctype = frappe.qb.DocType("Warehouse") + + warehouses = ( + frappe.qb.from_(doctype) + .select(doctype.name) + .where(doctype.disabled == 0) + .where((doctype.is_group == 1) | (doctype.name == filters.warehouse)) + .orderby(doctype.name) + .run(as_list=True) + ) + + return warehouses diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py index 363b0e0bbe4..4e820c88d9b 100644 --- a/erpnext/stock/reorder_item.py +++ b/erpnext/stock/reorder_item.py @@ -60,6 +60,7 @@ def _reorder_item(): else: projected_qty = flt(item_warehouse_projected_qty.get(kwargs.item_code, {}).get(kwargs.warehouse)) + original_reorder_qty = reorder_qty if (reorder_level or reorder_qty) and projected_qty <= reorder_level: deficiency = reorder_level - projected_qty if deficiency > reorder_qty: @@ -73,6 +74,9 @@ def _reorder_item(): "warehouse": kwargs.warehouse, "reorder_qty": reorder_qty, "item_details": kwargs.item_details, + "projected_on_hand": projected_qty, + "reorder_level": reorder_level, + "original_reorder_qty": original_reorder_qty, } ) @@ -240,6 +244,7 @@ def create_material_request(material_requests): mr.update( { "company": company, + "auto_created_via_reorder": 1, "transaction_date": nowdate(), "material_request_type": "Material Transfer" if request_type == "Transfer" @@ -285,6 +290,9 @@ def create_material_request(material_requests): "description": item.description, "item_group": item.item_group, "brand": item.brand, + "reorder_qty": d.original_reorder_qty, + "projected_on_hand": d.projected_on_hand, + "reorder_level": d.reorder_level, }, )