Skip to content

Commit 5e0cc07

Browse files
committed
[MIG] stock_product_variant_mto: Migration to 18.0
1 parent bee6c75 commit 5e0cc07

File tree

10 files changed

+116
-63
lines changed

10 files changed

+116
-63
lines changed

stock_product_variant_mto/README.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Stock Product Variant MTO
3131
This module allows to define if a product variant can use the Make To
3232
Order route without any dependency on its template routes settings.
3333

34+
The routes are moved from product template to product product.
35+
3436
.. IMPORTANT::
3537
This is an alpha version, the data model and design can change at any time without warning.
3638
Only for development or testing purpose, do not use in production.
@@ -64,6 +66,15 @@ Contributors
6466

6567
- Matthieu Méquignon <[email protected]>
6668
- Akim Juillerat <[email protected]>
69+
- Chau Le <[email protected]>
70+
71+
Other credits
72+
-------------
73+
74+
The development and migration of this module has been financially
75+
supported by:
76+
77+
- Camptocamp
6778

6879
Maintainers
6980
-----------

stock_product_variant_mto/__manifest__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{
55
"name": "Stock Product Variant MTO",
66
"summary": "Allow to individually set variants as MTO",
7-
"version": "14.0.1.0.0",
7+
"version": "18.0.1.0.0",
88
"development_status": "Alpha",
99
"category": "Inventory",
1010
"website": "https://github.com/OCA/stock-logistics-workflow",

stock_product_variant_mto/models/product_product.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,31 @@ class ProductProduct(models.Model):
2323
)
2424

2525
route_ids = fields.Many2many(
26-
"stock.location.route",
26+
"stock.route",
2727
compute="_compute_route_ids",
2828
domain="[('product_selectable', '=', True)]",
29-
store=False,
29+
store=True,
3030
)
3131

3232
def _compute_is_mto(self):
3333
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False)
34+
if not mto_route:
35+
self.update({"is_mto": False})
36+
return
37+
3438
for product in self:
35-
if not mto_route:
36-
product.is_mto = False
37-
continue
3839
product.is_mto = mto_route in product.product_tmpl_id.route_ids
3940

4041
@api.depends("is_mto", "product_tmpl_id.route_ids")
4142
def _compute_route_ids(self):
4243
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False)
4344
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
45+
template_routes = product.product_tmpl_id.route_ids
46+
47+
if mto_route:
48+
if product.is_mto and mto_route not in template_routes:
49+
template_routes += mto_route
50+
elif not product.is_mto and mto_route in template_routes:
51+
template_routes -= mto_route
52+
53+
product.route_ids = template_routes
Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,70 @@
11
# Copyright 2023 Camptocamp SA
22
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
33

4-
from odoo import _, api, models
4+
from odoo import api, models
55

66

77
class ProductTemplate(models.Model):
88
_inherit = "product.template"
99

1010
def write(self, values):
11-
if "route_ids" not in values:
11+
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False)
12+
13+
if "route_ids" not in values or not mto_route:
1214
return super().write(values)
15+
1316
# As _compute_is_mto cannot use api.depends (or it would reset MTO
1417
# route on variants as soon as there is a change on the template routes),
1518
# we need to check which template in self had MTO route activated
1619
# 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)
20+
21+
templates_not_mto_before = self.filtered(lambda t: mto_route not in t.route_ids)
22+
1923
res = super().write(values)
24+
2025
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-
)
26+
templates_mto_added = templates_not_mto_before & templates_mto_after
27+
templates_mto_removed = self - templates_mto_after - templates_not_mto_before
28+
2529
(
2630
templates_mto_added | templates_mto_removed
2731
).product_variant_ids._compute_is_mto()
32+
2833
return res
2934

3035
@api.onchange("route_ids")
3136
def onchange_route_ids(self):
3237
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+
if not mto_route:
39+
return
40+
41+
origin_routes = (
42+
self._origin.route_ids if self._origin else self.env["stock.route"]
43+
)
44+
current_routes = (
45+
self.route_ids._origin if self.route_ids else self.env["stock.route"]
46+
)
47+
48+
if mto_route not in origin_routes and mto_route in current_routes:
3749
# Return warning activating MTO route
3850
return {
3951
"warning": {
40-
"title": _("Warning"),
41-
"message": _(
42-
"Activating MTO route will reset `Variant is MTO` setting on the variants."
52+
"title": self.env._("Warning"),
53+
"message": self.env._(
54+
"Activating MTO route will reset `Variant is MTO` "
55+
"setting on the variants."
4356
),
4457
}
4558
}
46-
if (
47-
mto_route in self._origin.route_ids
48-
and mto_route not in self.route_ids._origin
49-
):
59+
60+
if mto_route in origin_routes and mto_route not in current_routes:
5061
# Return warning deactivating MTO route
5162
return {
5263
"warning": {
53-
"title": _("Warning"),
54-
"message": _(
55-
"Deactivating MTO route will reset `Variant is MTO` setting on the variants."
64+
"title": self.env._("Warning"),
65+
"message": self.env._(
66+
"Deactivating MTO route will reset `Variant is MTO` "
67+
"setting on the variants."
5668
),
5769
}
5870
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
- Matthieu Méquignon \<<[email protected]>\>
22
- Akim Juillerat \<<[email protected]>\>
3+
- Chau Le \<<[email protected]>\>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The development and migration of this module has been financially supported by:
2+
3+
- Camptocamp
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
This module allows to define if a product variant can use the Make To
22
Order route without any dependency on its template routes settings.
3+
4+
The routes are moved from product template to product product.

stock_product_variant_mto/static/description/index.html

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ <h1 class="title">Stock Product Variant MTO</h1>
372372
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-workflow/tree/18.0/stock_product_variant_mto"><img alt="OCA/stock-logistics-workflow" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-workflow-18-0/stock-logistics-workflow-18-0-stock_product_variant_mto"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-workflow&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
373373
<p>This module allows to define if a product variant can use the Make To
374374
Order route without any dependency on its template routes settings.</p>
375+
<p>The routes are moved from product template to product product.</p>
375376
<div class="admonition important">
376377
<p class="first admonition-title">Important</p>
377378
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
@@ -385,7 +386,8 @@ <h1 class="title">Stock Product Variant MTO</h1>
385386
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
386387
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
387388
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
388-
<li><a class="reference internal" href="#maintainers" id="toc-entry-5">Maintainers</a></li>
389+
<li><a class="reference internal" href="#other-credits" id="toc-entry-5">Other credits</a></li>
390+
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
389391
</ul>
390392
</li>
391393
</ul>
@@ -411,10 +413,19 @@ <h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
411413
<ul class="simple">
412414
<li>Matthieu Méquignon &lt;<a class="reference external" href="mailto:matthieu.mequignon&#64;camptocamp.com">matthieu.mequignon&#64;camptocamp.com</a>&gt;</li>
413415
<li>Akim Juillerat &lt;<a class="reference external" href="mailto:akim.juillerat&#64;camptocamp.com">akim.juillerat&#64;camptocamp.com</a>&gt;</li>
416+
<li>Chau Le &lt;<a class="reference external" href="mailto:chaulb&#64;trobz.com">chaulb&#64;trobz.com</a>&gt;</li>
417+
</ul>
418+
</div>
419+
<div class="section" id="other-credits">
420+
<h2><a class="toc-backref" href="#toc-entry-5">Other credits</a></h2>
421+
<p>The development and migration of this module has been financially
422+
supported by:</p>
423+
<ul class="simple">
424+
<li>Camptocamp</li>
414425
</ul>
415426
</div>
416427
<div class="section" id="maintainers">
417-
<h2><a class="toc-backref" href="#toc-entry-5">Maintainers</a></h2>
428+
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
418429
<p>This module is maintained by the OCA.</p>
419430
<a class="reference external image-reference" href="https://odoo-community.org">
420431
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />

stock_product_variant_mto/tests/common.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
# Copyright 2023 Camptocamp SA
22
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
33

4-
from odoo.tests.common import Form, SavepointCase
4+
from odoo.tests import Form, tagged
55

6+
from odoo.addons.base.tests.common import BaseCommon
67

7-
class TestMTOVariantCommon(SavepointCase):
8-
at_install = False
9-
post_install = True
108

9+
@tagged("post_install", "-at_install")
10+
class TestMTOVariantCommon(BaseCommon):
1111
@classmethod
1212
def setUpClass(cls):
1313
super().setUpClass()
14-
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
1514
cls.setUpClassProduct()
1615

1716
@classmethod
@@ -79,13 +78,13 @@ def toggle_is_mto(self, records):
7978
record.is_mto = not record.is_mto
8079

8180
def assertVariantsMTO(self, records):
82-
records.invalidate_cache(["is_mto"])
81+
records.invalidate_recordset(["is_mto"])
8382
self.assertTrue(all([record.is_mto for record in records]))
8483
for rec in records:
8584
self.assertIn(self.mto_route, rec.route_ids)
8685

8786
def assertVariantsNotMTO(self, records):
88-
records.invalidate_cache(["is_mto"])
87+
records.invalidate_recordset(["is_mto"])
8988
self.assertFalse(any([record.is_mto for record in records]))
9089
for rec in records:
9190
self.assertNotIn(self.mto_route, rec.route_ids)

stock_product_variant_mto/tests/test_mto_variant.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
from .common import TestMTOVariantCommon
66

7+
onchange_logger = "odoo.tests.form.onchange"
8+
9+
_logger = logging.getLogger(onchange_logger)
10+
711

812
class TestMTOVariant(TestMTOVariantCommon):
913
def test_variants_mto(self):
@@ -24,14 +28,16 @@ def test_variants_mto(self):
2428
self.assertVariantsMTO(black_pen | blue_pen)
2529
self.assertVariantsNotMTO(red_pen | green_pen)
2630
# Now enable the mto route for the template, all variants get is_mto = True
27-
self.add_route(pen_template, self.mto_route)
31+
with self.assertLogs(onchange_logger, level="WARNING"):
32+
self.add_route(pen_template, self.mto_route)
2833
self.assertVariantsMTO(pens)
2934
# Disable mto route for black_pen
3035
self.toggle_is_mto(black_pen)
3136
self.assertVariantsNotMTO(black_pen)
3237
self.assertVariantsMTO(blue_pen | green_pen | red_pen)
3338
# Disable mto route on the template, reset is_mto on variants
34-
self.remove_route(pen_template, self.mto_route)
39+
with self.assertLogs(onchange_logger, level="WARNING"):
40+
self.remove_route(pen_template, self.mto_route)
3541
self.assertVariantsNotMTO(pens)
3642

3743
def test_template_routes_updated(self):
@@ -44,7 +50,8 @@ def test_template_routes_updated(self):
4450
black_pen = self.black_pen
4551
self.assertVariantsNotMTO(pens)
4652
# If template is set to MTO, all variants are updated
47-
self.add_route(pen_template, self.mto_route)
53+
with self.assertLogs(onchange_logger, level="WARNING"):
54+
self.add_route(pen_template, self.mto_route)
4855
self.assertVariantsMTO(pens)
4956
# Now toggle a few variants to is_mto == False
5057
self.toggle_is_mto(black_pen | blue_pen)
@@ -65,43 +72,49 @@ def test_template_warnings(self):
6572
red_pen = self.red_pen
6673
green_pen = self.green_pen
6774
black_pen = self.black_pen
68-
onchange_logger = logging.getLogger("odoo.tests.common.onchange")
6975
self.assertVariantsNotMTO(pens)
76+
7077
# enable mto route for black pen
7178
self.toggle_is_mto(black_pen)
7279
self.assertVariantsMTO(black_pen)
80+
7381
# Enable mto route on the template, raise warning as is_mto is reset on variants
74-
with self.assertLogs(onchange_logger) as log:
82+
with self.assertLogs(onchange_logger, level="WARNING") as log_catcher:
7583
self.add_route(pen_template, self.mto_route)
76-
self.assertIn("WARNING", log.output[0])
77-
self.assertIn("Activating MTO route will reset", log.output[0])
84+
self.assertIn("WARNING", log_catcher.output[0])
85+
self.assertIn("Activating MTO route will reset", log_catcher.output[0])
7886
self.assertVariantsMTO(pens)
87+
7988
# Disable mto route for black pen
8089
self.toggle_is_mto(black_pen)
8190
self.assertVariantsNotMTO(black_pen)
8291
self.assertVariantsMTO(blue_pen | green_pen | red_pen)
92+
8393
# Enable unrelated route does not raise warning nor reset
8494
random_route = self.mto_route.create({"name": "loutourout de la vit"})
85-
with self.assertLogs(onchange_logger) as log:
95+
with self.assertLogs(onchange_logger) as log_catcher:
8696
self.add_route(pen_template, random_route)
87-
onchange_logger.info("No warning raised")
88-
self.assertNotIn("WARNING", log.output[0])
97+
_logger.info("No warning raised")
98+
self.assertNotIn("WARNING", log_catcher.output[0])
8999
self.assertVariantsNotMTO(black_pen)
90100
self.assertVariantsMTO(blue_pen | green_pen | red_pen)
91-
# Disable mto route on the template, raise warning as is_mto is reset on variants
92-
with self.assertLogs(onchange_logger) as log:
101+
102+
# Disable mto route on the template,
103+
# raise warning as is_mto is reset on variants
104+
with self.assertLogs(onchange_logger) as log_catcher:
93105
self.remove_route(pen_template, self.mto_route)
94-
self.assertIn("WARNING", log.output[0])
95-
self.assertIn("Deactivating MTO route will reset", log.output[0])
106+
self.assertIn("WARNING", log_catcher.output[0])
107+
self.assertIn("Deactivating MTO route will reset", log_catcher.output[0])
96108
self.assertVariantsNotMTO(pens)
109+
97110
# Enable mto route for black pen
98111
self.toggle_is_mto(black_pen)
99112
self.assertVariantsMTO(black_pen)
100113
self.assertVariantsNotMTO(blue_pen | green_pen | red_pen)
114+
101115
# Disable unrelated route does not raise warning nor reset
102-
with self.assertLogs(onchange_logger) as log:
116+
with self.assertLogs(onchange_logger) as log_catcher:
103117
self.remove_route(pen_template, random_route)
104-
onchange_logger.info("No warning raised")
105-
self.assertNotIn("WARNING", log.output[0])
118+
_logger.info("No warning raised")
106119
self.assertVariantsMTO(black_pen)
107120
self.assertVariantsNotMTO(blue_pen | green_pen | red_pen)

0 commit comments

Comments
 (0)