From 3157929c30e883895a765c07c8f5ee14d13b4851 Mon Sep 17 00:00:00 2001
From: roen-odoo <roen@odoo.com>
Date: Wed, 9 Mar 2022 08:43:25 +0000
Subject: [PATCH] [FIX] mrp, sale_mrp: Avoid merging stock move different
 bom_line_id

Current behavior:
When using a product kit that have a product kit in his BoM some move line where merging when they shouldn't.
Because of this the delivered count wasn't correctly updated in any sale order using this product

Steps to reproduce:
- Create product B to manufacture with a BoM (type Kit) using component A and component B
- Create product A to manufacture with a BoM (type Kit) using product B and component A
- Create a sale order with product A
- Confirm the sale order and validate the delivery
- The delivered count of product A on the sale order stays at 0

opw-2777810

closes odoo/odoo#86545

X-original-commit: 7d1af314320547ab5e37c1d97cad22992c98565b
Signed-off-by: Tiffany Chang <tic@odoo.com>
Signed-off-by: Engels Robin (roen) <roen@odoo.com>
---
 addons/mrp/models/stock_move.py               |  6 ++
 .../sale_mrp/tests/test_sale_mrp_kit_bom.py   | 66 +++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py
index 5615e0c528f0..4897f0156a3b 100644
--- a/addons/mrp/models/stock_move.py
+++ b/addons/mrp/models/stock_move.py
@@ -120,6 +120,12 @@ class StockMove(models.Model):
         for move in self:
             move.order_finished_lot_ids = move.raw_material_production_id.lot_producing_id
 
+    @api.model
+    def _prepare_merge_moves_distinct_fields(self):
+        distinct_fields = super()._prepare_merge_moves_distinct_fields()
+        distinct_fields.append('bom_line_id')
+        return distinct_fields
+
     @api.depends('raw_material_production_id.bom_id')
     def _compute_allowed_operation_ids(self):
         for move in self:
diff --git a/addons/sale_mrp/tests/test_sale_mrp_kit_bom.py b/addons/sale_mrp/tests/test_sale_mrp_kit_bom.py
index 93c907b392ae..c91315d27beb 100644
--- a/addons/sale_mrp/tests/test_sale_mrp_kit_bom.py
+++ b/addons/sale_mrp/tests/test_sale_mrp_kit_bom.py
@@ -343,3 +343,69 @@ class TestSaleMrpKitBom(TransactionCase):
 
         # Checks the delivery amount (must be 10).
         self.assertEqual(so.order_line.qty_delivered, 10)
+
+    def test_qty_delivered_with_bom_using_kit(self):
+        """Check the quantity delivered, when one product is a kit
+        and his bom uses another product that is also a kit"""
+
+        self.kitA = self._create_product('Kit A', 'consu', 0.00)
+        self.kitB = self._create_product('Kit B', 'consu', 0.00)
+        self.compA = self._create_product('ComponentA', 'consu', 0.00)
+        self.compB = self._create_product('ComponentB', 'consu', 0.00)
+
+        # Create BoM for KitB
+        bom_product_formA = Form(self.env['mrp.bom'])
+        bom_product_formA.product_id = self.kitB
+        bom_product_formA.product_tmpl_id = self.kitB.product_tmpl_id
+        bom_product_formA.product_qty = 1.0
+        bom_product_formA.type = 'phantom'
+        with bom_product_formA.bom_line_ids.new() as bom_line:
+            bom_line.product_id = self.compA
+            bom_line.product_qty = 1
+        with bom_product_formA.bom_line_ids.new() as bom_line:
+            bom_line.product_id = self.compB
+            bom_line.product_qty = 1
+        self.bomA = bom_product_formA.save()
+
+        # Create BoM for KitA
+        bom_product_formB = Form(self.env['mrp.bom'])
+        bom_product_formB.product_id = self.kitA
+        bom_product_formB.product_tmpl_id = self.kitA.product_tmpl_id
+        bom_product_formB.product_qty = 1.0
+        bom_product_formB.type = 'phantom'
+        with bom_product_formB.bom_line_ids.new() as bom_line:
+            bom_line.product_id = self.compA
+            bom_line.product_qty = 1
+        with bom_product_formB.bom_line_ids.new() as bom_line:
+            bom_line.product_id = self.kitB
+            bom_line.product_qty = 1
+        self.bomB = bom_product_formB.save()
+
+        self.customer = self.env['res.partner'].create({
+            'name': 'customer',
+        })
+
+        so = self.env['sale.order'].create({
+            'partner_id': self.customer.id,
+            'order_line': [
+                (0, 0, {
+                    'name': self.kitA.name,
+                    'product_id': self.kitA.id,
+                    'product_uom_qty': 1.0,
+                    'product_uom': self.kitA.uom_id.id,
+                    'price_unit': 1,
+                    'tax_id': False,
+                })],
+        })
+        so.action_confirm()
+
+        self.assertTrue(so.picking_ids)
+        self.assertEqual(so.order_line.qty_delivered, 0)
+
+        picking = so.picking_ids
+        action = picking.button_validate()
+        wizard = Form(self.env[action['res_model']].with_context(action['context'])).save()
+        wizard.process()
+
+        # Checks the delivery amount (must be 1).
+        self.assertEqual(so.order_line.qty_delivered, 1)
-- 
GitLab