diff --git a/stock_picking_return_lot/README.rst b/stock_picking_return_lot/README.rst new file mode 100644 index 000000000000..d38e6c0a02fd --- /dev/null +++ b/stock_picking_return_lot/README.rst @@ -0,0 +1,104 @@ +======================== +Stock Picking Return Lot +======================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:4fc5ebde82b0ced4f081cfecb7cb1defeb8d632488a9b3fbd621e0299d50d97d + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fstock--logistics--workflow-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-workflow/tree/17.0/stock_picking_return_lot + :alt: OCA/stock-logistics-workflow +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-workflow-17-0/stock-logistics-workflow-17-0-stock_picking_return_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/stock-logistics-workflow&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +When a product is tracked by lot or serial number and is returned by a +customer, it’s crucial to clearly indicate to the user which lot or +serial number can be accepted. This way, we prevent user from receiving +a product with a lot or serial number different from the original +delivery. + +This module enhances the return process by creating a separate return +line for each product/lot and automatically pre-filling it with the lot +from the original delivery. It relies on the `Stock Restrict +Lot `__ +module to enforce accurate tracking, ensuring that the reception order +reflects the correct lot or serial number that should be received. + +**Table of contents** + +.. contents:: + :local: + +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 +------- + +* Camptocamp +* ACSONE SA/NV + +Contributors +------------ + +- Iryna Vyshnevska +- `PyTech SRL `__: + + - Alessio Renda + - Sebastiano Picchi + +- `Ooops404 `__: + + - Foresti Francesco + +- `ACSONE SA/NV `__: + + - Souheil Bejaoui + +- `APSL-Nagarro `__: + + - Antoni Marroig + +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/stock-logistics-workflow `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_picking_return_lot/__init__.py b/stock_picking_return_lot/__init__.py new file mode 100644 index 000000000000..5cb1c49143f5 --- /dev/null +++ b/stock_picking_return_lot/__init__.py @@ -0,0 +1 @@ +from . import wizards diff --git a/stock_picking_return_lot/__manifest__.py b/stock_picking_return_lot/__manifest__.py new file mode 100644 index 000000000000..392a19be93b4 --- /dev/null +++ b/stock_picking_return_lot/__manifest__.py @@ -0,0 +1,14 @@ +# Copyright 2020 Camptocamp +# Copyright 2024 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Stock Picking Return Lot", + "summary": "Propagate SN/lots from origin picking to return picking.", + "version": "17.0.1.0.0", + "license": "AGPL-3", + "author": "Camptocamp, ACSONE SA/NV, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/stock-logistics-workflow", + "depends": ["stock", "stock_restrict_lot"], + "data": ["wizards/stock_return_picking.xml"], +} diff --git a/stock_picking_return_lot/i18n/it.po b/stock_picking_return_lot/i18n/it.po new file mode 100644 index 000000000000..b2e0b5230694 --- /dev/null +++ b/stock_picking_return_lot/i18n/it.po @@ -0,0 +1,37 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_return_lot +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-09-04 10:06+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.6.2\n" + +#. module: stock_picking_return_lot +#: model:ir.model.fields,field_description:stock_picking_return_lot.field_stock_return_picking_line__lot_id +msgid "Lot/Serial Number" +msgstr "Numero di lotto/serie" + +#. module: stock_picking_return_lot +#: model:ir.model.fields,field_description:stock_picking_return_lot.field_stock_return_picking_line__lots_visible +msgid "Lots Visible" +msgstr "Lotti visibili" + +#. module: stock_picking_return_lot +#: model:ir.model,name:stock_picking_return_lot.model_stock_return_picking +msgid "Return Picking" +msgstr "Prelievo di reso" + +#. module: stock_picking_return_lot +#: model:ir.model,name:stock_picking_return_lot.model_stock_return_picking_line +msgid "Return Picking Line" +msgstr "Riga prelievo di reso" diff --git a/stock_picking_return_lot/i18n/stock_picking_return_lot.pot b/stock_picking_return_lot/i18n/stock_picking_return_lot.pot new file mode 100644 index 000000000000..37c714033d36 --- /dev/null +++ b/stock_picking_return_lot/i18n/stock_picking_return_lot.pot @@ -0,0 +1,34 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_return_lot +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \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: stock_picking_return_lot +#: model:ir.model.fields,field_description:stock_picking_return_lot.field_stock_return_picking_line__lot_id +msgid "Lot/Serial Number" +msgstr "" + +#. module: stock_picking_return_lot +#: model:ir.model.fields,field_description:stock_picking_return_lot.field_stock_return_picking_line__lots_visible +msgid "Lots Visible" +msgstr "" + +#. module: stock_picking_return_lot +#: model:ir.model,name:stock_picking_return_lot.model_stock_return_picking +msgid "Return Picking" +msgstr "" + +#. module: stock_picking_return_lot +#: model:ir.model,name:stock_picking_return_lot.model_stock_return_picking_line +msgid "Return Picking Line" +msgstr "" diff --git a/stock_picking_return_lot/pyproject.toml b/stock_picking_return_lot/pyproject.toml new file mode 100644 index 000000000000..4231d0cccb3d --- /dev/null +++ b/stock_picking_return_lot/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/stock_picking_return_lot/readme/CONTRIBUTORS.md b/stock_picking_return_lot/readme/CONTRIBUTORS.md new file mode 100644 index 000000000000..a2d788da9efb --- /dev/null +++ b/stock_picking_return_lot/readme/CONTRIBUTORS.md @@ -0,0 +1,10 @@ +- Iryna Vyshnevska \<\> +- [PyTech SRL](https://www.pytech.it): + - Alessio Renda + - Sebastiano Picchi +- [Ooops404](https://www.ooops404.com): + - Foresti Francesco \<\> +- [ACSONE SA/NV](https://www.acsone.eu): + - Souheil Bejaoui \<\> +- [APSL-Nagarro](https://apsl.tech): + - Antoni Marroig \<\> diff --git a/stock_picking_return_lot/readme/DESCRIPTION.md b/stock_picking_return_lot/readme/DESCRIPTION.md new file mode 100644 index 000000000000..fcf6953de301 --- /dev/null +++ b/stock_picking_return_lot/readme/DESCRIPTION.md @@ -0,0 +1,12 @@ +When a product is tracked by lot or serial number and is returned by a +customer, it’s crucial to clearly indicate to the user which lot or +serial number can be accepted. This way, we prevent user from receiving +a product with a lot or serial number different from the original +delivery. + +This module enhances the return process by creating a separate return +line for each product/lot and automatically pre-filling it with the lot +from the original delivery. It relies on the [Stock Restrict +Lot](https://github.com/OCA/stock-logistics-workflow/tree/16.0/stock_restrict_lot) +module to enforce accurate tracking, ensuring that the reception order +reflects the correct lot or serial number that should be received. diff --git a/stock_picking_return_lot/static/description/icon.png b/stock_picking_return_lot/static/description/icon.png new file mode 100644 index 000000000000..3a0328b516c4 Binary files /dev/null and b/stock_picking_return_lot/static/description/icon.png differ diff --git a/stock_picking_return_lot/static/description/index.html b/stock_picking_return_lot/static/description/index.html new file mode 100644 index 000000000000..1297efe032e2 --- /dev/null +++ b/stock_picking_return_lot/static/description/index.html @@ -0,0 +1,451 @@ + + + + + +Stock Picking Return Lot + + + +
+

Stock Picking Return Lot

+ + +

Beta License: AGPL-3 OCA/stock-logistics-workflow Translate me on Weblate Try me on Runboat

+

When a product is tracked by lot or serial number and is returned by a +customer, it’s crucial to clearly indicate to the user which lot or +serial number can be accepted. This way, we prevent user from receiving +a product with a lot or serial number different from the original +delivery.

+

This module enhances the return process by creating a separate return +line for each product/lot and automatically pre-filling it with the lot +from the original delivery. It relies on the Stock Restrict +Lot +module to enforce accurate tracking, ensuring that the reception order +reflects the correct lot or serial number that should be received.

+

Table of contents

+ +
+

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

+
    +
  • Camptocamp
  • +
  • ACSONE SA/NV
  • +
+
+
+

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/stock-logistics-workflow project on GitHub.

+

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

+
+
+
+ + diff --git a/stock_picking_return_lot/tests/__init__.py b/stock_picking_return_lot/tests/__init__.py new file mode 100644 index 000000000000..13b150e4d3d0 --- /dev/null +++ b/stock_picking_return_lot/tests/__init__.py @@ -0,0 +1 @@ +from . import test_stock_picking_return_lot diff --git a/stock_picking_return_lot/tests/test_stock_picking_return_lot.py b/stock_picking_return_lot/tests/test_stock_picking_return_lot.py new file mode 100644 index 000000000000..549c59b94e65 --- /dev/null +++ b/stock_picking_return_lot/tests/test_stock_picking_return_lot.py @@ -0,0 +1,205 @@ +# Copyright 2020 Iryna Vyshnevska Camptocamp +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import Command +from odoo.tests.common import TransactionCase + + +class StockPickingReturnLotTest(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.picking_obj = cls.env["stock.picking"] + cls.partner = cls.env["res.partner"].create({"name": "Test"}) + cls.product = cls.env["product.product"].create( + {"name": "test_product", "type": "product", "tracking": "lot"} + ) + cls.lot_1 = cls.env["stock.lot"].create( + {"name": "000001", "product_id": cls.product.id} + ) + cls.lot_2 = cls.env["stock.lot"].create( + {"name": "000002", "product_id": cls.product.id} + ) + cls.picking_type_out = cls.env.ref("stock.picking_type_out") + cls.stock_location = cls.env.ref("stock.stock_location_stock") + cls.customer_location = cls.env.ref("stock.stock_location_customers") + cls.env["stock.quant"]._update_available_quantity( + cls.product, cls.stock_location, 1, lot_id=cls.lot_1 + ) + cls.env["stock.quant"]._update_available_quantity( + cls.product, cls.stock_location, 2, lot_id=cls.lot_2 + ) + cls.picking = cls.picking_obj.create( + { + "partner_id": cls.partner.id, + "picking_type_id": cls.picking_type_out.id, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + "move_ids": [ + Command.create( + { + "name": cls.product.name, + "product_id": cls.product.id, + "product_uom_qty": 3, + "product_uom": cls.product.uom_id.id, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ) + ], + } + ) + cls.picking.action_confirm() + cls.picking.move_ids.picked = True + cls.picking._action_done() + + @classmethod + def create_return_wiz(cls, picking): + return ( + cls.env["stock.return.picking"] + .with_context(active_id=picking.id, active_model="stock.picking") + .create({}) + ) + + def _create_picking(self, product=None): + if not product: + product = self.product + picking = self.picking_obj.create( + { + "partner_id": self.partner.id, + "picking_type_id": self.picking_type_out.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customer_location.id, + "move_ids": [ + Command.create( + { + "name": product.name, + "product_id": product.id, + "product_uom_qty": 1, + "product_uom": product.uom_id.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customer_location.id, + }, + ), + ], + } + ) + self.env["stock.move"].create( + { + "picking_id": picking.id, + "name": product.name, + "product_id": product.id, + "product_uom_qty": 1, + "product_uom": self.product.uom_id.id, + "location_id": self.stock_location.id, + "location_dest_id": self.customer_location.id, + } + ) + return picking + + def _create_validate_picking(self): + picking = self._create_picking() + picking.action_confirm() + picking.move_ids.picked = True + picking._action_done() + return picking + + def test_partial_return(self): + wiz = self.create_return_wiz(self.picking) + self.assertEqual(len(wiz.product_return_moves), 2) + return_line_1 = wiz.product_return_moves.filtered( + lambda m, lot=self.lot_1: m.lot_id == lot + ) + return_line_2 = wiz.product_return_moves.filtered( + lambda m, lot=self.lot_2: m.lot_id == lot + ) + self.assertEqual(return_line_1.quantity, 1) + self.assertEqual(return_line_2.quantity, 2) + return_line_2.quantity = 1 + picking_returned_id = wiz._create_returns()[0] + picking_returned = self.picking_obj.browse(picking_returned_id) + move_1 = picking_returned.move_ids.filtered( + lambda m, lot=self.lot_1: m.restrict_lot_id == lot + ) + move_2 = picking_returned.move_ids.filtered( + lambda m, lot=self.lot_2: m.restrict_lot_id == lot + ) + self.assertEqual(move_1.move_line_ids.lot_id, self.lot_1) + self.assertEqual(move_2.move_line_ids.lot_id, self.lot_2) + self.assertEqual(move_2.product_qty, 1) + + def test_full_return_after_partial_return(self): + self.test_partial_return() + wiz = self.create_return_wiz(self.picking) + self.assertEqual(len(wiz.product_return_moves), 2) + + return_line_1 = wiz.product_return_moves.filtered( + lambda m, lot=self.lot_1: m.lot_id == lot + ) + return_line_2 = wiz.product_return_moves.filtered( + lambda m, lot=self.lot_2: m.lot_id == lot + ) + self.assertEqual(return_line_1.quantity, 0) + self.assertEqual(return_line_2.quantity, 1) + picking_returned_id = wiz._create_returns()[0] + picking_returned = self.picking_obj.browse(picking_returned_id) + move_1 = picking_returned.move_ids.filtered( + lambda m, lot=self.lot_1: m.restrict_lot_id == lot + ) + move_2 = picking_returned.move_ids.filtered( + lambda m, lot=self.lot_2: m.restrict_lot_id == lot + ) + self.assertFalse(move_1) + self.assertEqual(move_2.move_line_ids.lot_id, self.lot_2) + self.assertEqual(move_2.product_qty, 1) + + def test_multiple_move_same_product_different_lot(self): + self.env["stock.quant"]._update_available_quantity( + self.product, self.stock_location, 1, lot_id=self.lot_1 + ) + self.env["stock.quant"]._update_available_quantity( + self.product, self.stock_location, 1, lot_id=self.lot_2 + ) + picking = self._create_validate_picking() + wiz = self.create_return_wiz(picking) + self.assertEqual(len(wiz.product_return_moves), 2) + return_line_1 = wiz.product_return_moves.filtered( + lambda m, lot=self.lot_1: m.lot_id == lot + ) + return_line_2 = wiz.product_return_moves.filtered( + lambda m, lot=self.lot_2: m.lot_id == lot + ) + self.assertEqual(return_line_1.quantity, 1) + self.assertEqual(return_line_2.quantity, 1) + picking_returned_id = wiz._create_returns()[0] + picking_returned = self.picking_obj.browse(picking_returned_id) + move_1 = picking_returned.move_ids.filtered( + lambda m, lot=self.lot_1: m.restrict_lot_id == lot + ) + move_2 = picking_returned.move_ids.filtered( + lambda m, lot=self.lot_2: m.restrict_lot_id == lot + ) + self.assertEqual(move_1.move_line_ids.lot_id, self.lot_1) + self.assertEqual(move_2.move_line_ids.lot_id, self.lot_2) + self.assertEqual(move_2.product_qty, 1) + + def test_multiple_move_same_product_same_lot(self): + self.env["stock.quant"]._update_available_quantity( + self.product, self.stock_location, 2, lot_id=self.lot_1 + ) + picking = self._create_validate_picking() + wiz = self.create_return_wiz(picking) + self.assertEqual(len(wiz.product_return_moves), 2) + return_lines = wiz.product_return_moves.filtered( + lambda m, lot=self.lot_1: m.lot_id == lot + ) + self.assertEqual(return_lines[0].quantity, 1) + self.assertEqual(return_lines[1].quantity, 1) + picking_returned_id = wiz._create_returns()[0] + picking_returned = self.picking_obj.browse(picking_returned_id) + moves = picking_returned.move_ids.filtered( + lambda m, lot=self.lot_1: m.restrict_lot_id == lot + ) + self.assertEqual(moves.move_line_ids.lot_id, self.lot_1) + self.assertEqual(moves[0].product_qty, 1) + self.assertEqual(moves[1].product_qty, 1) diff --git a/stock_picking_return_lot/wizards/__init__.py b/stock_picking_return_lot/wizards/__init__.py new file mode 100644 index 000000000000..18b78728aae5 --- /dev/null +++ b/stock_picking_return_lot/wizards/__init__.py @@ -0,0 +1,2 @@ +from . import stock_return_picking +from . import stock_return_picking_line diff --git a/stock_picking_return_lot/wizards/stock_return_picking.py b/stock_picking_return_lot/wizards/stock_return_picking.py new file mode 100644 index 000000000000..ba813089afa9 --- /dev/null +++ b/stock_picking_return_lot/wizards/stock_return_picking.py @@ -0,0 +1,92 @@ +# Copyright 2020 Iryna Vyshnevska Camptocamp +# Copyright 2024 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from collections import defaultdict + +from odoo import api, models +from odoo.tools.float_utils import float_round + + +class ReturnPicking(models.TransientModel): + _inherit = "stock.return.picking" + + def _get_qty_by_product_lot(self): + res = defaultdict(float) + for group in self.env["stock.move.line"].read_group( + [ + ("picking_id", "=", self.picking_id.id), + ("state", "=", "done"), + ("move_id.scrapped", "=", False), + ], + ["quantity:sum"], + ["move_id", "lot_id"], + lazy=False, + ): + lot_id = group.get("lot_id")[0] if group.get("lot_id") else False + move_id = group.get("move_id")[0] + quantity = group.get("quantity") + res[(move_id, lot_id)] += quantity + return res + + @api.depends("picking_id") + def _compute_moves_locations(self): + res = super()._compute_moves_locations() + product_return_moves = [(5,)] + line_fields = [f for f in self.env["stock.return.picking.line"]._fields.keys()] + product_return_moves_data_tmpl = self.env[ + "stock.return.picking.line" + ].default_get(line_fields) + qty_by_product_lot = self._get_qty_by_product_lot() + for (move_id, lot_id), quantity in qty_by_product_lot.items(): + product_return_moves_data = dict(product_return_moves_data_tmpl) + product_return_moves_data.update( + self._prepare_stock_return_picking_line_vals(move_id, lot_id, quantity) + ) + product_return_moves.append((0, 0, product_return_moves_data)) + if self.picking_id: + self.product_return_moves = product_return_moves + return res + + @api.model + def _prepare_stock_return_picking_line_vals(self, move_id, lot_id, quantity): + move = self.env["stock.move"].browse(move_id) + quantity = quantity + for dest_move in move.move_dest_ids: + if ( + not dest_move.origin_returned_move_id + or dest_move.origin_returned_move_id != move + ): + continue + + if ( + dest_move.restrict_lot_id + and dest_move.restrict_lot_id.id == lot_id + or not lot_id + ): + if dest_move.state in ("partially_available", "assigned"): + quantity -= sum(dest_move.move_line_ids.mapped("quantity")) + elif dest_move.state == "done": + quantity -= dest_move.product_qty + quantity = float_round( + quantity, precision_rounding=move.product_id.uom_id.rounding + ) + return { + "product_id": move.product_id.id, + "quantity": quantity, + "move_id": move.id, + "uom_id": move.product_id.uom_id.id, + "lot_id": lot_id, + } + + def _prepare_move_default_values(self, return_line, new_picking): + vals = super()._prepare_move_default_values(return_line, new_picking) + vals["restrict_lot_id"] = return_line.lot_id.id + return vals + + def _create_returns(self): + res = super()._create_returns() + picking_returned = self.env["stock.picking"].browse(res[0]) + for ml in picking_returned.move_line_ids: + ml.lot_id = ml.move_id.restrict_lot_id + return res diff --git a/stock_picking_return_lot/wizards/stock_return_picking.xml b/stock_picking_return_lot/wizards/stock_return_picking.xml new file mode 100644 index 000000000000..2193d2470dec --- /dev/null +++ b/stock_picking_return_lot/wizards/stock_return_picking.xml @@ -0,0 +1,21 @@ + + + + + stock.return.picking + + + + + + + + + diff --git a/stock_picking_return_lot/wizards/stock_return_picking_line.py b/stock_picking_return_lot/wizards/stock_return_picking_line.py new file mode 100644 index 000000000000..c132e5cd3bf6 --- /dev/null +++ b/stock_picking_return_lot/wizards/stock_return_picking_line.py @@ -0,0 +1,20 @@ +# Copyright 2024 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class StockReturnPickingLine(models.TransientModel): + _inherit = "stock.return.picking.line" + + lot_id = fields.Many2one( + "stock.lot", + string="Lot/Serial Number", + domain="[('product_id', '=', product_id)]", + ) + lots_visible = fields.Boolean(compute="_compute_lots_visible") + + @api.depends("product_id.tracking") + def _compute_lots_visible(self): + for rec in self: + rec.lots_visible = rec.product_id.tracking != "none"