From e4b66dc731572927741e05ac92d0f41a894e3392 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 7 Aug 2026 22:20:38 +0530 Subject: [PATCH] test: min order qty conversion takes the grid ceiling Covers both rounding brackets, an exactly representable conversion, the no-minimum path, and the ceiling through the plan items and materials from other locations flows. --- .../production_plan/test_production_plan.py | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index a7891b10be0..2732aa7046e 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -2384,6 +2384,73 @@ class TestProductionPlan(ERPNextTestSuite): self.assertEqual(items_by_type["Material Transfer"].get("quantity"), 7.0) self.assertEqual(items_by_type["Purchase"].get("quantity"), 1000.0) + def test_min_order_qty_conversion_takes_grid_ceiling(self): + from erpnext.manufacturing.doctype.production_plan.services.material_request import ( + _quantity_in_purchase_uom, + ) + + original_precision = frappe.db.get_default("float_precision") + frappe.db.set_default("float_precision", "3") + self.addCleanup(frappe.db.set_default, "float_precision", original_precision) + + self.assertEqual(_quantity_in_purchase_uom(50000, 453.592292197, 50000), 110.232) + self.assertEqual(_quantity_in_purchase_uom(2000, 0.453592, 2000), 4409.249) + self.assertEqual(_quantity_in_purchase_uom(10, 0.5, 10), 20.0) + self.assertEqual(_quantity_in_purchase_uom(50000, 453.592292197), 110.231) + + def test_min_order_qty_grid_ceiling_in_plan_items(self): + original_precision = frappe.db.get_default("float_precision") + frappe.db.set_default("float_precision", "3") + self.addCleanup(frappe.db.set_default, "float_precision", original_precision) + + conversion_factor = 453.592292197 + fg_item = make_item(properties={"is_stock_item": 1}).name + rm_item = make_item( + properties={"is_stock_item": 1, "min_order_qty": 50000, "purchase_uom": "_Test UOM 1"}, + uoms=[{"uom": "_Test UOM 1", "conversion_factor": conversion_factor}], + ).name + + make_bom(item=fg_item, raw_materials=[rm_item], source_warehouse="_Test Warehouse - _TC") + + pln = create_production_plan(item_code=fg_item, planned_qty=1, do_not_submit=1) + pln.consider_minimum_order_qty = 1 + mr_items = get_items_for_material_requests(pln.as_dict()) + + self.assertEqual(mr_items[0].get("quantity"), 110.232) + self.assertGreaterEqual(mr_items[0].get("quantity") * conversion_factor, 50000) + + def test_min_order_qty_grid_ceiling_from_other_locations(self): + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + + original_precision = frappe.db.get_default("float_precision") + frappe.db.set_default("float_precision", "3") + self.addCleanup(frappe.db.set_default, "float_precision", original_precision) + + conversion_factor = 453.592292197 + fg_item = make_item(properties={"is_stock_item": 1}).name + rm_item = make_item( + properties={"is_stock_item": 1, "min_order_qty": 50000, "purchase_uom": "_Test UOM 1"}, + uoms=[{"uom": "_Test UOM 1", "conversion_factor": conversion_factor}], + ).name + + rm_warehouse = create_warehouse("MOQ Ceiling RM Warehouse", company="_Test Company") + source_warehouse = create_warehouse("MOQ Ceiling Source Warehouse", company="_Test Company") + make_stock_entry(item_code=rm_item, qty=4, rate=100, target=source_warehouse) + + make_bom(item=fg_item, raw_materials=[rm_item], source_warehouse="_Test Warehouse - _TC") + + pln = create_production_plan(item_code=fg_item, planned_qty=10, do_not_submit=1) + pln.for_warehouse = rm_warehouse + pln.consider_minimum_order_qty = 1 + pln.ignore_existing_ordered_qty = 1 + mr_items = get_items_for_material_requests( + pln.as_dict(), warehouses=[{"warehouse": source_warehouse}] + ) + + rows_by_type = {d.get("material_request_type"): d for d in mr_items} + self.assertEqual(rows_by_type["Material Transfer"].get("quantity"), 4) + self.assertEqual(rows_by_type["Purchase"].get("quantity"), 110.232) + def test_fg_item_quantity(self): fg_item = make_item(properties={"is_stock_item": 1}).name rm_item = make_item(properties={"is_stock_item": 1}).name