Skip to content

Commit e206919

Browse files
committed
[FIX] product_variant_route_mto: rely on stock_route_mto
1 parent a8ee499 commit e206919

File tree

4 files changed

+56
-38
lines changed

4 files changed

+56
-38
lines changed

product_variant_route_mto/__manifest__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright 2023 Camptocamp SA
2+
# Copyright 2025 Jacques-Etienne Baudoux (BCIM) <[email protected]>
23
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
34

45
{
@@ -9,10 +10,10 @@
910
"category": "Inventory",
1011
"website": "https://github.com/OCA/product-attribute",
1112
"author": "Camptocamp SA, Odoo Community Association (OCA)",
12-
"maintainers": ["mmequignon"],
13+
"maintainers": ["mmequignon", "jbaudoux"],
1314
"license": "AGPL-3",
1415
"installable": True,
1516
"auto_install": False,
16-
"depends": ["stock"],
17+
"depends": ["product_route_mto"],
1718
"data": ["views/product_product.xml"],
1819
}
Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright 2023 Camptocamp SA
2+
# Copyright 2025 Jacques-Etienne Baudoux (BCIM) <[email protected]>
23
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
34

45
from odoo import api, fields, models
@@ -16,7 +17,7 @@ class ProductProduct(models.Model):
1617

1718
is_mto = fields.Boolean(
1819
string="Variant is MTO",
19-
compute="_compute_is_mto",
20+
related="product_tmpl_id.is_mto",
2021
store=True,
2122
readonly=False,
2223
help=IS_MTO_HELP,
@@ -27,26 +28,28 @@ class ProductProduct(models.Model):
2728
compute="_compute_route_ids",
2829
domain="[('product_selectable', '=', True)]",
2930
store=False,
31+
search="_search_route_ids",
3032
)
3133

32-
def _compute_is_mto(self):
33-
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False)
34-
for product in self:
35-
if not mto_route:
36-
product.is_mto = False
37-
continue
38-
product.is_mto = mto_route in product.product_tmpl_id.route_ids
39-
4034
@api.depends("is_mto", "product_tmpl_id.route_ids")
4135
def _compute_route_ids(self):
42-
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False)
36+
mto_routes = self.env["stock.route"].search([("is_mto", "=", True)])
4337
for product in self:
44-
if mto_route and mto_route in product.product_tmpl_id.route_ids:
45-
if not product.is_mto:
46-
product.route_ids = product.product_tmpl_id.route_ids - mto_route
47-
continue
48-
else:
49-
if mto_route and product.is_mto:
50-
product.route_ids = product.product_tmpl_id.route_ids + mto_route
51-
continue
52-
product.route_ids = product.product_tmpl_id.route_ids
38+
routes = product.product_tmpl_id.route_ids
39+
if product.is_mto:
40+
routes += mto_routes
41+
product.route_ids = routes
42+
43+
def _search_route_ids(self, operator, value):
44+
mto_routes = self.env["stock.route"].search([("is_mto", "=", True)])
45+
if operator in ("=", "!=") and value in mto_routes:
46+
return [("is_mto", operator, True)]
47+
domain = []
48+
route_ids = value.copy()
49+
for idx, route_id in enumerate(route_ids):
50+
if route_id in mto_routes.ids:
51+
route_ids.pop(idx)
52+
domain = [("is_mto", "=" if operator == "in" else "!=", True)]
53+
if route_ids:
54+
domain += [("product_tmpl_id.route_ids", operator, route_ids)]
55+
return domain

product_variant_route_mto/models/product_template.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright 2023 Camptocamp SA
2+
# Copyright 2025 Jacques-Etienne Baudoux (BCIM) <[email protected]>
23
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
34

45
from odoo import api, models
@@ -7,33 +8,46 @@
78
class ProductTemplate(models.Model):
89
_inherit = "product.template"
910

10-
def write(self, values):
11-
if "route_ids" not in values:
11+
def dis_write(self, values):
12+
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False)
13+
14+
if "route_ids" not in values or not mto_route:
1215
return super().write(values)
16+
1317
# As _compute_is_mto cannot use api.depends (or it would reset MTO
1418
# route on variants as soon as there is a change on the template routes),
1519
# we need to check which template in self had MTO route activated
1620
# or deactivated to force the recomputation of is_mto on variants
17-
mto_route = self.env.ref("stock.route_warehouse0_mto")
18-
template_not_mto_before = self.filtered(lambda t: mto_route not in t.route_ids)
21+
22+
templates_not_mto_before = self.filtered(lambda t: mto_route not in t.route_ids)
23+
1924
res = super().write(values)
25+
2026
templates_mto_after = self.filtered(lambda t: mto_route in t.route_ids)
21-
templates_mto_added = template_not_mto_before & templates_mto_after
22-
templates_mto_removed = (self - template_not_mto_before) & (
23-
self - templates_mto_after
24-
)
27+
templates_mto_added = templates_not_mto_before & templates_mto_after
28+
templates_mto_removed = self - templates_mto_after - templates_not_mto_before
29+
2530
(
2631
templates_mto_added | templates_mto_removed
2732
).product_variant_ids._compute_is_mto()
33+
2834
return res
2935

3036
@api.onchange("route_ids")
3137
def onchange_route_ids(self):
32-
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False)
33-
if (
34-
mto_route not in self._origin.route_ids
35-
and mto_route in self.route_ids._origin
36-
):
38+
mto_routes = self.env["stock.route"].search([("is_mto", "=", True)])
39+
if not mto_routes:
40+
return
41+
42+
origin_routes = (
43+
self._origin.route_ids if self._origin else self.env["stock.route"]
44+
)
45+
current_routes = (
46+
self.route_ids._origin if self.route_ids else self.env["stock.route"]
47+
)
48+
49+
added_routes = current_routes - origin_routes
50+
if set(mto_routes.ids) & set(added_routes.ids):
3751
# Return warning activating MTO route
3852
return {
3953
"warning": {
@@ -44,10 +58,9 @@ def onchange_route_ids(self):
4458
),
4559
}
4660
}
47-
if (
48-
mto_route in self._origin.route_ids
49-
and mto_route not in self.route_ids._origin
50-
):
61+
62+
removed_routes = origin_routes - current_routes
63+
if set(mto_routes.ids) & set(removed_routes.ids):
5164
# Return warning deactivating MTO route
5265
return {
5366
"warning": {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
- Matthieu Méquignon \<<[email protected]>\>
22
- Akim Juillerat \<<[email protected]>\>
33
- Chau Le \<<[email protected]>\>
4+
- Jacques-Etienne Baudoux (BCIM) \<<[email protected]>\>

0 commit comments

Comments
 (0)