From f5352325a254a376c1413d7427d0540edf4cac71 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 1772098a4..7cfb0a428 100644 --- a/mrp_multi_level/models/product_mrp_area.py +++ b/mrp_multi_level/models/product_mrp_area.py @@ -184,14 +184,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 ca4139073..dce257246 100644 --- a/mrp_multi_level/tests/common.py +++ b/mrp_multi_level/tests/common.py @@ -29,6 +29,7 @@ class TestMrpMultiLevelCommon(SavepointCase): 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(SavepointCase): 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_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 1f874d664..934471d7e 100644 --- a/mrp_multi_level/tests/test_mrp_multi_level.py +++ b/mrp_multi_level/tests/test_mrp_multi_level.py @@ -428,3 +428,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("purchase_stock.route_warehouse0_buy").id) + ] + product_mrp_area._compute_supply_method() + self.assertEqual(product_mrp_area.supply_method, "buy") + 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")