diff --git a/stock_packaging_calculator/README.rst b/stock_packaging_calculator/README.rst index c635d89ec..2c7b4c5d4 100644 --- a/stock_packaging_calculator/README.rst +++ b/stock_packaging_calculator/README.rst @@ -80,10 +80,7 @@ flag: Known issues / Roadmap ====================== -TODO -1. Fractional quantities (eg: 0.5 Kg) are lost when counting units -2. Maybe rely on packaging_uom Bug Tracker =========== @@ -108,6 +105,7 @@ Contributors - Simone Orsi - Christopher Ormaza +- Nguyen Minh Chien Maintainers ----------- diff --git a/stock_packaging_calculator/__manifest__.py b/stock_packaging_calculator/__manifest__.py index 929393373..95d66c9b3 100644 --- a/stock_packaging_calculator/__manifest__.py +++ b/stock_packaging_calculator/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Stock packaging calculator", "summary": "Compute product quantity to pick by packaging", - "version": "16.0.1.0.1", + "version": "17.0.1.0.0", "development_status": "Beta", "category": "Warehouse Management", "website": "https://github.com/OCA/stock-logistics-warehouse", diff --git a/stock_packaging_calculator/models/product.py b/stock_packaging_calculator/models/product.py index 5f9342424..fb35d7d99 100644 --- a/stock_packaging_calculator/models/product.py +++ b/stock_packaging_calculator/models/product.py @@ -6,7 +6,7 @@ import unicodedata from collections import namedtuple from odoo import api, models -from odoo.tools import float_compare +from odoo.tools import float_compare, float_is_zero, float_round from odoo.addons.base_sparse_field.models.fields import Serialized @@ -112,13 +112,21 @@ class Product(models.Model): def _product_qty_by_packaging(self, pkg_by_qty, qty, with_contained=False): """Produce a list of dictionaries of packaging info.""" - # TODO: refactor to handle fractional quantities (eg: 0.5 Kg) res = [] prepare_values = self.env.context.get( "_packaging_values_handler", self._prepare_qty_by_packaging_values ) for pkg in pkg_by_qty: qty_per_pkg, qty = self._qty_by_pkg(pkg.qty, qty) + # To handle fractional quantities (eg: 0.5 Kg) + if pkg.is_unit and not float_is_zero( + qty, precision_rounding=self.uom_id.rounding + ): + # `is_unit` package always be the last package by the sorting + # it has the same uom with the product, just sum the quantity + qty_per_pkg += float_round(qty, precision_rounding=self.uom_id.rounding) + qty = 0 + if qty_per_pkg: value = prepare_values(pkg, qty_per_pkg) if with_contained: @@ -191,7 +199,7 @@ class Product(models.Model): ) # Collect all strings representations as_string = [] - for record, info in zip(records, _qty_by_packaging): + for record, info in zip(records, _qty_by_packaging, strict=True): bit = _qty_by_packaging_as_str(record, info["qty"]) if bit: as_string.append(bit) diff --git a/stock_packaging_calculator/readme/CONTRIBUTORS.md b/stock_packaging_calculator/readme/CONTRIBUTORS.md index ed45df4f2..d17ea290f 100644 --- a/stock_packaging_calculator/readme/CONTRIBUTORS.md +++ b/stock_packaging_calculator/readme/CONTRIBUTORS.md @@ -1,2 +1,3 @@ - Simone Orsi \<\> - Christopher Ormaza \<\> +- Nguyen Minh Chien \<\> diff --git a/stock_packaging_calculator/readme/ROADMAP.md b/stock_packaging_calculator/readme/ROADMAP.md index c031f1086..e69de29bb 100644 --- a/stock_packaging_calculator/readme/ROADMAP.md +++ b/stock_packaging_calculator/readme/ROADMAP.md @@ -1,4 +0,0 @@ -TODO - -1. Fractional quantities (eg: 0.5 Kg) are lost when counting units -2. Maybe rely on packaging_uom diff --git a/stock_packaging_calculator/static/description/index.html b/stock_packaging_calculator/static/description/index.html index 8582a89c6..15484dca7 100644 --- a/stock_packaging_calculator/static/description/index.html +++ b/stock_packaging_calculator/static/description/index.html @@ -426,11 +426,6 @@ flag:

Known issues / Roadmap

-

TODO

-
    -
  1. Fractional quantities (eg: 0.5 Kg) are lost when counting units
  2. -
  3. Maybe rely on packaging_uom
  4. -

Bug Tracker

@@ -453,6 +448,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
diff --git a/stock_packaging_calculator/tests/__init__.py b/stock_packaging_calculator/tests/__init__.py index 441177cdc..05f92dad2 100644 --- a/stock_packaging_calculator/tests/__init__.py +++ b/stock_packaging_calculator/tests/__init__.py @@ -1,2 +1,3 @@ from . import test_packaging_calc from . import test_pkg_qty_str +from . import test_product_qty_by_packaging_mixin diff --git a/stock_packaging_calculator/tests/common.py b/stock_packaging_calculator/tests/common.py index 082084567..77390bd11 100644 --- a/stock_packaging_calculator/tests/common.py +++ b/stock_packaging_calculator/tests/common.py @@ -1,9 +1,9 @@ # Copyright 2020 Camptocamp SA # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl) -from odoo.tests import TransactionCase +from odoo.addons.base.tests.common import BaseCommon -class TestCommon(TransactionCase): +class TestCommon(BaseCommon): at_install = False post_install = True maxDiff = None @@ -11,7 +11,6 @@ class TestCommon(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) cls.uom_unit = cls.env.ref("uom.product_uom_unit") cls.product_a = cls.env["product.product"].create( { diff --git a/stock_packaging_calculator/tests/models.py b/stock_packaging_calculator/tests/models.py new file mode 100644 index 000000000..963f3b485 --- /dev/null +++ b/stock_packaging_calculator/tests/models.py @@ -0,0 +1,11 @@ +from odoo import fields, models + + +class TestProductQtyByPackagingMixin(models.Model): + _name = "test.product.qty_by_packaging.mixin" + _description = "Test ProductQtyByPackagingMixin" + _inherit = ["product.qty_by_packaging.mixin"] + _qty_by_pkg__qty_field_name = "quantity" + + product_id = fields.Many2one("product.product") + quantity = fields.Float() diff --git a/stock_packaging_calculator/tests/test_packaging_calc.py b/stock_packaging_calculator/tests/test_packaging_calc.py index 3d4bbfa85..6a0ec166b 100644 --- a/stock_packaging_calculator/tests/test_packaging_calc.py +++ b/stock_packaging_calculator/tests/test_packaging_calc.py @@ -55,6 +55,7 @@ class TestCalc(TestCommon): """Test fractional qty is lost.""" expected = [ make_pkg_values(self.pkg_box, qty=1), + make_pkg_values(self.uom_unit, qty=0.5), ] self.assertEqual(self.product_a.product_qty_by_packaging(50.5), expected) diff --git a/stock_packaging_calculator/tests/test_product_qty_by_packaging_mixin.py b/stock_packaging_calculator/tests/test_product_qty_by_packaging_mixin.py new file mode 100644 index 000000000..909f9b8fb --- /dev/null +++ b/stock_packaging_calculator/tests/test_product_qty_by_packaging_mixin.py @@ -0,0 +1,56 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +from odoo_test_helper import FakeModelLoader + +from .common import TestCommon + + +class TestPQPackagingMixin(TestCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + # Load a test model using odoo_test_helper + cls.loader = FakeModelLoader(cls.env, cls.__module__) + cls.loader.backup_registry() + from .models import TestProductQtyByPackagingMixin + + cls.loader.update_registry((TestProductQtyByPackagingMixin,)) + cls.model = cls.env[TestProductQtyByPackagingMixin._name] + + @classmethod + def tearDownClass(cls): + cls.loader.restore_registry() + return super().tearDownClass() + + def test_1_quantity_packaging(self): + record = self.model.create({"product_id": self.product_a.id, "quantity": 10}) + self.assertEqual(record.product_qty_by_packaging_display, "10 Units") + self.assertEqual( + record.with_context( + qty_by_pkg_only_packaging=True + ).product_qty_by_packaging_display, + "", + ) + record.quantity = 100 + self.assertEqual(record.product_qty_by_packaging_display, "2 Box") + record.quantity = 250 + self.assertEqual(record.product_qty_by_packaging_display, "1 Big Box,\xa01 Box") + record.quantity = 255 + self.assertEqual( + record.product_qty_by_packaging_display, + "1 Big Box,\xa01 Box,\xa05 Units", + ) + # only_packaging has no impact if we get not only units + self.assertEqual( + record.with_context( + qty_by_pkg_only_packaging=True + ).product_qty_by_packaging_display, + "1 Big Box,\xa01 Box,\xa05 Units", + ) + + def test_2_fractional_quantity(self): + record = self.model.create( + {"product_id": self.product_a.id, "quantity": 100.45} + ) + self.assertEqual( + record.product_qty_by_packaging_display, "2 Box,\xa00.45 Units" + ) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000..66bc2cbae --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +odoo_test_helper