diff --git a/mrp_bom_version/models/__init__.py b/mrp_bom_version/models/__init__.py index 8ec9ccdfe9d..e58e22e69a1 100644 --- a/mrp_bom_version/models/__init__.py +++ b/mrp_bom_version/models/__init__.py @@ -3,3 +3,4 @@ from . import mrp_bom from . import res_config +from . import stock_move diff --git a/mrp_bom_version/models/stock_move.py b/mrp_bom_version/models/stock_move.py new file mode 100644 index 00000000000..9c6a7fd75d4 --- /dev/null +++ b/mrp_bom_version/models/stock_move.py @@ -0,0 +1,14 @@ +# Copyright 2025 Akretion (https://www.akretion.com). +# @author Kévin Roche + +from odoo import models + + +class StockMove(models.Model): + _inherit = "stock.move" + + def _compute_kit_quantities(self, product_id, kit_qty, kit_bom, filters): + if len(self.bom_line_id.bom_id) == 1 and self.bom_line_id.bom_id != kit_bom: + if self.bom_line_id.bom_id.version < kit_bom.version: + kit_bom = self.bom_line_id.bom_id + return super()._compute_kit_quantities(product_id, kit_qty, kit_bom, filters) diff --git a/mrp_bom_version/tests/test_mrp_bom_version.py b/mrp_bom_version/tests/test_mrp_bom_version.py index 9aaf978faa0..d53c33944a7 100644 --- a/mrp_bom_version/tests/test_mrp_bom_version.py +++ b/mrp_bom_version/tests/test_mrp_bom_version.py @@ -85,3 +85,78 @@ def test_mrp_bom_versioning(self): self.assertEqual( new_bom.state, "draft", "New version must be created in 'draft' state" ) + + def test_historical_bom_still_used_in_picking(self): + self.mrp_bom.button_activate() + kit_product = self.mrp_bom.product_tmpl_id.product_variant_id + + picking = self.env["stock.picking"].create( + { + "partner_id": self.env.ref("base.res_partner_1").id, + "picking_type_id": self.env.ref("stock.picking_type_out").id, + "location_id": self.env.ref("stock.stock_location_stock").id, + "location_dest_id": self.env.ref("stock.stock_location_customers").id, + } + ) + bom_line_5 = self.mrp_bom.bom_line_ids.filtered( + lambda l: l.product_id == self.env.ref("product.product_product_5") + ) + bom_line_6 = self.mrp_bom.bom_line_ids.filtered( + lambda l: l.product_id == self.env.ref("product.product_product_6") + ) + + self.env["stock.move"].create( + { + "name": "Kit Move – compo 5", + "product_id": self.env.ref("product.product_product_5").id, + "product_uom_qty": 1, + "product_uom": kit_product.uom_id.id, + "picking_id": picking.id, + "location_id": picking.location_id.id, + "location_dest_id": picking.location_dest_id.id, + "bom_line_id": bom_line_5.id, + } + ) + self.env["stock.move"].create( + { + "name": "Kit Move – compo 6", + "product_id": self.env.ref("product.product_product_6").id, + "product_uom_qty": 1, + "product_uom": kit_product.uom_id.id, + "picking_id": picking.id, + "location_id": picking.location_id.id, + "location_dest_id": picking.location_dest_id.id, + "bom_line_id": bom_line_6.id, + } + ) + + picking.action_assign() + picking.button_validate() + + filters = { + "incoming_moves": lambda m: m.id in picking.move_ids.ids, + "outgoing_moves": lambda m: m.id not in picking.move_ids.ids, + } + + qty = picking.move_ids._compute_kit_quantities( + product_id=kit_product, + kit_qty=1, + kit_bom=self.mrp_bom, + filters=filters, + ) + self.assertEqual(qty, 1.0) + + self.mrp_bom.button_new_version() + new_bom = self.bom_model.with_context(active_test=False).search( + [ + ("previous_bom_id", "=", self.mrp_bom.id), + ], + limit=1, + ) + qty2 = picking.move_ids._compute_kit_quantities( + product_id=kit_product, + kit_qty=1, + kit_bom=new_bom, + filters=filters, + ) + self.assertEqual(qty2, 1.0)