From 8acdef9cf60d5413a1527fe38e4276810d8d2d5d Mon Sep 17 00:00:00 2001 From: BernatPForgeFlow Date: Wed, 8 Feb 2023 16:37:41 +0100 Subject: [PATCH] [IMP] mrp_multi_level: Supply method computation for MRP Parameters For each MRP Parameter, we will calculate its supply method based on the procurement rules path. We will go back in the rules until we find that the action is "buy" or "manufacture", or until the action is "Pull From" or "Pull & Push" and the supply method is "Take from Stock". This means we will show what the latest rule is if we were to do a procurement. Although it would be possible that the final action does not end up being executed if stock already exists in one of the intermediate locations. --- mrp_multi_level/demo/product_product_demo.xml | 8 ++++++ mrp_multi_level/models/product_mrp_area.py | 28 +++++++++++++++---- mrp_multi_level/tests/common.py | 17 +++++++++++ mrp_multi_level/tests/test_mrp_multi_level.py | 19 +++++++++++++ 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/mrp_multi_level/demo/product_product_demo.xml b/mrp_multi_level/demo/product_product_demo.xml index f9b45c103..aaeb05e65 100644 --- a/mrp_multi_level/demo/product_product_demo.xml +++ b/mrp_multi_level/demo/product_product_demo.xml @@ -36,6 +36,14 @@ eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]" /> + + FP-4 + + product + + + 2 + diff --git a/mrp_multi_level/models/product_mrp_area.py b/mrp_multi_level/models/product_mrp_area.py index 99e3bff7a..0b72d08eb 100644 --- a/mrp_multi_level/models/product_mrp_area.py +++ b/mrp_multi_level/models/product_mrp_area.py @@ -188,14 +188,30 @@ class ProductMRPArea(models.Model): "company_id": rec.mrp_area_id.company_id, } rule = group_obj._get_rule(rec.product_id, proc_loc, values) - if ( - rule.action == "manufacture" + if not rule: + rec.supply_method = "none" + continue + # Keep getting the rule for the product and the source location until the + # action is "buy" or "manufacture". Or until the action is "Pull From" or + # "Pull & Push" and the supply method is "Take from Stock". + while rule.action not in ("buy", "manufacture") and rule.procure_method in ( + "make_to_order", + "mts_else_mto", + ): + new_rule = group_obj._get_rule( + rec.product_id, rule.location_src_id, values + ) + if not new_rule: + break + rule = new_rule + # Determine the supply method based on the final rule. + rec.supply_method = ( + "phantom" + if rule.action == "manufacture" and rec.product_id.product_tmpl_id.bom_ids and rec.product_id.product_tmpl_id.bom_ids[0].type == "phantom" - ): - rec.supply_method = "phantom" - else: - rec.supply_method = rule.action if rule else "none" + else rule.action + ) @api.depends( "mrp_area_id", "supply_method", "product_id.route_ids", "product_id.seller_ids" diff --git a/mrp_multi_level/tests/common.py b/mrp_multi_level/tests/common.py index b8bc051f3..73d74f3b0 100644 --- a/mrp_multi_level/tests/common.py +++ b/mrp_multi_level/tests/common.py @@ -29,6 +29,7 @@ class TestMrpMultiLevelCommon(TransactionCase): cls.fp_1 = cls.env.ref("mrp_multi_level.product_product_fp_1") cls.fp_2 = cls.env.ref("mrp_multi_level.product_product_fp_2") cls.fp_3 = cls.env.ref("mrp_multi_level.product_product_fp_3") + cls.fp_4 = cls.env.ref("mrp_multi_level.product_product_fp_4") cls.sf_1 = cls.env.ref("mrp_multi_level.product_product_sf_1") cls.sf_2 = cls.env.ref("mrp_multi_level.product_product_sf_2") cls.sf_3 = cls.env.ref("mrp_multi_level.product_product_sf_3") @@ -219,6 +220,22 @@ class TestMrpMultiLevelCommon(TransactionCase): cls.product_mrp_area_obj.create( {"product_id": cls.prod_uom_test.id, "mrp_area_id": cls.mrp_area.id} ) + # Product MRP Parameter to test supply method computation + cls.env.ref("stock.route_warehouse0_mto").active = True + cls.env["stock.rule"].create( + { + "name": "WH2: Main Area → Secondary Area (MTO)", + "action": "pull", + "picking_type_id": cls.env.ref("stock.picking_type_in").id, + "location_src_id": cls.env.ref("stock.stock_location_stock").id, + "location_dest_id": cls.sec_loc.id, + "route_id": cls.env.ref("stock.route_warehouse0_mto").id, + "procure_method": "mts_else_mto", + } + ) + cls.product_mrp_area_obj.create( + {"product_id": cls.fp_4.id, "mrp_area_id": cls.secondary_area.id} + ) # Create pickings for Scenario 1: dt_base = cls.calendar.plan_days(3 + 1, datetime.today()) diff --git a/mrp_multi_level/tests/test_mrp_multi_level.py b/mrp_multi_level/tests/test_mrp_multi_level.py index 9b8743113..8bcf81f7e 100644 --- a/mrp_multi_level/tests/test_mrp_multi_level.py +++ b/mrp_multi_level/tests/test_mrp_multi_level.py @@ -426,3 +426,22 @@ class TestMrpMultiLevel(TestMrpMultiLevelCommon): [("product_mrp_area_id.product_id", "=", self.pp_4.id)] ) self.assertEqual(len(pp_4_planned_orders), 1) + + def test_17_supply_method(self): + """Test supply method computation.""" + self.fp_4.route_ids = [(5, 0, 0)] + product_mrp_area = self.product_mrp_area_obj.search( + [("product_id", "=", self.fp_4.id)] + ) + self.assertEqual(product_mrp_area.supply_method, "none") + self.fp_4.route_ids = [(4, self.env.ref("stock.route_warehouse0_mto").id)] + product_mrp_area._compute_supply_method() + self.assertEqual(product_mrp_area.supply_method, "pull") + self.fp_4.route_ids = [(4, self.env.ref("mrp.route_warehouse0_manufacture").id)] + product_mrp_area._compute_supply_method() + self.assertEqual(product_mrp_area.supply_method, "manufacture") + self.fp_4.route_ids = [ + (4, self.env.ref("purchase_stock.route_warehouse0_buy").id) + ] + product_mrp_area._compute_supply_method() + self.assertEqual(product_mrp_area.supply_method, "buy")