From 6ecf5b1ec81c53c422c59df2ee6bef3deed5b99e Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 27 Sep 2023 20:02:05 +0530 Subject: [PATCH] fix: incorrect qty for material request in Production Plan (#37270) (cherry picked from commit 8fe4a4d3aa7857e5e241bcb7145065753ab8b4cb) --- .../production_plan/production_plan.py | 27 ++++----- .../production_plan/test_production_plan.py | 58 +++++++++++++++++++ 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index fcaae79d6c5e..52bfeafea515 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -1508,6 +1508,10 @@ def get_items_for_material_requests(doc, warehouses=None, get_parent_warehouse_d def get_materials_from_other_locations(item, warehouses, new_mr_items, company): from erpnext.stock.doctype.pick_list.pick_list import get_available_item_locations + stock_uom, purchase_uom = frappe.db.get_value( + "Item", item.get("item_code"), ["stock_uom", "purchase_uom"] + ) + locations = get_available_item_locations( item.get("item_code"), warehouses, item.get("quantity"), company, ignore_validation=True ) @@ -1518,6 +1522,10 @@ def get_materials_from_other_locations(item, warehouses, new_mr_items, company): if required_qty <= 0: return + conversion_factor = 1.0 + if purchase_uom != stock_uom and purchase_uom == item["uom"]: + conversion_factor = get_uom_conversion_factor(item["item_code"], item["uom"]) + new_dict = copy.deepcopy(item) quantity = required_qty if d.get("qty") > required_qty else d.get("qty") @@ -1530,25 +1538,14 @@ def get_materials_from_other_locations(item, warehouses, new_mr_items, company): } ) - required_qty -= quantity + required_qty -= quantity / conversion_factor new_mr_items.append(new_dict) # raise purchase request for remaining qty - if required_qty: - stock_uom, purchase_uom = frappe.db.get_value( - "Item", item["item_code"], ["stock_uom", "purchase_uom"] - ) - - if purchase_uom != stock_uom and purchase_uom == item["uom"]: - conversion_factor = get_uom_conversion_factor(item["item_code"], item["uom"]) - if not (conversion_factor or frappe.flags.show_qty_in_stock_uom): - frappe.throw( - _("UOM Conversion factor ({0} -> {1}) not found for item: {2}").format( - purchase_uom, stock_uom, item["item_code"] - ) - ) - required_qty = required_qty / conversion_factor + precision = frappe.get_precision("Material Request Plan Item", "quantity") + if flt(required_qty, precision) > 0: + required_qty = required_qty if frappe.db.get_value("UOM", purchase_uom, "must_be_whole_number"): required_qty = ceil(required_qty) diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index 9ea746cbd8b9..c276f6a91b91 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -1219,6 +1219,64 @@ def test_skip_available_qty_for_sub_assembly_items(self): if row.item_code == "SubAssembly2 For SUB Test": self.assertEqual(row.quantity, 10) + def test_transfer_and_purchase_mrp_for_purchase_uom(self): + from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + + bom_tree = { + "Test FG Item INK PEN": { + "Test RM Item INK": {}, + } + } + + parent_bom = create_nested_bom(bom_tree, prefix="") + if not frappe.db.exists("UOM Conversion Detail", {"parent": "Test RM Item INK", "uom": "Kg"}): + doc = frappe.get_doc("Item", "Test RM Item INK") + doc.purchase_uom = "Kg" + doc.append("uoms", {"uom": "Kg", "conversion_factor": 0.5}) + doc.save() + + wh1 = create_warehouse("PNE Warehouse", company="_Test Company") + wh2 = create_warehouse("MBE Warehouse", company="_Test Company") + mrp_warhouse = create_warehouse("MRPBE Warehouse", company="_Test Company") + + make_stock_entry( + item_code="Test RM Item INK", + qty=2, + rate=100, + target=wh1, + ) + + make_stock_entry( + item_code="Test RM Item INK", + qty=2, + rate=100, + target=wh2, + ) + + plan = create_production_plan( + item_code=parent_bom.item, + planned_qty=10, + do_not_submit=1, + warehouse="_Test Warehouse - _TC", + ) + + plan.for_warehouse = mrp_warhouse + + items = get_items_for_material_requests( + plan.as_dict(), warehouses=[{"warehouse": wh1}, {"warehouse": wh2}] + ) + + for row in items: + row = frappe._dict(row) + if row.material_request_type == "Material Transfer": + self.assertTrue(row.from_warehouse in [wh1, wh2]) + self.assertEqual(row.quantity, 2) + + if row.material_request_type == "Purchase": + self.assertTrue(row.warehouse == mrp_warhouse) + self.assertEqual(row.quantity, 12) + def create_production_plan(**args): """