diff --git a/stock_location_package_restriction/models/stock_location.py b/stock_location_package_restriction/models/stock_location.py
index 862dd69c9..cb312cce5 100644
--- a/stock_location_package_restriction/models/stock_location.py
+++ b/stock_location_package_restriction/models/stock_location.py
@@ -41,14 +41,20 @@ class StockLocation(models.Model):
]
has_package_restriction_violation = fields.Boolean(
- compute="_compute_has_package_restriction_violation",
+ compute="_compute_package_restriction_violation",
search="_search_has_package_restriction_violation",
)
+ package_restriction_violation_message = fields.Char(
+ compute="_compute_package_restriction_violation",
+ )
+
def _has_package_restriction_violation_query(self):
self.flush()
query = """
- SELECT stock_quant.location_id
+ SELECT stock_quant.location_id,
+ (count(distinct(stock_quant.package_id)) > 1)::bool as has_multiple_packages,
+ (count(*) FILTER (WHERE stock_quant.package_id IS NULL) > 0)::bool as has_no_package
FROM stock_quant
JOIN stock_location ON stock_location.id = stock_quant.location_id
WHERE
@@ -78,13 +84,50 @@ class StockLocation(models.Model):
return query
@api.depends("package_restriction")
- def _compute_has_package_restriction_violation(self):
+ def _compute_package_restriction_violation(self):
self.env.cr.execute(
self._has_package_restriction_violation_query(), (tuple(self.ids),)
)
- error_ids = [r[0] for r in self.env.cr.fetchall()]
+ errors = {r[0]: r[1:] for r in self.env.cr.fetchall()}
for location in self:
- location.has_package_restriction_violation = location.id in error_ids
+ error = errors.get(location.id)
+ if not error:
+ location.has_package_restriction_violation = False
+ location.package_restriction_violation_message = False
+ continue
+ location.has_package_restriction_violation = True
+ if location.package_restriction == NOPACKAGE:
+ location.package_restriction_violation_message = _(
+ "This location should only contain items without package "
+ "but it contains the package(s): {packages}"
+ ).format(
+ packages=", ".join(location.quant_ids.package_id.mapped("name"))
+ )
+ else:
+ messages = []
+ has_multiple_package, has_no_package = error
+ if has_multiple_package:
+ messages.append(
+ _(
+ "This location should only contain a single package "
+ "but it contains the package(s): {packages}"
+ ).format(
+ packages=", ".join(
+ location.quant_ids.package_id.mapped("name")
+ )
+ )
+ )
+ if has_no_package:
+ products = location.quant_ids.filtered(
+ lambda q: not q.package_id
+ ).product_id
+ messages.append(
+ _(
+ "This location should only contain items in a package "
+ "but it contains the items of product(s): {products}"
+ ).format(products=", ".join(products.mapped("name")))
+ )
+ location.package_restriction_violation_message = "\n".join(messages)
def _search_has_package_restriction_violation(self, operator, value):
search_has_violation = (
diff --git a/stock_location_package_restriction/tests/test_stock_location.py b/stock_location_package_restriction/tests/test_stock_location.py
index 9c1772c26..e12196166 100644
--- a/stock_location_package_restriction/tests/test_stock_location.py
+++ b/stock_location_package_restriction/tests/test_stock_location.py
@@ -16,35 +16,42 @@ class TestStockLocation(TestLocationPackageRestrictionCommon):
self._change_product_qty(self.product_1, self.location_1, False, 50)
self.location_1.package_restriction = NOPACKAGE
self.assertFalse(self.location_1.has_package_restriction_violation)
+ self.assertFalse(self.location_1.package_restriction_violation_message)
def test_location_no_package_location_ko(self):
self._change_product_qty(self.product_1, self.location_1, self.pack_1, 50)
self.location_1.package_restriction = NOPACKAGE
self.assertTrue(self.location_1.has_package_restriction_violation)
+ self.assertTrue(self.location_1.package_restriction_violation_message)
def test_location_multi_package_location_ok(self):
self._change_product_qty(self.product_1, self.location_1, self.pack_1, 50)
self._change_product_qty(self.product_1, self.location_1, self.pack_2, 50)
self.location_1.package_restriction = MULTIPACKAGE
self.assertFalse(self.location_1.has_package_restriction_violation)
+ self.assertFalse(self.location_1.package_restriction_violation_message)
def test_location_multi_package_location_ko(self):
self._change_product_qty(self.product_1, self.location_1, False, 50)
self.location_1.package_restriction = MULTIPACKAGE
self.assertTrue(self.location_1.has_package_restriction_violation)
+ self.assertTrue(self.location_1.package_restriction_violation_message)
def test_location_single_package_location_ok(self):
self._change_product_qty(self.product_1, self.location_1, self.pack_1, 50)
self.location_1.package_restriction = SINGLEPACKAGE
self.assertFalse(self.location_1.has_package_restriction_violation)
+ self.assertFalse(self.location_1.package_restriction_violation_message)
def test_location_single_package_location_ko_multi(self):
self._change_product_qty(self.product_1, self.location_1, self.pack_1, 50)
self._change_product_qty(self.product_1, self.location_1, self.pack_2, 50)
self.location_1.package_restriction = SINGLEPACKAGE
self.assertTrue(self.location_1.has_package_restriction_violation)
+ self.assertTrue(self.location_1.package_restriction_violation_message)
def test_location_single_package_location_ko_no(self):
self._change_product_qty(self.product_1, self.location_1, False, 50)
self.location_1.package_restriction = SINGLEPACKAGE
self.assertTrue(self.location_1.has_package_restriction_violation)
+ self.assertTrue(self.location_1.package_restriction_violation_message)
diff --git a/stock_location_package_restriction/views/stock_location.xml b/stock_location_package_restriction/views/stock_location.xml
index 2ec7e232e..7ffc38340 100644
--- a/stock_location_package_restriction/views/stock_location.xml
+++ b/stock_location_package_restriction/views/stock_location.xml
@@ -13,7 +13,7 @@
class="alert alert-danger"
role="alert"
attrs="{'invisible': [('has_package_restriction_violation','=',False)]}"
- >Package restriction is not respected
+ >