diff --git a/mrp_lot_number_propagation/models/mrp_production.py b/mrp_lot_number_propagation/models/mrp_production.py index 40ea6e6fd..8d8b090d4 100644 --- a/mrp_lot_number_propagation/models/mrp_production.py +++ b/mrp_lot_number_propagation/models/mrp_production.py @@ -111,13 +111,30 @@ class MrpProduction(models.Model): and m.state not in ("done", "cancel") ) if finish_moves and not finish_moves.quantity_done: - lot = self.env["stock.production.lot"].create( - { - "product_id": order.product_id.id, - "company_id": order.company_id.id, - "name": order.propagated_lot_producing, - } + lot_model = self.env["stock.production.lot"] + lot = lot_model.search( + [ + ("product_id", "=", order.product_id.id), + ("company_id", "=", order.company_id.id), + ("name", "=", order.propagated_lot_producing), + ], + limit=1, ) + if lot.quant_ids: + raise UserError( + _( + "Lot/Serial number %s already exists and has been used. " + "Unable to propagate it." + ) + ) + if not lot: + lot = self.env["stock.production.lot"].create( + { + "product_id": order.product_id.id, + "company_id": order.company_id.id, + "name": order.propagated_lot_producing, + } + ) order.with_context(lot_propagation=True).lot_producing_id = lot def write(self, vals): diff --git a/mrp_lot_number_propagation/tests/test_mrp_production.py b/mrp_lot_number_propagation/tests/test_mrp_production.py index 90d22ede9..b464e9a44 100644 --- a/mrp_lot_number_propagation/tests/test_mrp_production.py +++ b/mrp_lot_number_propagation/tests/test_mrp_production.py @@ -57,6 +57,47 @@ class TestMrpProduction(Common): self.order.button_mark_done() self.assertEqual(self.order.lot_producing_id.name, self.LOT_NAME) + def test_order_post_inventory_lot_already_exists_but_not_used(self): + self._update_stock_component_qty(self.order) + self.order.action_confirm() + self._set_qty_done(self.order) + self.assertEqual(self.order.propagated_lot_producing, self.LOT_NAME) + # Create a lot with the same number for the finished product + # without any stock/quants (so not used at all) before validating the MO + existing_lot = self.env["stock.production.lot"].create( + { + "product_id": self.order.product_id.id, + "company_id": self.order.company_id.id, + "name": self.order.propagated_lot_producing, + } + ) + self.order.button_mark_done() + self.assertEqual(self.order.lot_producing_id, existing_lot) + + def test_order_post_inventory_lot_already_exists_and_used(self): + self._update_stock_component_qty(self.order) + self.order.action_confirm() + self._set_qty_done(self.order) + self.assertEqual(self.order.propagated_lot_producing, self.LOT_NAME) + # Create a lot with the same number for the finished product + # with some stock/quants (so it is considered as used) before + # validating the MO + existing_lot = self.env["stock.production.lot"].create( + { + "product_id": self.order.product_id.id, + "company_id": self.order.company_id.id, + "name": self.order.propagated_lot_producing, + } + ) + self._update_qty_in_location( + self.env.ref("stock.stock_location_stock"), + self.order.product_id, + 1, + lot=existing_lot, + ) + with self.assertRaisesRegex(UserError, "already exists and has been used"): + self.order.button_mark_done() + def test_confirm_with_variant_ok(self): self._add_color_and_legs_variants(self.bom_product_template) self._add_color_and_legs_variants(self.product_template_tracked_by_sn)