From ce6cc5240e6c8bc517523d1d711a4d0bad3b209a Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 22 Oct 2026 16:36:22 +0000 Subject: [PATCH] fix(manufacturing): skip warehouse user permission check for work order available qty --- erpnext/manufacturing/doctype/work_order/work_order.py | 6 +++--- erpnext/stock/utils.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 808777b02a1..5906a3f6db3 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -36,7 +36,7 @@ from erpnext.stock.doctype.batch.batch import make_batch from erpnext.stock.doctype.item.item import get_item_defaults, validate_end_of_life from erpnext.stock.doctype.serial_no.serial_no import get_available_serial_nos, get_serial_nos from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty -from erpnext.stock.utils import get_bin, get_latest_stock_qty, validate_warehouse_company +from erpnext.stock.utils import _get_latest_stock_qty, get_bin, validate_warehouse_company from erpnext.utilities.transaction_base import validate_uom_is_integer @@ -1230,10 +1230,10 @@ class WorkOrder(Document): def set_available_qty(self): for d in self.get("required_items"): if d.source_warehouse: - d.available_qty_at_source_warehouse = get_latest_stock_qty(d.item_code, d.source_warehouse) + d.available_qty_at_source_warehouse = _get_latest_stock_qty(d.item_code, d.source_warehouse) if self.wip_warehouse: - d.available_qty_at_wip_warehouse = get_latest_stock_qty(d.item_code, self.wip_warehouse) + d.available_qty_at_wip_warehouse = _get_latest_stock_qty(d.item_code, self.wip_warehouse) def set_required_items(self, reset_only_qty=False): """set required_items for production to keep track of reserved qty""" diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index 28fef8bc43a..c590ebbd3c7 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -202,11 +202,17 @@ def get_serial_nos_data(serial_nos): @frappe.whitelist() def get_latest_stock_qty(item_code, warehouse=None): + if warehouse: + erpnext.require_user_permission("Warehouse", warehouse) + + return _get_latest_stock_qty(item_code, warehouse) + + +def _get_latest_stock_qty(item_code, warehouse=None): + # no warehouse check here: Work Order reads the warehouses already on the document # same guard as get_stock_balance above, which returns the same Bin quantity. Loser-free for # the only caller: Work Order write is held by Manufacturing User, who holds Item read. frappe.has_permission("Item", "read", throw=True) - if warehouse: - erpnext.require_user_permission("Warehouse", warehouse) values, condition = [item_code], "" if warehouse: