mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
stock_location_package_restriction: show violations
Show and search locations that does not respect the restriction.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.osv.expression import NEGATIVE_TERM_OPERATORS
|
||||
|
||||
NOPACKAGE = "nopackage"
|
||||
SINGLEPACKAGE = "singlepackage"
|
||||
@@ -39,6 +40,67 @@ class StockLocation(models.Model):
|
||||
(SINGLEPACKAGE, "Mandatory and unique"),
|
||||
]
|
||||
|
||||
has_package_restriction_violation = fields.Boolean(
|
||||
compute="_compute_has_package_restriction_violation",
|
||||
search="_search_has_package_restriction_violation",
|
||||
)
|
||||
|
||||
def _has_package_restriction_violation_query(self):
|
||||
self.flush()
|
||||
query = """
|
||||
SELECT stock_quant.location_id
|
||||
FROM stock_quant
|
||||
JOIN stock_location ON stock_location.id = stock_quant.location_id
|
||||
WHERE
|
||||
quantity != 0
|
||||
AND stock_location.package_restriction IS NOT NULL
|
||||
"""
|
||||
if self:
|
||||
query += "AND stock_quant.location_id in %s"
|
||||
query += f"""
|
||||
GROUP BY
|
||||
stock_quant.location_id, stock_location.package_restriction
|
||||
HAVING
|
||||
(
|
||||
stock_location.package_restriction = '{NOPACKAGE}'
|
||||
AND count(distinct(stock_quant.package_id)) > 0
|
||||
) OR (
|
||||
stock_location.package_restriction = '{SINGLEPACKAGE}'
|
||||
AND (
|
||||
count(distinct(stock_quant.package_id)) > 1
|
||||
OR count(*) FILTER (WHERE stock_quant.package_id IS NULL) > 0
|
||||
)
|
||||
) OR (
|
||||
stock_location.package_restriction = '{MULTIPACKAGE}'
|
||||
AND count(*) FILTER (WHERE stock_quant.package_id IS NULL) > 0
|
||||
)
|
||||
"""
|
||||
return query
|
||||
|
||||
@api.depends("package_restriction")
|
||||
def _compute_has_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()]
|
||||
for location in self:
|
||||
location.has_package_restriction_violation = location.id in error_ids
|
||||
|
||||
def _search_has_package_restriction_violation(self, operator, value):
|
||||
search_has_violation = (
|
||||
# has_restriction_violation != False
|
||||
(operator in NEGATIVE_TERM_OPERATORS and not value)
|
||||
# has_restriction_violation = True
|
||||
or (operator not in NEGATIVE_TERM_OPERATORS and value)
|
||||
)
|
||||
self.env.cr.execute(self._has_package_restriction_violation_query())
|
||||
error_ids = [r[0] for r in self.env.cr.fetchall()]
|
||||
if search_has_violation:
|
||||
op = "in"
|
||||
else:
|
||||
op = "not in"
|
||||
return [("id", op, error_ids)]
|
||||
|
||||
def _check_package_restriction(self, move_lines=None):
|
||||
"""Check if the location respect the package restrictions
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# Copyright 2024 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
|
||||
from odoo.addons.stock_location_package_restriction.models.stock_location import (
|
||||
MULTIPACKAGE,
|
||||
NOPACKAGE,
|
||||
SINGLEPACKAGE,
|
||||
)
|
||||
|
||||
from .common import TestLocationPackageRestrictionCommon
|
||||
|
||||
|
||||
class TestStockLocation(TestLocationPackageRestrictionCommon):
|
||||
def test_location_no_package_location_ok(self):
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
@@ -7,6 +7,14 @@
|
||||
<field name="model">stock.location</field>
|
||||
<field name="inherit_id" ref="stock.view_location_form" />
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="after">
|
||||
<field name="has_package_restriction_violation" invisible="1" />
|
||||
<div
|
||||
class="alert alert-danger"
|
||||
role="alert"
|
||||
attrs="{'invisible': [('has_package_restriction_violation','=',False)]}"
|
||||
>Package restriction is not respected</div>
|
||||
</div>
|
||||
<xpath expr="//group[last()]">
|
||||
<group name="restrictions" string="Restrictions">
|
||||
<field name="package_restriction" />
|
||||
@@ -14,15 +22,34 @@
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="stock_location_search_view">
|
||||
<field
|
||||
name="name"
|
||||
>stock.location.search (in stock_location_package_restriction)</field>
|
||||
<field name="model">stock.location</field>
|
||||
<field name="inherit_id" ref="stock.view_location_search" />
|
||||
<field name="arch" type="xml">
|
||||
<filter name="inactive" position="after">
|
||||
<filter
|
||||
string="With package restriction violation"
|
||||
name="has_package_restriction_violation"
|
||||
domain="[('has_package_restriction_violation','=',True)]"
|
||||
/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="stock_location_tree_view">
|
||||
<field
|
||||
name="name"
|
||||
>stock.location.tree (in stock_location_unique_product)</field>
|
||||
>stock.location.tree (in stock_location_package_restriction)</field>
|
||||
<field name="model">stock.location</field>
|
||||
<field name="inherit_id" ref="stock.view_location_tree2" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="company_id" position="before">
|
||||
<field name="package_restriction" />
|
||||
<field name="has_package_restriction_violation" />
|
||||
<field name="package_restriction" optional="hide" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Reference in New Issue
Block a user