Repository: OCA/manufacture

Issue:
[12.0] mrp_multi_level: BoM explosion ignores product variant attributes
**Impacted versions:** 12.0, 13.0

**Steps to reproduce:** (using Customizable Desk from demo data)
1. Create configurable components products
   * Desk Leg, Steel
   * Desk Leg, Aluminum
   * Desk Leg, Custom
   * White Trim Kit
   * Black Trim Kit
1. Create BoM for product template "Customizable Desk"
   * Product = Desk Leg, Steel; Apply on Variants = Legs: Steel
   * Product = Desk Leg, Aluminum; Apply on Variants = Legs: Aluminum
   * Product = Desk Leg, Custom; Apply on Variants = Legs: Custom
   * Product = White Trim Kit; Apply on Variants = Color: White
   * Product = Black Trim Kit; Apply on Variants = Color: Black
1. Set supply route to Manufacture for Customizable Desk
1. Add product MRP Area Parameters for components listed above, and for Customizable Desk (Aluminum, Black)
1. Create sale order for product variant "Customizable Desk (Aluminum, Black)"
1. Run MRP Multi Level
1. Go to MRP Inventory list and look at the component products to procure

**Current behavior:**
The user is prompted to procure all component products

**Expected behavior:**
The user should only be prompted to procure components "Desk Leg, Aluminum", and "Black Trim Kit"

![image](https://user-images.githubusercontent.com/7604932/83551096-1a997a80-a4c5-11ea-967e-923f77eae90b.png)




Discussion:

Resolving patch:
diff --git a/mrp_multi_level/wizards/mrp_multi_level.py b/mrp_multi_level/wizards/mrp_multi_level.py
--- a/mrp_multi_level/wizards/mrp_multi_level.py
+++ b/mrp_multi_level/wizards/mrp_multi_level.py
@@ -189,6 +189,8 @@ def explode_action(self, product_mrp_area_id, mrp_action_date, name, qty, action
                 ):
                     # Stop explosion.
                     continue
+                if bomline._skip_bom_line(product_mrp_area_id.product_id):
+                    continue
                 # TODO: review: mrp_transit_delay, mrp_inspection_delay
                 mrp_date_demand_2 = mrp_date_demand - timedelta(
                     days=(


Test patch:
diff --git a/mrp_multi_level/tests/common.py b/mrp_multi_level/tests/common.py
--- a/mrp_multi_level/tests/common.py
+++ b/mrp_multi_level/tests/common.py
@@ -32,6 +32,11 @@ def setUpClass(cls):
         cls.sf_2 = cls.env.ref("mrp_multi_level.product_product_sf_2")
         cls.pp_1 = cls.env.ref("mrp_multi_level.product_product_pp_1")
         cls.pp_2 = cls.env.ref("mrp_multi_level.product_product_pp_2")
+        cls.product_4b = cls.env.ref("product.product_product_4b")
+        cls.av_11 = cls.env.ref("mrp_multi_level.product_product_av_11")
+        cls.av_12 = cls.env.ref("mrp_multi_level.product_product_av_12")
+        cls.av_21 = cls.env.ref("mrp_multi_level.product_product_av_21")
+        cls.av_22 = cls.env.ref("mrp_multi_level.product_product_av_22")
         cls.company = cls.env.ref("base.main_company")
         cls.mrp_area = cls.env.ref("mrp_multi_level.mrp_area_stock_wh0")
         cls.vendor = cls.env.ref("mrp_multi_level.res_partner_lazer_tech")
@@ -201,7 +206,7 @@ def setUpClass(cls):
             cls.product_scenario_1, 18, dt_next_group, location=cls.cases_loc
         )
 
-        # Create test picking for FP-1 and FP-2:
+        # Create test picking for FP-1, FP-2 and Desk(steel, black):
         res = cls.calendar.plan_days(7 + 1, datetime.today().replace(hour=0))
         date_move = res.date()
         cls.picking_1 = cls.stock_picking_obj.create(
@@ -239,6 +244,20 @@ def setUpClass(cls):
                             "location_dest_id": cls.customer_location.id,
                         },
                     ),
+                    (
+                        0,
+                        0,
+                        {
+                            "name": "Test move product-4b",
+                            "product_id": cls.product_4b.id,
+                            "date_expected": date_move,
+                            "date": date_move,
+                            "product_uom": cls.product_4b.uom_id.id,
+                            "product_uom_qty": 150,
+                            "location_id": cls.stock_location.id,
+                            "location_dest_id": cls.customer_location.id,
+                        },
+                    ),
                 ],
             }
         )
diff --git a/mrp_multi_level/tests/test_mrp_multi_level.py b/mrp_multi_level/tests/test_mrp_multi_level.py
--- a/mrp_multi_level/tests/test_mrp_multi_level.py
+++ b/mrp_multi_level/tests/test_mrp_multi_level.py
@@ -309,3 +309,30 @@ def test_11_special_scenario_1(self):
         self.assertEqual(mrp_invs[0].to_procure, 130)
         # Net needs = 18, available on-hand = 3 -> 15
         self.assertEqual(mrp_invs[1].to_procure, 15)
+
+    def test_12_bom_line_attribute_value_skip(self):
+        """Check for the correct demand on components of a product with
+        multiple variants"""
+        product_4b_demand = self.mrp_inventory_obj.search(
+            [("product_mrp_area_id.product_id", "=", self.product_4b.id)]
+        )
+        self.assertTrue(product_4b_demand)
+        self.assertTrue(product_4b_demand.to_procure)
+        # No demand or supply for AV-12 or AV-21
+        av_12_supply = self.mrp_inventory_obj.search(
+            [("product_mrp_area_id.product_id", "=", self.av_12.id)]
+        )
+        self.assertFalse(av_12_supply)
+        av_21_supply = self.mrp_inventory_obj.search(
+            [("product_mrp_area_id.product_id", "=", self.av_21.id)]
+        )
+        self.assertFalse(av_21_supply)
+        # Supply for AV-11 and AV-22
+        av_11_supply = self.mrp_inventory_obj.search(
+            [("product_mrp_area_id.product_id", "=", self.av_11.id)]
+        )
+        self.assertTrue(av_11_supply)
+        av_22_supply = self.mrp_inventory_obj.search(
+            [("product_mrp_area_id.product_id", "=", self.av_22.id)]
+        )
+        self.assertTrue(av_22_supply)