From 84de2d48d2ac769d3e968320810ab91e81378178 Mon Sep 17 00:00:00 2001 From: Mateu Griful Date: Wed, 14 Jul 2021 13:58:02 +0200 Subject: [PATCH 01/11] [ADD] stock_packaging_qty --- stock_move_packaging_qty/__init__.py | 1 + stock_move_packaging_qty/__manifest__.py | 14 +++ stock_move_packaging_qty/models/__init__.py | 1 + stock_move_packaging_qty/models/stock_move.py | 112 ++++++++++++++++++ .../readme/CONTRIBUTORS.rst | 2 + .../readme/DESCRIPTION.rst | 1 + stock_move_packaging_qty/tests/__init__.py | 1 + .../tests/test_stock_move_packaging_qty.py | 46 +++++++ .../views/stock_move_tree_view.xml | 16 +++ .../views/stock_picking_form_view.xml | 19 +++ 10 files changed, 213 insertions(+) create mode 100644 stock_move_packaging_qty/__init__.py create mode 100644 stock_move_packaging_qty/__manifest__.py create mode 100644 stock_move_packaging_qty/models/__init__.py create mode 100644 stock_move_packaging_qty/models/stock_move.py create mode 100644 stock_move_packaging_qty/readme/CONTRIBUTORS.rst create mode 100644 stock_move_packaging_qty/readme/DESCRIPTION.rst create mode 100644 stock_move_packaging_qty/tests/__init__.py create mode 100644 stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py create mode 100644 stock_move_packaging_qty/views/stock_move_tree_view.xml create mode 100644 stock_move_packaging_qty/views/stock_picking_form_view.xml diff --git a/stock_move_packaging_qty/__init__.py b/stock_move_packaging_qty/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/stock_move_packaging_qty/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_move_packaging_qty/__manifest__.py b/stock_move_packaging_qty/__manifest__.py new file mode 100644 index 000000000..a2b128217 --- /dev/null +++ b/stock_move_packaging_qty/__manifest__.py @@ -0,0 +1,14 @@ +# Copyright 2021 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +{ + "name": "Stock Packaging Qty", + "summary": "Add packaging fields in the stock moves", + "version": "13.0.1.1.0", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "category": "Warehouse", + "depends": ["stock"], + "data": ["views/stock_picking_form_view.xml", "views/stock_move_tree_view.xml"], + "license": "LGPL-3", + "installable": True, +} diff --git a/stock_move_packaging_qty/models/__init__.py b/stock_move_packaging_qty/models/__init__.py new file mode 100644 index 000000000..6bda2d242 --- /dev/null +++ b/stock_move_packaging_qty/models/__init__.py @@ -0,0 +1 @@ +from . import stock_move diff --git a/stock_move_packaging_qty/models/stock_move.py b/stock_move_packaging_qty/models/stock_move.py new file mode 100644 index 000000000..0495a9f97 --- /dev/null +++ b/stock_move_packaging_qty/models/stock_move.py @@ -0,0 +1,112 @@ +# Copyright 2020 Camptocamp SA +# Copyright 2021 ForgeFlow, S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import _, api, fields, models +from odoo.exceptions import UserError + +from odoo.addons import decimal_precision as dp + + +class StockPicking(models.Model): + _inherit = "stock.move" + + product_packaging = fields.Many2one( + comodel_name="product.packaging", + string="Package", + default=False, + check_company=True, + ) + product_packaging_qty = fields.Float( + string="Package quantity", + compute="_compute_product_packaging_qty", + inverse="_inverse_product_packaging_qty", + digits=dp.get_precision("Product Unit of Measure"), + ) + + @api.depends( + "product_qty", "product_uom", "product_packaging", "product_packaging.qty" + ) + def _compute_product_packaging_qty(self): + for move in self: + if ( + not move.product_packaging + or move.product_qty == 0 + or move.product_packaging.qty == 0 + ): + move.product_packaging_qty = 0 + continue + # Consider uom + if move.product_id.uom_id != move.product_uom: + product_qty = move.product_uom._compute_quantity( + move.product_uom_qty, move.product_id.uom_id + ) + else: + product_qty = move.product_uom_qty + move.product_packaging_qty = product_qty / move.product_packaging.qty + + def _prepare_product_packaging_qty_values(self): + return { + "product_uom_qty": self.product_packaging.qty * self.product_packaging_qty, + "product_uom": self.product_packaging.product_uom_id.id, + } + + def _inverse_product_packaging_qty(self): + for move in self: + if move.product_packaging_qty and not move.product_packaging: + raise UserError( + _( + "You must define a package before setting a quantity " + "of said package." + ) + ) + if move.product_packaging and move.product_packaging.qty == 0: + raise UserError( + _("Please select a packaging with a quantity bigger than 0") + ) + if move.product_packaging and move.product_packaging_qty: + move.write(move._prepare_product_packaging_qty_values()) + + @api.onchange("product_packaging") + def _onchange_product_packaging(self): + if self.product_packaging: + self.update( + { + "product_packaging_qty": 1, + "product_uom_qty": self.product_packaging.qty, + "product_uom": self.product_id.uom_id, + } + ) + else: + self.update({"product_packaging_qty": 0}) + if self.product_packaging: + return self._check_package() + + @api.onchange("product_packaging_qty") + def _onchange_product_packaging_qty(self): + if self.product_packaging_qty and self.product_packaging: + self.update(self._prepare_product_packaging_qty_values()) + + @api.onchange("product_uom_qty", "product_uom") + def onchange_quantity(self): + res = super().onchange_quantity() + if not res: + res = self._check_package() + return res + + def _check_package(self): + default_uom = self.product_id.uom_id + pack = self.product_packaging + qty = self.product_qty + q = default_uom._compute_quantity(pack.qty, self.product_uom) + if qty and q and round(qty % q, 2): + newqty = qty - (qty % q) + q + return { + "warning": { + "title": _("Warning"), + "message": _( + "This product is packaged by %.2f %s. You should use %.2f %s." + ) + % (pack.qty, default_uom.name, newqty, self.product_uom.name), + }, + } + return {} diff --git a/stock_move_packaging_qty/readme/CONTRIBUTORS.rst b/stock_move_packaging_qty/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..087dd2923 --- /dev/null +++ b/stock_move_packaging_qty/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Mateu Griful +* Lois Rilo diff --git a/stock_move_packaging_qty/readme/DESCRIPTION.rst b/stock_move_packaging_qty/readme/DESCRIPTION.rst new file mode 100644 index 000000000..6de170dfd --- /dev/null +++ b/stock_move_packaging_qty/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Add packaging fields in the stock moves diff --git a/stock_move_packaging_qty/tests/__init__.py b/stock_move_packaging_qty/tests/__init__.py new file mode 100644 index 000000000..7872eae71 --- /dev/null +++ b/stock_move_packaging_qty/tests/__init__.py @@ -0,0 +1 @@ +from . import test_stock_move_packaging_qty diff --git a/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py b/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py new file mode 100644 index 000000000..a2096240a --- /dev/null +++ b/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py @@ -0,0 +1,46 @@ +# Copyright 2021 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo.tests import SavepointCase + + +class TestStockMovePackagingQty(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + cls.partner = cls.env.ref("base.res_partner_12") + cls.product = cls.env.ref("product.product_product_9") + cls.packaging = cls.env["product.packaging"].create( + {"name": "Test packaging", "product_id": cls.product.id, "qty": 5.0} + ) + cls.wh = cls.env["stock.warehouse"].create( + {"name": "Base Warehouse", "code": "TESTWH"} + ) + cls.categ_unit = cls.env.ref("uom.product_uom_categ_unit") + cls.uom_unit = cls.env["uom.uom"].search( + [("category_id", "=", cls.categ_unit.id), ("uom_type", "=", "reference")], + limit=1, + ) + cls.customer_location = cls.env.ref("stock.stock_location_customers") + cls.supplier_location = cls.env.ref("stock.stock_location_suppliers") + + def test_product_packaging_qty(self): + move = self.env["stock.move"].create( + { + "name": "Move", + "location_id": self.supplier_location.id, + "location_dest_id": self.wh.lot_stock_id.id, + "partner_id": self.partner.id, + "product_id": self.product.id, + "product_uom": self.product.uom_id.id, + "product_uom_qty": 3.0, + "price_unit": 10.0, + } + ) + move.write({"product_packaging": self.packaging.id}) + move._onchange_product_packaging() + self.assertEqual(move.product_uom_qty, 5.0) + self.assertEqual(move.product_packaging_qty, 1.0) + move.write({"product_packaging_qty": 3.0}) + self.assertEqual(move.product_uom_qty, 15.0) diff --git a/stock_move_packaging_qty/views/stock_move_tree_view.xml b/stock_move_packaging_qty/views/stock_move_tree_view.xml new file mode 100644 index 000000000..e18b4442a --- /dev/null +++ b/stock_move_packaging_qty/views/stock_move_tree_view.xml @@ -0,0 +1,16 @@ + + + + + view.move.extra.tree + stock.move + + + + + + + + + + diff --git a/stock_move_packaging_qty/views/stock_picking_form_view.xml b/stock_move_packaging_qty/views/stock_picking_form_view.xml new file mode 100644 index 000000000..cea5f5c80 --- /dev/null +++ b/stock_move_packaging_qty/views/stock_picking_form_view.xml @@ -0,0 +1,19 @@ + + + + + stock.picking.form + stock.picking + + + + + + + + + + From 16ca5698e36535a0da294497206760dd06e3fb0e Mon Sep 17 00:00:00 2001 From: oca-travis Date: Mon, 26 Jul 2021 09:24:36 +0000 Subject: [PATCH 02/11] [UPD] Update stock_move_packaging_qty.pot --- .../i18n/stock_move_packaging_qty.pot | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot diff --git a/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot b/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot new file mode 100644 index 000000000..467e817b6 --- /dev/null +++ b/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot @@ -0,0 +1,53 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_move_packaging_qty +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.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_move_packaging_qty +#: model:ir.model.fields,field_description:stock_move_packaging_qty.field_stock_move__product_packaging +msgid "Package" +msgstr "" + +#. module: stock_move_packaging_qty +#: model:ir.model.fields,field_description:stock_move_packaging_qty.field_stock_move__product_packaging_qty +msgid "Package quantity" +msgstr "" + +#. module: stock_move_packaging_qty +#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 +#, python-format +msgid "Please select a packaging with a quantity bigger than 0" +msgstr "" + +#. module: stock_move_packaging_qty +#: model:ir.model,name:stock_move_packaging_qty.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: stock_move_packaging_qty +#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 +#, python-format +msgid "This product is packaged by %.2f %s. You should use %.2f %s." +msgstr "" + +#. module: stock_move_packaging_qty +#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 +#, python-format +msgid "Warning" +msgstr "" + +#. module: stock_move_packaging_qty +#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 +#, python-format +msgid "You must define a package before setting a quantity of said package." +msgstr "" From 7f338839715855cfa478714f7b1d3f71c0aa62da Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 26 Jul 2021 10:01:20 +0000 Subject: [PATCH 03/11] [UPD] README.rst --- stock_move_packaging_qty/README.rst | 74 +++ .../static/description/index.html | 420 ++++++++++++++++++ 2 files changed, 494 insertions(+) create mode 100644 stock_move_packaging_qty/README.rst create mode 100644 stock_move_packaging_qty/static/description/index.html diff --git a/stock_move_packaging_qty/README.rst b/stock_move_packaging_qty/README.rst new file mode 100644 index 000000000..e4db41a6d --- /dev/null +++ b/stock_move_packaging_qty/README.rst @@ -0,0 +1,74 @@ +=================== +Stock Packaging Qty +=================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_move_packaging_qty + :alt: OCA/stock-logistics-warehouse +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-13-0/stock-logistics-warehouse-13-0-stock_move_packaging_qty + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/153/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Add packaging fields in the stock moves + +**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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ForgeFlow + +Contributors +~~~~~~~~~~~~ + +* Mateu Griful +* Lois Rilo + +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-warehouse `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_move_packaging_qty/static/description/index.html b/stock_move_packaging_qty/static/description/index.html new file mode 100644 index 000000000..17eb89a1a --- /dev/null +++ b/stock_move_packaging_qty/static/description/index.html @@ -0,0 +1,420 @@ + + + + + + +Stock Packaging Qty + + + +
+

Stock Packaging Qty

+ + +

Beta License: LGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runbot

+

Add packaging fields in the stock moves

+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+ +
+

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-warehouse project on GitHub.

+

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

+
+
+
+ + From 45821522c0cd36b8dbd9ca07d935c0de28123bf8 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 26 Jul 2021 10:01:20 +0000 Subject: [PATCH 04/11] [ADD] icon.png --- .../static/description/icon.png | Bin 0 -> 9455 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 stock_move_packaging_qty/static/description/icon.png diff --git a/stock_move_packaging_qty/static/description/icon.png b/stock_move_packaging_qty/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 From 21e6a2095e6240d20829580758c3acf02c583c9f Mon Sep 17 00:00:00 2001 From: Carlos Roca Date: Thu, 29 Jul 2021 08:05:16 +0200 Subject: [PATCH 05/11] [FIX] stock_move_packaging_qty: Warning on runbot Since v13 the use of decimal_precision is deprecated, so we have to use the correct way. --- stock_move_packaging_qty/models/stock_move.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stock_move_packaging_qty/models/stock_move.py b/stock_move_packaging_qty/models/stock_move.py index 0495a9f97..352462ad3 100644 --- a/stock_move_packaging_qty/models/stock_move.py +++ b/stock_move_packaging_qty/models/stock_move.py @@ -4,8 +4,6 @@ from odoo import _, api, fields, models from odoo.exceptions import UserError -from odoo.addons import decimal_precision as dp - class StockPicking(models.Model): _inherit = "stock.move" @@ -20,7 +18,7 @@ class StockPicking(models.Model): string="Package quantity", compute="_compute_product_packaging_qty", inverse="_inverse_product_packaging_qty", - digits=dp.get_precision("Product Unit of Measure"), + digits="Product Unit of Measure", ) @api.depends( From e5672fadf3058141f1cc6298850c8617075b7e76 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Thu, 29 Jul 2021 06:45:58 +0000 Subject: [PATCH 06/11] [UPD] Update stock_move_packaging_qty.pot --- stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot b/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot index 467e817b6..bbf3e0442 100644 --- a/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot +++ b/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot @@ -25,6 +25,7 @@ msgstr "" #. module: stock_move_packaging_qty #: code:addons/stock_move_packaging_qty/models/stock_move.py:0 +#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 #, python-format msgid "Please select a packaging with a quantity bigger than 0" msgstr "" @@ -36,18 +37,21 @@ msgstr "" #. module: stock_move_packaging_qty #: code:addons/stock_move_packaging_qty/models/stock_move.py:0 +#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 #, python-format msgid "This product is packaged by %.2f %s. You should use %.2f %s." msgstr "" #. module: stock_move_packaging_qty #: code:addons/stock_move_packaging_qty/models/stock_move.py:0 +#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 #, python-format msgid "Warning" msgstr "" #. module: stock_move_packaging_qty #: code:addons/stock_move_packaging_qty/models/stock_move.py:0 +#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 #, python-format msgid "You must define a package before setting a quantity of said package." msgstr "" From b613f44034e629e49d684c56b48d1e485407ceec Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 29 Jul 2021 07:22:44 +0000 Subject: [PATCH 07/11] stock_move_packaging_qty 13.0.1.1.1 --- stock_move_packaging_qty/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock_move_packaging_qty/__manifest__.py b/stock_move_packaging_qty/__manifest__.py index a2b128217..268c8f475 100644 --- a/stock_move_packaging_qty/__manifest__.py +++ b/stock_move_packaging_qty/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Stock Packaging Qty", "summary": "Add packaging fields in the stock moves", - "version": "13.0.1.1.0", + "version": "13.0.1.1.1", "author": "ForgeFlow, Odoo Community Association (OCA)", "website": "https://github.com/OCA/stock-logistics-warehouse", "category": "Warehouse", From b930d73b86448a125ca019515e6eb2140c7f4d96 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Thu, 29 Jul 2021 07:41:35 +0000 Subject: [PATCH 08/11] [UPD] Update stock_move_packaging_qty.pot --- stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot | 4 ---- 1 file changed, 4 deletions(-) diff --git a/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot b/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot index bbf3e0442..467e817b6 100644 --- a/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot +++ b/stock_move_packaging_qty/i18n/stock_move_packaging_qty.pot @@ -25,7 +25,6 @@ msgstr "" #. module: stock_move_packaging_qty #: code:addons/stock_move_packaging_qty/models/stock_move.py:0 -#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 #, python-format msgid "Please select a packaging with a quantity bigger than 0" msgstr "" @@ -37,21 +36,18 @@ msgstr "" #. module: stock_move_packaging_qty #: code:addons/stock_move_packaging_qty/models/stock_move.py:0 -#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 #, python-format msgid "This product is packaged by %.2f %s. You should use %.2f %s." msgstr "" #. module: stock_move_packaging_qty #: code:addons/stock_move_packaging_qty/models/stock_move.py:0 -#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 #, python-format msgid "Warning" msgstr "" #. module: stock_move_packaging_qty #: code:addons/stock_move_packaging_qty/models/stock_move.py:0 -#: code:addons/stock_move_packaging_qty/models/stock_move.py:0 #, python-format msgid "You must define a package before setting a quantity of said package." msgstr "" From 27a237d6ac0d89fa821c3187b83ff3afcdb32296 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 28 Aug 2023 07:48:19 +0100 Subject: [PATCH 09/11] [IMP] stock_move_packaging_qty: black, isort, prettier --- .../odoo/addons/stock_move_packaging_qty | 1 + setup/stock_move_packaging_qty/setup.py | 6 ++++++ 2 files changed, 7 insertions(+) create mode 120000 setup/stock_move_packaging_qty/odoo/addons/stock_move_packaging_qty create mode 100644 setup/stock_move_packaging_qty/setup.py diff --git a/setup/stock_move_packaging_qty/odoo/addons/stock_move_packaging_qty b/setup/stock_move_packaging_qty/odoo/addons/stock_move_packaging_qty new file mode 120000 index 000000000..36962e5e5 --- /dev/null +++ b/setup/stock_move_packaging_qty/odoo/addons/stock_move_packaging_qty @@ -0,0 +1 @@ +../../../../stock_move_packaging_qty \ No newline at end of file diff --git a/setup/stock_move_packaging_qty/setup.py b/setup/stock_move_packaging_qty/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/stock_move_packaging_qty/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From a382f0eb3cebf95d88350e518df72ff387d39440 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 28 Aug 2023 09:18:37 +0100 Subject: [PATCH 10/11] [MIG] stock_move_packaging_qty: migrate to 16.0 - Code and DB migrations to use upstream field `product_packaging_id`, introduced in https://github.com/odoo/odoo/pull/68654. - Test class moved to `post_install`, to let it pass if `sale_stock` is installed too. - Satisfy new linters. @moduon MT-3694 --- stock_move_packaging_qty/__manifest__.py | 3 +- .../migrations/15.0.0/pre-migrate.py | 20 +++++++ stock_move_packaging_qty/models/stock_move.py | 55 +++++++++---------- .../readme/CONTRIBUTORS.rst | 1 + .../tests/test_stock_move_packaging_qty.py | 20 ++++++- .../views/stock_move_tree_view.xml | 25 ++++----- .../views/stock_picking_form_view.xml | 33 +++++------ 7 files changed, 92 insertions(+), 65 deletions(-) create mode 100644 stock_move_packaging_qty/migrations/15.0.0/pre-migrate.py diff --git a/stock_move_packaging_qty/__manifest__.py b/stock_move_packaging_qty/__manifest__.py index 268c8f475..723ef8051 100644 --- a/stock_move_packaging_qty/__manifest__.py +++ b/stock_move_packaging_qty/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Stock Packaging Qty", "summary": "Add packaging fields in the stock moves", - "version": "13.0.1.1.1", + "version": "16.0.1.0.0", "author": "ForgeFlow, Odoo Community Association (OCA)", "website": "https://github.com/OCA/stock-logistics-warehouse", "category": "Warehouse", @@ -11,4 +11,5 @@ "data": ["views/stock_picking_form_view.xml", "views/stock_move_tree_view.xml"], "license": "LGPL-3", "installable": True, + "maintainers": ["yajo"], } diff --git a/stock_move_packaging_qty/migrations/15.0.0/pre-migrate.py b/stock_move_packaging_qty/migrations/15.0.0/pre-migrate.py new file mode 100644 index 000000000..dda7c83db --- /dev/null +++ b/stock_move_packaging_qty/migrations/15.0.0/pre-migrate.py @@ -0,0 +1,20 @@ +# Copyright 2023 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from openupgradelib import openupgrade + + +def migrate(cr, version): + """Use upstream column. + + In https://github.com/odoo/odoo/pull/68654, upstream added product_packaging_id. + That feature is removed from this module and migrated there. + """ + if openupgrade.column_exists(cr, "stock_move", "product_packaging"): + openupgrade.rename_columns( + cr, + { + "stock_move": [ + ("product_packaging", "product_packaging_id"), + ], + }, + ) diff --git a/stock_move_packaging_qty/models/stock_move.py b/stock_move_packaging_qty/models/stock_move.py index 352462ad3..9e316a018 100644 --- a/stock_move_packaging_qty/models/stock_move.py +++ b/stock_move_packaging_qty/models/stock_move.py @@ -8,28 +8,21 @@ from odoo.exceptions import UserError class StockPicking(models.Model): _inherit = "stock.move" - product_packaging = fields.Many2one( - comodel_name="product.packaging", - string="Package", - default=False, - check_company=True, - ) product_packaging_qty = fields.Float( string="Package quantity", compute="_compute_product_packaging_qty", inverse="_inverse_product_packaging_qty", - digits="Product Unit of Measure", ) @api.depends( - "product_qty", "product_uom", "product_packaging", "product_packaging.qty" + "product_qty", "product_uom", "product_packaging_id", "product_packaging_id.qty" ) def _compute_product_packaging_qty(self): for move in self: if ( - not move.product_packaging + not move.product_packaging_id or move.product_qty == 0 - or move.product_packaging.qty == 0 + or move.product_packaging_id.qty == 0 ): move.product_packaging_qty = 0 continue @@ -40,60 +33,58 @@ class StockPicking(models.Model): ) else: product_qty = move.product_uom_qty - move.product_packaging_qty = product_qty / move.product_packaging.qty + move.product_packaging_qty = product_qty / move.product_packaging_id.qty def _prepare_product_packaging_qty_values(self): return { - "product_uom_qty": self.product_packaging.qty * self.product_packaging_qty, - "product_uom": self.product_packaging.product_uom_id.id, + "product_uom_qty": self.product_packaging_id.qty + * self.product_packaging_qty, + "product_uom": self.product_packaging_id.product_uom_id.id, } def _inverse_product_packaging_qty(self): for move in self: - if move.product_packaging_qty and not move.product_packaging: + if move.product_packaging_qty and not move.product_packaging_id: raise UserError( _( "You must define a package before setting a quantity " "of said package." ) ) - if move.product_packaging and move.product_packaging.qty == 0: + if move.product_packaging_id and move.product_packaging_id.qty == 0: raise UserError( _("Please select a packaging with a quantity bigger than 0") ) - if move.product_packaging and move.product_packaging_qty: + if move.product_packaging_id and move.product_packaging_qty: move.write(move._prepare_product_packaging_qty_values()) - @api.onchange("product_packaging") + @api.onchange("product_packaging_id") def _onchange_product_packaging(self): - if self.product_packaging: + if self.product_packaging_id: self.update( { "product_packaging_qty": 1, - "product_uom_qty": self.product_packaging.qty, + "product_uom_qty": self.product_packaging_id.qty, "product_uom": self.product_id.uom_id, } ) else: self.update({"product_packaging_qty": 0}) - if self.product_packaging: + if self.product_packaging_id: return self._check_package() @api.onchange("product_packaging_qty") def _onchange_product_packaging_qty(self): - if self.product_packaging_qty and self.product_packaging: + if self.product_packaging_qty and self.product_packaging_id: self.update(self._prepare_product_packaging_qty_values()) @api.onchange("product_uom_qty", "product_uom") - def onchange_quantity(self): - res = super().onchange_quantity() - if not res: - res = self._check_package() - return res + def _onchange_product_uom_check_package(self): + return self._check_package() def _check_package(self): default_uom = self.product_id.uom_id - pack = self.product_packaging + pack = self.product_packaging_id qty = self.product_qty q = default_uom._compute_quantity(pack.qty, self.product_uom) if qty and q and round(qty % q, 2): @@ -102,9 +93,15 @@ class StockPicking(models.Model): "warning": { "title": _("Warning"), "message": _( - "This product is packaged by %.2f %s. You should use %.2f %s." + "This product is packaged by %(old_qty).2f %(old_uom)s. " + "You should use %(new_qty).2f %(new_uom)s." ) - % (pack.qty, default_uom.name, newqty, self.product_uom.name), + % { + "old_qty": pack.qty, + "old_uom": default_uom.name, + "new_qty": newqty, + "new_uom": self.product_uom.name, + }, }, } return {} diff --git a/stock_move_packaging_qty/readme/CONTRIBUTORS.rst b/stock_move_packaging_qty/readme/CONTRIBUTORS.rst index 087dd2923..430ace9f1 100644 --- a/stock_move_packaging_qty/readme/CONTRIBUTORS.rst +++ b/stock_move_packaging_qty/readme/CONTRIBUTORS.rst @@ -1,2 +1,3 @@ * Mateu Griful * Lois Rilo +* Jairo Llopis (`Moduon `__) diff --git a/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py b/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py index a2096240a..7db980e76 100644 --- a/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py +++ b/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py @@ -1,10 +1,11 @@ # Copyright 2021 ForgeFlow S.L. (https://www.forgeflow.com) # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). -from odoo.tests import SavepointCase +from odoo.tests import Form, TransactionCase, tagged -class TestStockMovePackagingQty(SavepointCase): +@tagged("post_install", "-at_install") +class TestStockMovePackagingQty(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() @@ -38,9 +39,22 @@ class TestStockMovePackagingQty(SavepointCase): "price_unit": 10.0, } ) - move.write({"product_packaging": self.packaging.id}) + move.write({"product_packaging_id": self.packaging.id}) move._onchange_product_packaging() self.assertEqual(move.product_uom_qty, 5.0) self.assertEqual(move.product_packaging_qty, 1.0) move.write({"product_packaging_qty": 3.0}) self.assertEqual(move.product_uom_qty, 15.0) + + def test_product_uom_qty_change(self): + picking_f = Form(self.env["stock.picking"]) + picking_f.partner_id = self.partner + picking_f.picking_type_id = self.env.ref("stock.picking_type_out") + with picking_f.move_ids_without_package.new() as move_f: + move_f.product_id = self.product + self.assertEqual(move_f.product_uom_qty, 1) + self.assertEqual(move_f.product_packaging_qty, 0) + self.assertFalse(move_f.product_packaging_id) + move_f.product_packaging_id = self.packaging + self.assertEqual(move_f.product_uom_qty, 5) + self.assertEqual(move_f.product_packaging_qty, 1) diff --git a/stock_move_packaging_qty/views/stock_move_tree_view.xml b/stock_move_packaging_qty/views/stock_move_tree_view.xml index e18b4442a..65567141d 100644 --- a/stock_move_packaging_qty/views/stock_move_tree_view.xml +++ b/stock_move_packaging_qty/views/stock_move_tree_view.xml @@ -1,16 +1,13 @@ - - - - view.move.extra.tree - stock.move - - - - - - + + + view.move.extra.tree + stock.move + + + + - - - + + + diff --git a/stock_move_packaging_qty/views/stock_picking_form_view.xml b/stock_move_packaging_qty/views/stock_picking_form_view.xml index cea5f5c80..76a07a16d 100644 --- a/stock_move_packaging_qty/views/stock_picking_form_view.xml +++ b/stock_move_packaging_qty/views/stock_picking_form_view.xml @@ -1,19 +1,16 @@ - - - - stock.picking.form - stock.picking - - - - - - - - - - + + + stock.picking.form + stock.picking + + + + + + + + From 592dc5916d3474bed426aec4078cc066428fe3d1 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 29 Aug 2023 12:27:29 +0100 Subject: [PATCH 11/11] [REF] stock_move_packaging_qty: closer match upstream UX Without this patch, a user that wasn't able to edit a picking product qty would be able to edit the packaging qty and produce a product qty update (which they shouldn't be able to do). Now, the field is hidden or readonly when the `product_uom_qty` field is too. Also, the inverse method of `product_packaging_qty` was only being triggered when saving. That doesn't fit well with v16, where saving is pseudo-automatic. Thus, the inverse is reused as an onchange. To make it worse, the inverse method had a lot of validations. If they were meaningful, they should have been constraints instead. But they really didn't make any sense because they were testing impossible scenarios. For example, they were testing you didn't update the field when there's no packaging, but that's fixed now with a dynamic readonly attribute; also they were testing that the packaging qty != 0, but there's an upstream sql constraint that forbids that. There was a check that warned about impossible combinations of packages and UoM qtys. Now that everything is properly automated, that scenario is impossible. Thus, the check is removed. Summarizing, the module should be more usable and consistent now. @moduon MT-3694 --- stock_move_packaging_qty/models/stock_move.py | 101 +++++------------- .../tests/test_stock_move_packaging_qty.py | 1 + .../views/stock_move_tree_view.xml | 13 ++- .../views/stock_picking_form_view.xml | 15 ++- 4 files changed, 56 insertions(+), 74 deletions(-) diff --git a/stock_move_packaging_qty/models/stock_move.py b/stock_move_packaging_qty/models/stock_move.py index 9e316a018..e2490b2e9 100644 --- a/stock_move_packaging_qty/models/stock_move.py +++ b/stock_move_packaging_qty/models/stock_move.py @@ -1,8 +1,7 @@ # Copyright 2020 Camptocamp SA # Copyright 2021 ForgeFlow, S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) -from odoo import _, api, fields, models -from odoo.exceptions import UserError +from odoo import api, fields, models class StockPicking(models.Model): @@ -12,6 +11,7 @@ class StockPicking(models.Model): string="Package quantity", compute="_compute_product_packaging_qty", inverse="_inverse_product_packaging_qty", + help="Amount of packages demanded.", ) @api.depends( @@ -27,81 +27,38 @@ class StockPicking(models.Model): move.product_packaging_qty = 0 continue # Consider uom - if move.product_id.uom_id != move.product_uom: - product_qty = move.product_uom._compute_quantity( - move.product_uom_qty, move.product_id.uom_id - ) - else: - product_qty = move.product_uom_qty - move.product_packaging_qty = product_qty / move.product_packaging_id.qty - - def _prepare_product_packaging_qty_values(self): - return { - "product_uom_qty": self.product_packaging_id.qty - * self.product_packaging_qty, - "product_uom": self.product_packaging_id.product_uom_id.id, - } + move.product_packaging_qty = ( + move.product_uom_qty / move._get_single_package_uom_qty() + ) + @api.onchange("product_packaging_qty") def _inverse_product_packaging_qty(self): + """Store the quantity in the product's UoM. + + This inverse is also an onchange because otherwise changes are not + reflected live. + """ for move in self: - if move.product_packaging_qty and not move.product_packaging_id: - raise UserError( - _( - "You must define a package before setting a quantity " - "of said package." - ) - ) - if move.product_packaging_id and move.product_packaging_id.qty == 0: - raise UserError( - _("Please select a packaging with a quantity bigger than 0") - ) if move.product_packaging_id and move.product_packaging_qty: - move.write(move._prepare_product_packaging_qty_values()) + uom_factor = move._get_single_package_uom_qty() + move.product_uom_qty = move.product_packaging_qty * uom_factor @api.onchange("product_packaging_id") def _onchange_product_packaging(self): - if self.product_packaging_id: - self.update( - { - "product_packaging_qty": 1, - "product_uom_qty": self.product_packaging_id.qty, - "product_uom": self.product_id.uom_id, - } - ) - else: - self.update({"product_packaging_qty": 0}) - if self.product_packaging_id: - return self._check_package() + """Add a default qty if the packaging has an invalid value.""" + if not self.product_packaging_id: + self.product_packaging_qty = 0 + return + self.product_uom_qty = ( + self.product_packaging_id._check_qty(self.product_uom_qty, self.product_uom) + or self._get_single_package_uom_qty() + ) - @api.onchange("product_packaging_qty") - def _onchange_product_packaging_qty(self): - if self.product_packaging_qty and self.product_packaging_id: - self.update(self._prepare_product_packaging_qty_values()) - - @api.onchange("product_uom_qty", "product_uom") - def _onchange_product_uom_check_package(self): - return self._check_package() - - def _check_package(self): - default_uom = self.product_id.uom_id - pack = self.product_packaging_id - qty = self.product_qty - q = default_uom._compute_quantity(pack.qty, self.product_uom) - if qty and q and round(qty % q, 2): - newqty = qty - (qty % q) + q - return { - "warning": { - "title": _("Warning"), - "message": _( - "This product is packaged by %(old_qty).2f %(old_uom)s. " - "You should use %(new_qty).2f %(new_uom)s." - ) - % { - "old_qty": pack.qty, - "old_uom": default_uom.name, - "new_qty": newqty, - "new_uom": self.product_uom.name, - }, - }, - } - return {} + def _get_single_package_uom_qty(self): + """Return the quantity of a single package in the move's UoM.""" + self.ensure_one() + if not self.product_packaging_id: + return 0 + return self.product_packaging_id.product_uom_id._compute_quantity( + self.product_packaging_id.qty, self.product_uom + ) diff --git a/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py b/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py index 7db980e76..ca6ccff1e 100644 --- a/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py +++ b/stock_move_packaging_qty/tests/test_stock_move_packaging_qty.py @@ -10,6 +10,7 @@ class TestStockMovePackagingQty(TransactionCase): def setUpClass(cls): super().setUpClass() cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + cls.env.user.groups_id |= cls.env.ref("product.group_stock_packaging") cls.partner = cls.env.ref("base.res_partner_12") cls.product = cls.env.ref("product.product_product_9") cls.packaging = cls.env["product.packaging"].create( diff --git a/stock_move_packaging_qty/views/stock_move_tree_view.xml b/stock_move_packaging_qty/views/stock_move_tree_view.xml index 65567141d..fdee6314e 100644 --- a/stock_move_packaging_qty/views/stock_move_tree_view.xml +++ b/stock_move_packaging_qty/views/stock_move_tree_view.xml @@ -6,7 +6,18 @@ - + + diff --git a/stock_move_packaging_qty/views/stock_picking_form_view.xml b/stock_move_packaging_qty/views/stock_picking_form_view.xml index 76a07a16d..d6fd0b4c3 100644 --- a/stock_move_packaging_qty/views/stock_picking_form_view.xml +++ b/stock_move_packaging_qty/views/stock_picking_form_view.xml @@ -9,7 +9,20 @@ expr="//field[@name='move_ids_without_package']/tree/field[@name='product_packaging_id']" position="after" > - +