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:
-
TODO
-
-- Fractional quantities (eg: 0.5 Kg) are lost when counting units
-- Maybe rely on packaging_uom
-
@@ -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