stock_packaging_calculator: return dict instead of tuple

Allows to ship more information with each element in the list.
This commit is contained in:
Simone Orsi
2020-06-08 10:18:02 +02:00
committed by Sébastien BEAU
parent d411a3ac09
commit 3de5642d78
2 changed files with 40 additions and 20 deletions

View File

@@ -1,9 +1,14 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from collections import namedtuple
from odoo import models
from odoo.tools import float_compare
# Unify records as we mix up w/ UoM
Packaging = namedtuple("Packaging", "id name qty")
class Product(models.Model):
_inherit = "product.product"
@@ -16,23 +21,29 @@ class Product(models.Model):
Limitation: fractional quantities are lost.
:prod_qty: total qty to satisfy.
:returns: list of tuple in the form [(qty_per_package, package_name)]
:with_subpackaging: include calculation of contained packagings.
eg: 1 pallet contains 4 big boxes and 6 little boxes.
:returns: list of dict in the form
[{id: 1, qty: qty_per_package, name: package_name}]
"""
packagings = [(x.qty, x.name) for x in self.packaging_ids]
packagings = [Packaging(x.id, x.name, x.qty) for x in self.packaging_ids]
# Add minimal unit
packagings.append((self.uom_id.factor, self.uom_id.name))
packagings.append(
Packaging(self.uom_id.id, self.uom_id.name, self.uom_id.factor)
)
return self._product_qty_by_packaging(
sorted(packagings, reverse=True), prod_qty
sorted(packagings, reverse=True, key=lambda x: x.qty), prod_qty,
)
def _product_qty_by_packaging(self, pkg_by_qty, qty):
"""Produce a list of tuple of packaging qty and packaging name."""
"""Produce a list of dictionaries of packaging info."""
# TODO: refactor to handle fractional quantities (eg: 0.5 Kg)
res = []
for pkg_qty, pkg in pkg_by_qty:
qty_per_pkg, qty = self._qty_by_pkg(pkg_qty, qty)
for pkg in pkg_by_qty:
qty_per_pkg, qty = self._qty_by_pkg(pkg.qty, qty)
if qty_per_pkg:
res.append((qty_per_pkg, pkg))
value = {"id": pkg.id, "qty": qty_per_pkg, "name": pkg.name}
res.append(value)
if not qty:
break
return res

View File

@@ -30,24 +30,33 @@ class TestCalc(SavepointCase):
def test_calc_1(self):
"""Test easy behavior 1."""
self.assertEqual(
self.product_a.product_qty_by_packaging(2655),
[(1, "Pallet"), (3, "Big Box"), (1, "Box"), (5, self.uom_unit.name)],
)
expected = [
{"id": self.pkg_pallet.id, "qty": 1, "name": self.pkg_pallet.name},
{"id": self.pkg_big_box.id, "qty": 3, "name": self.pkg_big_box.name},
{"id": self.pkg_box.id, "qty": 1, "name": self.pkg_box.name},
{"id": self.uom_unit.id, "qty": 5, "name": self.uom_unit.name},
]
self.assertEqual(self.product_a.product_qty_by_packaging(2655), expected)
def test_calc_2(self):
"""Test easy behavior 2."""
self.assertEqual(
self.product_a.product_qty_by_packaging(350), [(1, "Big Box"), (3, "Box")]
)
expected = [
{"id": self.pkg_big_box.id, "qty": 1, "name": self.pkg_big_box.name},
{"id": self.pkg_box.id, "qty": 3, "name": self.pkg_box.name},
]
self.assertEqual(self.product_a.product_qty_by_packaging(350), expected)
def test_calc_3(self):
"""Test easy behavior 3."""
self.assertEqual(
self.product_a.product_qty_by_packaging(80),
[(1, "Box"), (30, self.uom_unit.name)],
)
expected = [
{"id": self.pkg_box.id, "qty": 1, "name": self.pkg_box.name},
{"id": self.uom_unit.id, "qty": 30, "name": self.uom_unit.name},
]
self.assertEqual(self.product_a.product_qty_by_packaging(80), expected)
def test_calc_6(self):
"""Test fractional qty is lost."""
self.assertEqual(self.product_a.product_qty_by_packaging(50.5), [(1, "Box")])
expected = [
{"id": self.pkg_box.id, "qty": 1, "name": self.pkg_box.name},
]
self.assertEqual(self.product_a.product_qty_by_packaging(50.5), expected)