fix: incorrect Reserved Qty for Production Plan in BIN for multi-uom case
(cherry picked from commit 2f632d031aa53e1e03763623449e7cde7dca3c55)
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index a988bad..d8cc8f6 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -1539,7 +1539,7 @@
frappe.qb.from_(table)
.inner_join(child)
.on(table.name == child.parent)
- .select(Sum(child.required_bom_qty * IfNull(child.conversion_factor, 1.0)))
+ .select(Sum(child.quantity * IfNull(child.conversion_factor, 1.0)))
.where(
(table.docstatus == 1)
& (child.item_code == item_code)
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index fcfba7f..f60dbfc 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -933,6 +933,54 @@
self.assertEqual(after_qty, before_qty)
+ def test_resered_qty_for_production_plan_for_material_requests_with_multi_UOM(self):
+ from erpnext.stock.utils import get_or_make_bin
+
+ fg_item = make_item(properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1"}).name
+ bom_item = make_item(
+ properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1", "purchase_uom": "Nos"}
+ ).name
+
+ if not frappe.db.exists("UOM Conversion Detail", {"parent": bom_item, "uom": "Nos"}):
+ doc = frappe.get_doc("Item", bom_item)
+ doc.append("uoms", {"uom": "Nos", "conversion_factor": 25})
+ doc.save()
+
+ make_bom(item=fg_item, raw_materials=[bom_item], source_warehouse="_Test Warehouse - _TC")
+
+ bin_name = get_or_make_bin(bom_item, "_Test Warehouse - _TC")
+ before_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan"))
+
+ pln = create_production_plan(
+ item_code=fg_item, planned_qty=100, ignore_existing_ordered_qty=1, stock_uom="_Test UOM 1"
+ )
+
+ for row in pln.mr_items:
+ self.assertEqual(row.uom, "Nos")
+ self.assertEqual(row.quantity, 4)
+
+ reserved_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan"))
+ self.assertEqual(reserved_qty - before_qty, 100.0)
+
+ pln.submit_material_request = 1
+ pln.make_work_order()
+
+ for work_order in frappe.get_all(
+ "Work Order",
+ fields=["name"],
+ filters={"production_plan": pln.name},
+ ):
+ wo_doc = frappe.get_doc("Work Order", work_order.name)
+ wo_doc.source_warehouse = "_Test Warehouse - _TC"
+ wo_doc.wip_warehouse = "_Test Warehouse 1 - _TC"
+ wo_doc.fg_warehouse = "_Test Warehouse - _TC"
+ wo_doc.submit()
+
+ reserved_qty_after_mr = flt(
+ frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")
+ )
+ self.assertEqual(reserved_qty_after_mr, before_qty)
+
def test_skip_available_qty_for_sub_assembly_items(self):
from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index ee247fd..00b1b20 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -118,8 +118,8 @@
self.title = _("{0} Request for {1}").format(_(self.material_request_type), items)[:100]
def on_submit(self):
- self.update_requested_qty()
self.update_requested_qty_in_production_plan()
+ self.update_requested_qty()
if self.material_request_type == "Purchase":
self.validate_budget()
@@ -178,8 +178,8 @@
)
def on_cancel(self):
- self.update_requested_qty()
self.update_requested_qty_in_production_plan()
+ self.update_requested_qty()
def get_mr_items_ordered_qty(self, mr_items):
mr_items_ordered_qty = {}
@@ -270,7 +270,13 @@
item_wh_list.append([d.item_code, d.warehouse])
for item_code, warehouse in item_wh_list:
- update_bin_qty(item_code, warehouse, {"indented_qty": get_indented_qty(item_code, warehouse)})
+ update_bin_qty(
+ item_code,
+ warehouse,
+ {
+ "indented_qty": get_indented_qty(item_code, warehouse),
+ },
+ )
def update_requested_qty_in_production_plan(self):
production_plans = []