From 59230cbbe5e807da658e743434a63f9e2bf0fc9d Mon Sep 17 00:00:00 2001 From: Marina Alapont Date: Tue, 9 Sep 2025 10:19:17 +0200 Subject: [PATCH 1/7] [ADD] mrp_production_unique_lot --- mrp_production_unique_lot/README.rst | 104 ++++ mrp_production_unique_lot/__init__.py | 1 + mrp_production_unique_lot/__manifest__.py | 21 + mrp_production_unique_lot/i18n/da_DK.po | 67 +++ .../i18n/mrp_production_unique_lot.pot | 62 +++ mrp_production_unique_lot/models/__init__.py | 2 + .../models/mrp_production.py | 148 ++++++ .../models/stock_picking_type.py | 14 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 9 + mrp_production_unique_lot/readme/USAGE.rst | 16 + .../static/description/index.html | 451 ++++++++++++++++++ mrp_production_unique_lot/tests/__init__.py | 1 + .../tests/test_mrp_production_unique_lot.py | 114 +++++ .../views/mrp_production_views.xml | 18 + .../views/stock_picking_views.xml | 13 + 16 files changed, 1042 insertions(+) create mode 100644 mrp_production_unique_lot/README.rst create mode 100644 mrp_production_unique_lot/__init__.py create mode 100644 mrp_production_unique_lot/__manifest__.py create mode 100644 mrp_production_unique_lot/i18n/da_DK.po create mode 100644 mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot create mode 100644 mrp_production_unique_lot/models/__init__.py create mode 100644 mrp_production_unique_lot/models/mrp_production.py create mode 100644 mrp_production_unique_lot/models/stock_picking_type.py create mode 100644 mrp_production_unique_lot/readme/CONTRIBUTORS.rst create mode 100644 mrp_production_unique_lot/readme/DESCRIPTION.rst create mode 100644 mrp_production_unique_lot/readme/USAGE.rst create mode 100644 mrp_production_unique_lot/static/description/index.html create mode 100644 mrp_production_unique_lot/tests/__init__.py create mode 100644 mrp_production_unique_lot/tests/test_mrp_production_unique_lot.py create mode 100644 mrp_production_unique_lot/views/mrp_production_views.xml create mode 100644 mrp_production_unique_lot/views/stock_picking_views.xml diff --git a/mrp_production_unique_lot/README.rst b/mrp_production_unique_lot/README.rst new file mode 100644 index 00000000000..6d275bc0bb8 --- /dev/null +++ b/mrp_production_unique_lot/README.rst @@ -0,0 +1,104 @@ +========================= +MRP Production Unique Lot +========================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:ef81bcc2de889e409ab3d3c3bf5e95d47da451b255845843ada83fd654afa6d0 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github + :target: https://github.com/OCA/manufacture/tree/16.0/mrp_production_unique_lot + :alt: OCA/manufacture +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/manufacture-16-0/manufacture-16-0-mrp_production_unique_lot + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/manufacture&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module enforces that each Manufacturing Order (MO) has a unique lot number +for its finished products. + +A lot generated by one MO cannot be reused in another MO, and this constraint +is applied when validating the production. + +Additionally, to improve user usability, the domain of the lot_producing_id +field has been updated to ensure only lot numbers that have not been used +are selectable, only in case the product is tracked by lots. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +1. **Configuring The Operation Type** + + - Navigate to Inventory > Configuration > Operation Types. + - Open the Manufacturing operation type. + - Check the option 'Force Production Lot Uniqueness'. + +2. **Creating a Manufacturing Order** + + - Create an MO for a product that is tracked by lots. + - Assign an existing **lot number** for the finished product. This should be a lot number + used on a done production. + +3. **Validating the Manufacturing Order** + + - When you validate the MO, an error is thrown because the lot has already been produced. + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ForgeFlow + +Contributors +~~~~~~~~~~~~ + +* Marina Alapont + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/manufacture `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mrp_production_unique_lot/__init__.py b/mrp_production_unique_lot/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/mrp_production_unique_lot/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/mrp_production_unique_lot/__manifest__.py b/mrp_production_unique_lot/__manifest__.py new file mode 100644 index 00000000000..0a1450625ea --- /dev/null +++ b/mrp_production_unique_lot/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2025 ForgeFlow, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +{ + "name": "MRP Production Unique Lot", + "Summary": "Ensures that production lot numbers are unique and cannot be reused " + "in another manufacturing order.", + "version": "16.0.1.0.0", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/manufacture", + "category": "Manufacturing", + "depends": [ + "mrp", + ], + "data": [ + "views/stock_picking_views.xml", + "views/mrp_production_views.xml", + ], + "installable": True, + "auto_install": False, +} diff --git a/mrp_production_unique_lot/i18n/da_DK.po b/mrp_production_unique_lot/i18n/da_DK.po new file mode 100644 index 00000000000..bda0cddbe1e --- /dev/null +++ b/mrp_production_unique_lot/i18n/da_DK.po @@ -0,0 +1,67 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_unique_lot +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-09-09 10:46+0000\n" +"PO-Revision-Date: 2025-09-09 10:46+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_mrp_production__allowed_lot_producing_ids +msgid "Allowed Lot/Serial Numbers" +msgstr "Tilladte Lot/Serienumre" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_mrp_production__force_lot_uniqueness +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_stock_picking_type__force_production_lot_uniqueness +msgid "Force Production Lot Uniqueness" +msgstr "Gennemtving entydighed af produktionslot" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,help:mrp_production_unique_lot.field_mrp_production__force_lot_uniqueness +#: model:ir.model.fields,help:mrp_production_unique_lot.field_stock_picking_type__force_production_lot_uniqueness +msgid "" +"If checked, each Manufacturing Order (MO) will have a unique lot number for " +"its finished products. Therefore, lot numbers that have already been used in" +" an MO cannot be reused." +msgstr "" +"Hvis markeret, vil hver produktionsordre (MO) have et unikt lotnummer for " +"sine færdigvarer. Derfor kan lotnumre, der allerede er brugt i en " +"MO, ikke genbruges." + +#. module: mrp_production_unique_lot +#: model:ir.model,name:mrp_production_unique_lot.model_stock_picking_type +msgid "Picking Type" +msgstr "Pluk type" + +#. module: mrp_production_unique_lot +#: model:ir.model,name:mrp_production_unique_lot.model_mrp_production +msgid "Production Order" +msgstr "Produktionsordre" + +#. module: mrp_production_unique_lot +#. odoo-python +#: code:addons/mrp_production_unique_lot/models/mrp_production.py:0 +#, python-format +msgid "" +"The lot number %(number)s used for byproduct %(product_name)s has already " +"been produced" +msgstr "" +"Lotnummeret %(number)s, brugt til biproduktet %(product_name)s, er allerede " +"blevet produceret." + +#. module: mrp_production_unique_lot +#. odoo-python +#: code:addons/mrp_production_unique_lot/models/mrp_production.py:0 +#, python-format +msgid "This lot number for product %s has already been produced" +msgstr "Dette lotnummer for produktet %s er allerede blevet produceret." diff --git a/mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot b/mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot new file mode 100644 index 00000000000..f689d0d53c1 --- /dev/null +++ b/mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot @@ -0,0 +1,62 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_unique_lot +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-09-09 10:46+0000\n" +"PO-Revision-Date: 2025-09-09 10:46+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_mrp_production__allowed_lot_producing_ids +msgid "Allowed Lot/Serial Numbers" +msgstr "" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_mrp_production__force_lot_uniqueness +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_stock_picking_type__force_production_lot_uniqueness +msgid "Force Production Lot Uniqueness" +msgstr "" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,help:mrp_production_unique_lot.field_mrp_production__force_lot_uniqueness +#: model:ir.model.fields,help:mrp_production_unique_lot.field_stock_picking_type__force_production_lot_uniqueness +msgid "" +"If checked, each Manufacturing Order (MO) will have a unique lot number for " +"its finished products. Therefore, lot numbers that have already been used in" +" an MO cannot be reused." +msgstr "" + +#. module: mrp_production_unique_lot +#: model:ir.model,name:mrp_production_unique_lot.model_stock_picking_type +msgid "Picking Type" +msgstr "" + +#. module: mrp_production_unique_lot +#: model:ir.model,name:mrp_production_unique_lot.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: mrp_production_unique_lot +#. odoo-python +#: code:addons/mrp_production_unique_lot/models/mrp_production.py:0 +#, python-format +msgid "" +"The lot number %(number)s used for byproduct %(product_name)s has already " +"been produced" +msgstr "" + +#. module: mrp_production_unique_lot +#. odoo-python +#: code:addons/mrp_production_unique_lot/models/mrp_production.py:0 +#, python-format +msgid "This lot number for product %s has already been produced" +msgstr "" diff --git a/mrp_production_unique_lot/models/__init__.py b/mrp_production_unique_lot/models/__init__.py new file mode 100644 index 00000000000..41dc87858ee --- /dev/null +++ b/mrp_production_unique_lot/models/__init__.py @@ -0,0 +1,2 @@ +from . import mrp_production +from . import stock_picking_type diff --git a/mrp_production_unique_lot/models/mrp_production.py b/mrp_production_unique_lot/models/mrp_production.py new file mode 100644 index 00000000000..0a0a3e77801 --- /dev/null +++ b/mrp_production_unique_lot/models/mrp_production.py @@ -0,0 +1,148 @@ +# Copyright 2025 ForgeFlow, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import _, fields, models +from odoo.exceptions import UserError + + +class MrpProduction(models.Model): + _inherit = "mrp.production" + + force_lot_uniqueness = fields.Boolean( + related="picking_type_id.force_production_lot_uniqueness" + ) + + allowed_lot_producing_ids = fields.Many2many( + "stock.lot", + string="Allowed Lot/Serial Numbers", + compute="_compute_allowed_lot_producing_ids", + ) + + def _compute_allowed_lot_producing_ids(self): + for record in self: + lot_ids = self.env["stock.lot"].search( + [ + ("product_id", "=", record.product_id.id), + ("company_id", "=", record.company_id.id), + ] + ) + if record.force_lot_uniqueness and record.product_id.tracking == "lot": + allowed_lots = lot_ids.filtered( + lambda lot: not record._is_finished_lot_already_produced(lot) + ) + record.allowed_lot_producing_ids = allowed_lots + else: + record.allowed_lot_producing_ids = lot_ids + + def _button_mark_done_sanity_checks(self): + res = super()._button_mark_done_sanity_checks() + for order in self: + order._check_lot_uniqueness() + return res + + def _check_lot_uniqueness(self): + """Alert the user if the lot number has already been produced. + This method is based on the odoo code for serial numbers in _check_sn_uniqueness + """ + if not self.force_lot_uniqueness or not self.lot_producing_id: + return + + if ( + self.product_tracking == "lot" + and self.lot_producing_id + and self._is_finished_lot_already_produced(self.lot_producing_id) + ): + raise UserError( + _( + "This lot number for product %s has already been produced", + self.product_id.name, + ) + ) + + for move in self.move_finished_ids: + if move.has_tracking != "lot" or move.product_id == self.product_id: + continue + for move_line in move.move_line_ids: + if self._is_finished_lot_already_produced( + move_line.lot_id, excluded_sml=move_line + ): + raise UserError( + _( + "The lot number %(number)s used for byproduct %(product_name)s" + " has already been produced", + number=move_line.lot_id.name, + product_name=move_line.product_id.name, + ) + ) + + def _is_finished_lot_already_produced(self, lot, excluded_sml=None): + """ + Check if the given lot has already been produced in another MO, + taking into account unbuilt and scrapped moves, and excluding + the current production move lines if provided. + + This method is based on the odoo code for serial numbers in + _is_finished_sn_already_produced + """ + excluded_move_lines = excluded_sml or self.env["stock.move.line"] + + # Domain for all done move lines with this lot + base_domain = [("lot_id", "=", lot.id), ("state", "=", "done")] + + # Finished move lines in production location that are not unbuilt + done_count = self.env["stock.move.line"].search_count( + base_domain + + [ + ("location_id.usage", "=", "production"), + ("move_id.unbuild_id", "=", False), + ] + ) + + if done_count: + # Move lines that were unbuilt + unbuilt_count = self.env["stock.move.line"].search_count( + base_domain + + [ + ("production_id", "=", False), + ("location_dest_id.usage", "=", "production"), + ("move_id.unbuild_id", "!=", False), + ] + ) + + # Move lines moved to scrap + moved_to_scrap_count = self.env["stock.move.line"].search_count( + base_domain + + [ + ("location_id.scrap_location", "=", False), + ("location_dest_id.scrap_location", "=", True), + ] + ) + + # Move lines restored from scrap + restored_from_scrap_count = self.env["stock.move.line"].search_count( + [ + ("lot_id", "=", lot.id), + ("state", "=", "done"), + ("location_id.scrap_location", "=", True), + ("location_dest_id.scrap_location", "=", False), + ] + ) + + # If any production still exists that was not unbuilt/scrapped, return True + if not ( + (unbuilt_count or moved_to_scrap_count) + and done_count + - unbuilt_count + - moved_to_scrap_count + + restored_from_scrap_count + == 0 + ): + return True + + # Check duplicates in current production, excluding specified move lines if any + current_move_lines = self.move_finished_ids.move_line_ids - excluded_move_lines + duplicates_in_current = current_move_lines.filtered( + lambda ml: ml.qty_done and ml.lot_id == lot + ) + + return bool(duplicates_in_current) diff --git a/mrp_production_unique_lot/models/stock_picking_type.py b/mrp_production_unique_lot/models/stock_picking_type.py new file mode 100644 index 00000000000..b1b72813123 --- /dev/null +++ b/mrp_production_unique_lot/models/stock_picking_type.py @@ -0,0 +1,14 @@ +# Copyright 2025 ForgeFlow, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class StockPickingType(models.Model): + _inherit = "stock.picking.type" + + force_production_lot_uniqueness = fields.Boolean( + help="If checked, each Manufacturing Order (MO) will have a unique lot " + "number for its finished products. Therefore, lot numbers that have " + "already been used in an MO cannot be reused.", + ) diff --git a/mrp_production_unique_lot/readme/CONTRIBUTORS.rst b/mrp_production_unique_lot/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..82fa316ae83 --- /dev/null +++ b/mrp_production_unique_lot/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Marina Alapont diff --git a/mrp_production_unique_lot/readme/DESCRIPTION.rst b/mrp_production_unique_lot/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..34b678d115d --- /dev/null +++ b/mrp_production_unique_lot/readme/DESCRIPTION.rst @@ -0,0 +1,9 @@ +This module enforces that each Manufacturing Order (MO) has a unique lot number +for its finished products. + +A lot generated by one MO cannot be reused in another MO, and this constraint +is applied when validating the production. + +Additionally, to improve user usability, the domain of the lot_producing_id +field has been updated to ensure only lot numbers that have not been used +are selectable, only in case the product is tracked by lots. diff --git a/mrp_production_unique_lot/readme/USAGE.rst b/mrp_production_unique_lot/readme/USAGE.rst new file mode 100644 index 00000000000..de2e0efac0c --- /dev/null +++ b/mrp_production_unique_lot/readme/USAGE.rst @@ -0,0 +1,16 @@ +1. **Configuring The Operation Type** + + - Navigate to Inventory > Configuration > Operation Types. + - Open the Manufacturing operation type. + - Check the option 'Force Production Lot Uniqueness'. + +2. **Creating a Manufacturing Order** + + - Create an MO for a product that is tracked by lots. + - Assign an existing **lot number** for the finished product. This should be a lot number + used on a done production. + +3. **Validating the Manufacturing Order** + + - When you validate the MO, an error is thrown because the lot has already been produced. + diff --git a/mrp_production_unique_lot/static/description/index.html b/mrp_production_unique_lot/static/description/index.html new file mode 100644 index 00000000000..57bc9512f15 --- /dev/null +++ b/mrp_production_unique_lot/static/description/index.html @@ -0,0 +1,451 @@ + + + + + +MRP Production Unique Lot + + + +
+

MRP Production Unique Lot

+ + +

Beta License: AGPL-3 OCA/manufacture Translate me on Weblate Try me on Runboat

+

This module enforces that each Manufacturing Order (MO) has a unique lot number +for its finished products.

+

A lot generated by one MO cannot be reused in another MO, and this constraint +is applied when validating the production.

+

Additionally, to improve user usability, the domain of the lot_producing_id +field has been updated to ensure only lot numbers that have not been used +are selectable, only in case the product is tracked by lots.

+

Table of contents

+ +
+

Usage

+
    +
  1. Configuring The Operation Type
      +
    • Navigate to Inventory > Configuration > Operation Types.
    • +
    • Open the Manufacturing operation type.
    • +
    • Check the option ‘Force Production Lot Uniqueness’.
    • +
    +
  2. +
  3. Creating a Manufacturing Order
      +
    • Create an MO for a product that is tracked by lots.
    • +
    • Assign an existing lot number for the finished product. This should be a lot number +used on a done production.
    • +
    +
  4. +
  5. Validating the Manufacturing Order
      +
    • When you validate the MO, an error is thrown because the lot has already been produced.
    • +
    +
  6. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/manufacture project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/mrp_production_unique_lot/tests/__init__.py b/mrp_production_unique_lot/tests/__init__.py new file mode 100644 index 00000000000..eba3d870d09 --- /dev/null +++ b/mrp_production_unique_lot/tests/__init__.py @@ -0,0 +1 @@ +from . import test_mrp_production_unique_lot diff --git a/mrp_production_unique_lot/tests/test_mrp_production_unique_lot.py b/mrp_production_unique_lot/tests/test_mrp_production_unique_lot.py new file mode 100644 index 00000000000..9bafc1d90cd --- /dev/null +++ b/mrp_production_unique_lot/tests/test_mrp_production_unique_lot.py @@ -0,0 +1,114 @@ +# Copyright 2025 ForgeFlow, S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo.exceptions import UserError +from odoo.tests import Form + +from odoo.addons.mrp.tests import common + + +class TestMrpLotUniqueness(common.TestMrpCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.picking_type = cls.env.ref("stock.warehouse0").manu_type_id + cls.picking_type.write({"force_production_lot_uniqueness": True}) + cls.mo, cls.bom, cls.final_product, _, _ = cls.generate_mo( + tracking_final="lot", picking_type_id=cls.picking_type + ) + cls.lot = cls.env["stock.lot"].create( + {"name": "LOT-001", "product_id": cls.final_product.id} + ) + + mo_form = Form(cls.mo) + mo_form.qty_producing = 5 + mo_form.lot_producing_id = cls.lot + mo = mo_form.save() + mo.button_mark_done() + + def test_unique_lot_validation(self): + mo2 = self.env["mrp.production"].create( + { + "product_id": self.final_product.id, + "bom_id": self.bom.id, + "picking_type_id": self.picking_type.id, + "product_qty": 10, + } + ) + mo2.action_confirm() + + # Try to assign the same lot + mo_form = Form(mo2) + mo_form.qty_producing = 10 + mo_form.lot_producing_id = self.lot + mo = mo_form.save() + with self.assertRaises(UserError): + mo.button_mark_done() + + # Try with another lot + lot2 = self.env["stock.lot"].create( + {"name": "LOT-002", "product_id": self.final_product.id} + ) + mo_form = Form(mo2) + mo_form.qty_producing = 10 + mo_form.lot_producing_id = lot2 + mo = mo_form.save() + mo.button_mark_done() + + def test_lot_reusable_after_unbuild(self): + x = Form(self.env["mrp.unbuild"]) + x.product_id = self.final_product + x.mo_id = self.mo + x.product_qty = self.mo.product_qty + x.save().action_unbuild() + + mo2 = self.env["mrp.production"].create( + { + "product_id": self.final_product.id, + "bom_id": self.bom.id, + "picking_type_id": self.picking_type.id, + "product_qty": 10, + } + ) + mo2.action_confirm() + + # Try to assign the same lot, it should not raise + mo_form = Form(mo2) + mo_form.qty_producing = 10 + mo_form.lot_producing_id = self.lot + mo = mo_form.save() + mo.button_mark_done() + + def test_lot_reusable_after_scrap(self): + scrap_id = ( + self.env["stock.scrap"] + .with_context(active_model="mrp.production", active_id=self.mo.id) + .create( + { + "product_id": self.final_product.id, + "scrap_qty": self.mo.product_qty, + "product_uom_id": self.final_product.uom_id.id, + "production_id": self.mo.id, + "lot_id": self.lot.id, + } + ) + ) + scrap_id.do_scrap() + + mo2 = self.env["mrp.production"].create( + { + "product_id": self.final_product.id, + "bom_id": self.bom.id, + "picking_type_id": self.picking_type.id, + "product_qty": 10, + } + ) + mo2.action_confirm() + + # Try to assign the same lot, it should not raise + mo_form = Form(mo2) + mo_form.qty_producing = 10 + mo_form.lot_producing_id = self.lot + mo = mo_form.save() + mo.button_mark_done() diff --git a/mrp_production_unique_lot/views/mrp_production_views.xml b/mrp_production_unique_lot/views/mrp_production_views.xml new file mode 100644 index 00000000000..1f8b709080e --- /dev/null +++ b/mrp_production_unique_lot/views/mrp_production_views.xml @@ -0,0 +1,18 @@ + + + + mrp.production.form.unique.lot + mrp.production + + + + + + + [('id', 'in', allowed_lot_producing_ids)] + + + + diff --git a/mrp_production_unique_lot/views/stock_picking_views.xml b/mrp_production_unique_lot/views/stock_picking_views.xml new file mode 100644 index 00000000000..116cf083bf7 --- /dev/null +++ b/mrp_production_unique_lot/views/stock_picking_views.xml @@ -0,0 +1,13 @@ + + + + Operation Types - Unique Production Lot + stock.picking.type + + + + + + + + From dc8a2f3ff1c9d4d44de0f0114d096443dce7ad99 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Tue, 28 Oct 2025 17:29:00 +0000 Subject: [PATCH 2/7] [UPD] Update mrp_production_unique_lot.pot --- mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot b/mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot index f689d0d53c1..66d5690420f 100644 --- a/mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot +++ b/mrp_production_unique_lot/i18n/mrp_production_unique_lot.pot @@ -4,10 +4,8 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 16.0+e\n" +"Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-09-09 10:46+0000\n" -"PO-Revision-Date: 2025-09-09 10:46+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" From 8190a897170097d450726a035ad5b4fccdeaf0ec Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 28 Oct 2025 17:34:28 +0000 Subject: [PATCH 3/7] [BOT] post-merge updates --- mrp_production_unique_lot/README.rst | 8 +++-- .../static/description/icon.png | Bin 0 -> 10254 bytes .../static/description/index.html | 28 +++++++++++------- 3 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 mrp_production_unique_lot/static/description/icon.png diff --git a/mrp_production_unique_lot/README.rst b/mrp_production_unique_lot/README.rst index 6d275bc0bb8..46edf72b168 100644 --- a/mrp_production_unique_lot/README.rst +++ b/mrp_production_unique_lot/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ========================= MRP Production Unique Lot ========================= @@ -7,13 +11,13 @@ MRP Production Unique Lot !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:ef81bcc2de889e409ab3d3c3bf5e95d47da451b255845843ada83fd654afa6d0 + !! source digest: sha256:383bc907a875b26540be19b1d9327fb1bf8c7693d4b2d322ca9d2ac98103698f !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github diff --git a/mrp_production_unique_lot/static/description/icon.png b/mrp_production_unique_lot/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1dcc49c24f364e9adf0afbc6fc0bac6dbecdeb11 GIT binary patch literal 10254 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 -MRP Production Unique Lot +README.rst -
-

MRP Production Unique Lot

+
+ + +Odoo Community Association + +
+

MRP Production Unique Lot

-

Beta License: AGPL-3 OCA/manufacture Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/manufacture Translate me on Weblate Try me on Runboat

This module enforces that each Manufacturing Order (MO) has a unique lot number for its finished products.

A lot generated by one MO cannot be reused in another MO, and this constraint @@ -391,7 +396,7 @@

MRP Production Unique Lot

-

Usage

+

Usage

  1. Configuring The Operation Type
    • Navigate to Inventory > Configuration > Operation Types.
    • @@ -412,7 +417,7 @@

      Usage

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -420,21 +425,21 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

+
From b0fcb8d304aa1a5b6a6de93717af9678d97bae57 Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 30 Oct 2025 07:50:33 +0000 Subject: [PATCH 4/7] Added translation using Weblate (Italian) --- mrp_production_unique_lot/i18n/it.po | 61 ++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 mrp_production_unique_lot/i18n/it.po diff --git a/mrp_production_unique_lot/i18n/it.po b/mrp_production_unique_lot/i18n/it.po new file mode 100644 index 00000000000..076ce8425f9 --- /dev/null +++ b/mrp_production_unique_lot/i18n/it.po @@ -0,0 +1,61 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_production_unique_lot +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_mrp_production__allowed_lot_producing_ids +msgid "Allowed Lot/Serial Numbers" +msgstr "" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_mrp_production__force_lot_uniqueness +#: model:ir.model.fields,field_description:mrp_production_unique_lot.field_stock_picking_type__force_production_lot_uniqueness +msgid "Force Production Lot Uniqueness" +msgstr "" + +#. module: mrp_production_unique_lot +#: model:ir.model.fields,help:mrp_production_unique_lot.field_mrp_production__force_lot_uniqueness +#: model:ir.model.fields,help:mrp_production_unique_lot.field_stock_picking_type__force_production_lot_uniqueness +msgid "" +"If checked, each Manufacturing Order (MO) will have a unique lot number for " +"its finished products. Therefore, lot numbers that have already been used in" +" an MO cannot be reused." +msgstr "" + +#. module: mrp_production_unique_lot +#: model:ir.model,name:mrp_production_unique_lot.model_stock_picking_type +msgid "Picking Type" +msgstr "" + +#. module: mrp_production_unique_lot +#: model:ir.model,name:mrp_production_unique_lot.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: mrp_production_unique_lot +#. odoo-python +#: code:addons/mrp_production_unique_lot/models/mrp_production.py:0 +#, python-format +msgid "" +"The lot number %(number)s used for byproduct %(product_name)s has already " +"been produced" +msgstr "" + +#. module: mrp_production_unique_lot +#. odoo-python +#: code:addons/mrp_production_unique_lot/models/mrp_production.py:0 +#, python-format +msgid "This lot number for product %s has already been produced" +msgstr "" From 1817e24d4bed2ec466003100a1c2368f805dc117 Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 30 Oct 2025 08:07:20 +0000 Subject: [PATCH 5/7] Translated using Weblate (Italian) Currently translated at 100.0% (7 of 7 strings) Translation: manufacture-16.0/manufacture-16.0-mrp_production_unique_lot Translate-URL: https://translation.odoo-community.org/projects/manufacture-16-0/manufacture-16-0-mrp_production_unique_lot/it/ --- mrp_production_unique_lot/i18n/it.po | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/mrp_production_unique_lot/i18n/it.po b/mrp_production_unique_lot/i18n/it.po index 076ce8425f9..a80215d82e2 100644 --- a/mrp_production_unique_lot/i18n/it.po +++ b/mrp_production_unique_lot/i18n/it.po @@ -6,24 +6,26 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2025-10-30 10:43+0000\n" +"Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.10.4\n" #. module: mrp_production_unique_lot #: model:ir.model.fields,field_description:mrp_production_unique_lot.field_mrp_production__allowed_lot_producing_ids msgid "Allowed Lot/Serial Numbers" -msgstr "" +msgstr "Numeri lotto/seriali consentiti" #. module: mrp_production_unique_lot #: model:ir.model.fields,field_description:mrp_production_unique_lot.field_mrp_production__force_lot_uniqueness #: model:ir.model.fields,field_description:mrp_production_unique_lot.field_stock_picking_type__force_production_lot_uniqueness msgid "Force Production Lot Uniqueness" -msgstr "" +msgstr "Forza unicità lotto produzione" #. module: mrp_production_unique_lot #: model:ir.model.fields,help:mrp_production_unique_lot.field_mrp_production__force_lot_uniqueness @@ -33,16 +35,19 @@ msgid "" "its finished products. Therefore, lot numbers that have already been used in" " an MO cannot be reused." msgstr "" +"Se selezionata, ogni ordine di produzione (OP) avrà un numero di lotto " +"univoco per i suoi prodotti finiti. Pertanto, i numeri di lotto già " +"utilizzati in un OP non potranno essere riutilizzati." #. module: mrp_production_unique_lot #: model:ir.model,name:mrp_production_unique_lot.model_stock_picking_type msgid "Picking Type" -msgstr "" +msgstr "Tipo prelievo" #. module: mrp_production_unique_lot #: model:ir.model,name:mrp_production_unique_lot.model_mrp_production msgid "Production Order" -msgstr "" +msgstr "Ordine di produzione" #. module: mrp_production_unique_lot #. odoo-python @@ -52,10 +57,12 @@ msgid "" "The lot number %(number)s used for byproduct %(product_name)s has already " "been produced" msgstr "" +"Il numero di lotto %(number)s usato per il semilavorato %(product_name)s è " +"già stato prodotto" #. module: mrp_production_unique_lot #. odoo-python #: code:addons/mrp_production_unique_lot/models/mrp_production.py:0 #, python-format msgid "This lot number for product %s has already been produced" -msgstr "" +msgstr "Questo numero di lotto per il prodotto %s è già stato prodotto" From 55ff68ff89f591a4533ecfa86e7ad504df3de475 Mon Sep 17 00:00:00 2001 From: JasminSForgeFlow Date: Tue, 3 Feb 2026 07:37:25 +0000 Subject: [PATCH 6/7] [IMP] mrp_production_unique_lot: pre-commit auto fixes --- mrp_production_unique_lot/README.rst | 41 ++++++++++--------- mrp_production_unique_lot/pyproject.toml | 3 ++ .../readme/CONTRIBUTORS.md | 1 + .../readme/CONTRIBUTORS.rst | 1 - .../readme/DESCRIPTION.md | 10 +++++ .../readme/DESCRIPTION.rst | 9 ---- mrp_production_unique_lot/readme/USAGE.md | 11 +++++ mrp_production_unique_lot/readme/USAGE.rst | 16 -------- .../static/description/index.html | 28 +++++++------ 9 files changed, 61 insertions(+), 59 deletions(-) create mode 100644 mrp_production_unique_lot/pyproject.toml create mode 100644 mrp_production_unique_lot/readme/CONTRIBUTORS.md delete mode 100644 mrp_production_unique_lot/readme/CONTRIBUTORS.rst create mode 100644 mrp_production_unique_lot/readme/DESCRIPTION.md delete mode 100644 mrp_production_unique_lot/readme/DESCRIPTION.rst create mode 100644 mrp_production_unique_lot/readme/USAGE.md delete mode 100644 mrp_production_unique_lot/readme/USAGE.rst diff --git a/mrp_production_unique_lot/README.rst b/mrp_production_unique_lot/README.rst index 46edf72b168..66e37c28246 100644 --- a/mrp_production_unique_lot/README.rst +++ b/mrp_production_unique_lot/README.rst @@ -21,26 +21,27 @@ MRP Production Unique Lot :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github - :target: https://github.com/OCA/manufacture/tree/16.0/mrp_production_unique_lot + :target: https://github.com/OCA/manufacture/tree/19.0/mrp_production_unique_lot :alt: OCA/manufacture .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/manufacture-16-0/manufacture-16-0-mrp_production_unique_lot + :target: https://translation.odoo-community.org/projects/manufacture-19-0/manufacture-19-0-mrp_production_unique_lot :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/manufacture&target_branch=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/manufacture&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -This module enforces that each Manufacturing Order (MO) has a unique lot number -for its finished products. +This module enforces that each Manufacturing Order (MO) has a unique lot +number for its finished products. -A lot generated by one MO cannot be reused in another MO, and this constraint -is applied when validating the production. +A lot generated by one MO cannot be reused in another MO, and this +constraint is applied when validating the production. -Additionally, to improve user usability, the domain of the lot_producing_id -field has been updated to ensure only lot numbers that have not been used -are selectable, only in case the product is tracked by lots. +Additionally, to improve user usability, the domain of the +lot_producing_id field has been updated to ensure only lot numbers that +have not been used are selectable, only in case the product is tracked +by lots. **Table of contents** @@ -59,13 +60,13 @@ Usage 2. **Creating a Manufacturing Order** - Create an MO for a product that is tracked by lots. - - Assign an existing **lot number** for the finished product. This should be a lot number - used on a done production. + - Assign an existing **lot number** for the finished product. This + should be a lot number used on a done production. 3. **Validating the Manufacturing Order** - - When you validate the MO, an error is thrown because the lot has already been produced. - + - When you validate the MO, an error is thrown because the lot has + already been produced. Bug Tracker =========== @@ -73,7 +74,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -81,17 +82,17 @@ Credits ======= Authors -~~~~~~~ +------- * ForgeFlow Contributors -~~~~~~~~~~~~ +------------ -* Marina Alapont +- Marina Alapont Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -103,6 +104,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/manufacture `_ project on GitHub. +This module is part of the `OCA/manufacture `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mrp_production_unique_lot/pyproject.toml b/mrp_production_unique_lot/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/mrp_production_unique_lot/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/mrp_production_unique_lot/readme/CONTRIBUTORS.md b/mrp_production_unique_lot/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..089e6dd3923 --- /dev/null +++ b/mrp_production_unique_lot/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Marina Alapont \ diff --git a/mrp_production_unique_lot/readme/CONTRIBUTORS.rst b/mrp_production_unique_lot/readme/CONTRIBUTORS.rst deleted file mode 100644 index 82fa316ae83..00000000000 --- a/mrp_production_unique_lot/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1 +0,0 @@ -* Marina Alapont diff --git a/mrp_production_unique_lot/readme/DESCRIPTION.md b/mrp_production_unique_lot/readme/DESCRIPTION.md new file mode 100644 index 00000000000..442b8790268 --- /dev/null +++ b/mrp_production_unique_lot/readme/DESCRIPTION.md @@ -0,0 +1,10 @@ +This module enforces that each Manufacturing Order (MO) has a unique lot +number for its finished products. + +A lot generated by one MO cannot be reused in another MO, and this +constraint is applied when validating the production. + +Additionally, to improve user usability, the domain of the +lot_producing_id field has been updated to ensure only lot numbers that +have not been used are selectable, only in case the product is tracked +by lots. diff --git a/mrp_production_unique_lot/readme/DESCRIPTION.rst b/mrp_production_unique_lot/readme/DESCRIPTION.rst deleted file mode 100644 index 34b678d115d..00000000000 --- a/mrp_production_unique_lot/readme/DESCRIPTION.rst +++ /dev/null @@ -1,9 +0,0 @@ -This module enforces that each Manufacturing Order (MO) has a unique lot number -for its finished products. - -A lot generated by one MO cannot be reused in another MO, and this constraint -is applied when validating the production. - -Additionally, to improve user usability, the domain of the lot_producing_id -field has been updated to ensure only lot numbers that have not been used -are selectable, only in case the product is tracked by lots. diff --git a/mrp_production_unique_lot/readme/USAGE.md b/mrp_production_unique_lot/readme/USAGE.md new file mode 100644 index 00000000000..03bf7a739d8 --- /dev/null +++ b/mrp_production_unique_lot/readme/USAGE.md @@ -0,0 +1,11 @@ +1. **Configuring The Operation Type** + - Navigate to Inventory \> Configuration \> Operation Types. + - Open the Manufacturing operation type. + - Check the option 'Force Production Lot Uniqueness'. +2. **Creating a Manufacturing Order** + - Create an MO for a product that is tracked by lots. + - Assign an existing **lot number** for the finished product. This + should be a lot number used on a done production. +3. **Validating the Manufacturing Order** + - When you validate the MO, an error is thrown because the lot has + already been produced. diff --git a/mrp_production_unique_lot/readme/USAGE.rst b/mrp_production_unique_lot/readme/USAGE.rst deleted file mode 100644 index de2e0efac0c..00000000000 --- a/mrp_production_unique_lot/readme/USAGE.rst +++ /dev/null @@ -1,16 +0,0 @@ -1. **Configuring The Operation Type** - - - Navigate to Inventory > Configuration > Operation Types. - - Open the Manufacturing operation type. - - Check the option 'Force Production Lot Uniqueness'. - -2. **Creating a Manufacturing Order** - - - Create an MO for a product that is tracked by lots. - - Assign an existing **lot number** for the finished product. This should be a lot number - used on a done production. - -3. **Validating the Manufacturing Order** - - - When you validate the MO, an error is thrown because the lot has already been produced. - diff --git a/mrp_production_unique_lot/static/description/index.html b/mrp_production_unique_lot/static/description/index.html index a5fb7d005ce..cb6de4e800e 100644 --- a/mrp_production_unique_lot/static/description/index.html +++ b/mrp_production_unique_lot/static/description/index.html @@ -374,14 +374,15 @@

MRP Production Unique Lot

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:383bc907a875b26540be19b1d9327fb1bf8c7693d4b2d322ca9d2ac98103698f !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/manufacture Translate me on Weblate Try me on Runboat

-

This module enforces that each Manufacturing Order (MO) has a unique lot number -for its finished products.

-

A lot generated by one MO cannot be reused in another MO, and this constraint -is applied when validating the production.

-

Additionally, to improve user usability, the domain of the lot_producing_id -field has been updated to ensure only lot numbers that have not been used -are selectable, only in case the product is tracked by lots.

+

Beta License: AGPL-3 OCA/manufacture Translate me on Weblate Try me on Runboat

+

This module enforces that each Manufacturing Order (MO) has a unique lot +number for its finished products.

+

A lot generated by one MO cannot be reused in another MO, and this +constraint is applied when validating the production.

+

Additionally, to improve user usability, the domain of the +lot_producing_id field has been updated to ensure only lot numbers that +have not been used are selectable, only in case the product is tracked +by lots.

Table of contents

    @@ -406,12 +407,13 @@

    Usage

  • Creating a Manufacturing Order
    • Create an MO for a product that is tracked by lots.
    • -
    • Assign an existing lot number for the finished product. This should be a lot number -used on a done production.
    • +
    • Assign an existing lot number for the finished product. This +should be a lot number used on a done production.
  • Validating the Manufacturing Order
      -
    • When you validate the MO, an error is thrown because the lot has already been produced.
    • +
    • When you validate the MO, an error is thrown because the lot has +already been produced.
  • @@ -421,7 +423,7 @@

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

    +feedback.

    Do not contact contributors directly about support or help with technical issues.

@@ -447,7 +449,7 @@

Maintainers

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

-

This module is part of the OCA/manufacture project on GitHub.

+

This module is part of the OCA/manufacture project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

From 4011a1293e6f33e41ca9d4c3650469477271bad4 Mon Sep 17 00:00:00 2001 From: JasminSForgeFlow Date: Fri, 20 Feb 2026 12:22:22 +0000 Subject: [PATCH 7/7] [MIG] mrp_production_unique_lot: Migration to 19.0 --- mrp_production_unique_lot/README.rst | 1 + mrp_production_unique_lot/__manifest__.py | 2 +- .../models/mrp_production.py | 29 ++++++++++--------- .../readme/CONTRIBUTORS.md | 1 + .../static/description/index.html | 1 + .../tests/test_mrp_production_unique_lot.py | 12 ++++---- .../views/mrp_production_views.xml | 4 +-- .../views/stock_picking_views.xml | 2 +- 8 files changed, 29 insertions(+), 23 deletions(-) diff --git a/mrp_production_unique_lot/README.rst b/mrp_production_unique_lot/README.rst index 66e37c28246..4395b35437b 100644 --- a/mrp_production_unique_lot/README.rst +++ b/mrp_production_unique_lot/README.rst @@ -90,6 +90,7 @@ Contributors ------------ - Marina Alapont +- Jasmin Solanki Maintainers ----------- diff --git a/mrp_production_unique_lot/__manifest__.py b/mrp_production_unique_lot/__manifest__.py index 0a1450625ea..143bd9afb7e 100644 --- a/mrp_production_unique_lot/__manifest__.py +++ b/mrp_production_unique_lot/__manifest__.py @@ -4,7 +4,7 @@ "name": "MRP Production Unique Lot", "Summary": "Ensures that production lot numbers are unique and cannot be reused " "in another manufacturing order.", - "version": "16.0.1.0.0", + "version": "19.0.1.0.0", "author": "ForgeFlow, Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/manufacture", diff --git a/mrp_production_unique_lot/models/mrp_production.py b/mrp_production_unique_lot/models/mrp_production.py index 0a0a3e77801..28d09adf175 100644 --- a/mrp_production_unique_lot/models/mrp_production.py +++ b/mrp_production_unique_lot/models/mrp_production.py @@ -1,7 +1,7 @@ # Copyright 2025 ForgeFlow, S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -from odoo import _, fields, models +from odoo import fields, models from odoo.exceptions import UserError @@ -28,7 +28,8 @@ def _compute_allowed_lot_producing_ids(self): ) if record.force_lot_uniqueness and record.product_id.tracking == "lot": allowed_lots = lot_ids.filtered( - lambda lot: not record._is_finished_lot_already_produced(lot) + lambda lot, + record=record: not record._is_finished_lot_already_produced(lot) ) record.allowed_lot_producing_ids = allowed_lots else: @@ -44,16 +45,16 @@ def _check_lot_uniqueness(self): """Alert the user if the lot number has already been produced. This method is based on the odoo code for serial numbers in _check_sn_uniqueness """ - if not self.force_lot_uniqueness or not self.lot_producing_id: + if not self.force_lot_uniqueness or not self.lot_producing_ids: return if ( self.product_tracking == "lot" - and self.lot_producing_id - and self._is_finished_lot_already_produced(self.lot_producing_id) + and self.lot_producing_ids + and self._is_finished_lot_already_produced(self.lot_producing_ids) ): raise UserError( - _( + self.env._( "This lot number for product %s has already been produced", self.product_id.name, ) @@ -67,9 +68,9 @@ def _check_lot_uniqueness(self): move_line.lot_id, excluded_sml=move_line ): raise UserError( - _( - "The lot number %(number)s used for byproduct %(product_name)s" - " has already been produced", + self.env._( + "The lot number %(number)s used for byproduct " + "%(product_name)s has already been produced", number=move_line.lot_id.name, product_name=move_line.product_id.name, ) @@ -113,8 +114,8 @@ def _is_finished_lot_already_produced(self, lot, excluded_sml=None): moved_to_scrap_count = self.env["stock.move.line"].search_count( base_domain + [ - ("location_id.scrap_location", "=", False), - ("location_dest_id.scrap_location", "=", True), + ("location_id.usage", "!=", "inventory"), + ("location_dest_id.usage", "=", "inventory"), ] ) @@ -123,8 +124,8 @@ def _is_finished_lot_already_produced(self, lot, excluded_sml=None): [ ("lot_id", "=", lot.id), ("state", "=", "done"), - ("location_id.scrap_location", "=", True), - ("location_dest_id.scrap_location", "=", False), + ("location_id.usage", "=", "inventory"), + ("location_dest_id.usage", "!=", "inventory"), ] ) @@ -142,7 +143,7 @@ def _is_finished_lot_already_produced(self, lot, excluded_sml=None): # Check duplicates in current production, excluding specified move lines if any current_move_lines = self.move_finished_ids.move_line_ids - excluded_move_lines duplicates_in_current = current_move_lines.filtered( - lambda ml: ml.qty_done and ml.lot_id == lot + lambda ml: ml.quantity and ml.lot_id == lot ) return bool(duplicates_in_current) diff --git a/mrp_production_unique_lot/readme/CONTRIBUTORS.md b/mrp_production_unique_lot/readme/CONTRIBUTORS.md index 089e6dd3923..1b528d37914 100644 --- a/mrp_production_unique_lot/readme/CONTRIBUTORS.md +++ b/mrp_production_unique_lot/readme/CONTRIBUTORS.md @@ -1 +1,2 @@ - Marina Alapont \ +- Jasmin Solanki \ diff --git a/mrp_production_unique_lot/static/description/index.html b/mrp_production_unique_lot/static/description/index.html index cb6de4e800e..18013441963 100644 --- a/mrp_production_unique_lot/static/description/index.html +++ b/mrp_production_unique_lot/static/description/index.html @@ -438,6 +438,7 @@

Authors

Contributors

diff --git a/mrp_production_unique_lot/tests/test_mrp_production_unique_lot.py b/mrp_production_unique_lot/tests/test_mrp_production_unique_lot.py index 9bafc1d90cd..511e27f45bf 100644 --- a/mrp_production_unique_lot/tests/test_mrp_production_unique_lot.py +++ b/mrp_production_unique_lot/tests/test_mrp_production_unique_lot.py @@ -23,8 +23,8 @@ def setUpClass(cls): mo_form = Form(cls.mo) mo_form.qty_producing = 5 - mo_form.lot_producing_id = cls.lot mo = mo_form.save() + mo.lot_producing_ids = cls.lot mo.button_mark_done() def test_unique_lot_validation(self): @@ -41,7 +41,7 @@ def test_unique_lot_validation(self): # Try to assign the same lot mo_form = Form(mo2) mo_form.qty_producing = 10 - mo_form.lot_producing_id = self.lot + mo_form.lot_producing_ids = self.lot mo = mo_form.save() with self.assertRaises(UserError): mo.button_mark_done() @@ -50,9 +50,10 @@ def test_unique_lot_validation(self): lot2 = self.env["stock.lot"].create( {"name": "LOT-002", "product_id": self.final_product.id} ) + mo2.action_clear_lot_producing_ids() mo_form = Form(mo2) mo_form.qty_producing = 10 - mo_form.lot_producing_id = lot2 + mo_form.lot_producing_ids = lot2 mo = mo_form.save() mo.button_mark_done() @@ -60,6 +61,7 @@ def test_lot_reusable_after_unbuild(self): x = Form(self.env["mrp.unbuild"]) x.product_id = self.final_product x.mo_id = self.mo + x.lot_id = self.lot x.product_qty = self.mo.product_qty x.save().action_unbuild() @@ -76,7 +78,7 @@ def test_lot_reusable_after_unbuild(self): # Try to assign the same lot, it should not raise mo_form = Form(mo2) mo_form.qty_producing = 10 - mo_form.lot_producing_id = self.lot + mo_form.lot_producing_ids = self.lot mo = mo_form.save() mo.button_mark_done() @@ -109,6 +111,6 @@ def test_lot_reusable_after_scrap(self): # Try to assign the same lot, it should not raise mo_form = Form(mo2) mo_form.qty_producing = 10 - mo_form.lot_producing_id = self.lot + mo_form.lot_producing_ids = self.lot mo = mo_form.save() mo.button_mark_done() diff --git a/mrp_production_unique_lot/views/mrp_production_views.xml b/mrp_production_unique_lot/views/mrp_production_views.xml index 1f8b709080e..bb1454c1dd3 100644 --- a/mrp_production_unique_lot/views/mrp_production_views.xml +++ b/mrp_production_unique_lot/views/mrp_production_views.xml @@ -5,10 +5,10 @@ mrp.production - + - + [('id', 'in', allowed_lot_producing_ids)] diff --git a/mrp_production_unique_lot/views/stock_picking_views.xml b/mrp_production_unique_lot/views/stock_picking_views.xml index 116cf083bf7..2b05cc82451 100644 --- a/mrp_production_unique_lot/views/stock_picking_views.xml +++ b/mrp_production_unique_lot/views/stock_picking_views.xml @@ -5,7 +5,7 @@ stock.picking.type - +