From f967343f383156e43788aaff9a5e37e4c2f403a7 Mon Sep 17 00:00:00 2001 From: Mateu Griful Date: Wed, 14 Jul 2021 13:58:02 +0200 Subject: [PATCH] [ADD] stock_packaging_qty --- .../odoo/addons/stock_move_packaging_qty | 1 + setup/stock_move_packaging_qty/setup.py | 6 + 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 +++ 12 files changed, 220 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 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/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, +) 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 + + + + + + + + + +