diff --git a/sale_stock_mto_as_mts_orderpoint/models/product_product.py b/sale_stock_mto_as_mts_orderpoint/models/product_product.py
index 77025fa524a2..fb3ade8240eb 100644
--- a/sale_stock_mto_as_mts_orderpoint/models/product_product.py
+++ b/sale_stock_mto_as_mts_orderpoint/models/product_product.py
@@ -3,6 +3,7 @@
from odoo import models
+
class ProductProduct(models.Model):
_inherit = "product.product"
diff --git a/sale_stock_mto_as_mts_orderpoint/models/stock_warehouse.py b/sale_stock_mto_as_mts_orderpoint/models/stock_warehouse.py
index 936e883af639..b16056d6d3a2 100644
--- a/sale_stock_mto_as_mts_orderpoint/models/stock_warehouse.py
+++ b/sale_stock_mto_as_mts_orderpoint/models/stock_warehouse.py
@@ -7,24 +7,29 @@ class StockWarehouse(models.Model):
_inherit = "stock.warehouse"
- mto_as_mts = fields.Boolean(inverse="_inverse_mto_as_mts")
+ mto_as_mts = fields.Boolean()
def _get_locations_for_mto_orderpoints(self):
return self.mapped("lot_stock_id")
- def _inverse_mto_as_mts(self):
- mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False)
- if not mto_route:
- return
+ def write(self, vals):
+ res = super().write(vals)
+ if "mto_as_mts" in vals and vals["mto_as_mts"] == False:
+ self._archive_orderpoints_on_mts_mto_removal()
+ return res
+
+ def _archive_orderpoints_on_mts_mto_removal(self):
for warehouse in self:
- if warehouse.mto_as_mts:
- wh_mto_rules = self.env["stock.rule"].search(
- [
- ("route_id", "=", mto_route.id),
- "|",
- ("warehouse_id", "=", warehouse.id),
- ("picking_type_id.warehouse_id", "=", warehouse.id),
- ]
- )
- if wh_mto_rules:
- wh_mto_rules.active = False
+ domain = warehouse._get_orderpoints_to_archive_domain()
+ orderpoints = self.env["stock.warehouse.orderpoint"].search(domain)
+ if orderpoints:
+ orderpoints.write({"active": False})
+
+ def _get_orderpoints_to_archive_domain(self):
+ self.ensure_one()
+ locations = self._get_locations_for_mto_orderpoints()
+ return [
+ ("product_min_qty", "=", 0.0),
+ ("product_max_qty", "=", 0.0),
+ ("location_id", "in", locations.ids),
+ ]
diff --git a/sale_stock_mto_as_mts_orderpoint_product_variant/models/product_product.py b/sale_stock_mto_as_mts_orderpoint_product_variant/models/product_product.py
index 6b6393c1bada..cf5f11f4ac96 100644
--- a/sale_stock_mto_as_mts_orderpoint_product_variant/models/product_product.py
+++ b/sale_stock_mto_as_mts_orderpoint_product_variant/models/product_product.py
@@ -1,7 +1,9 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-from odoo import api, models
+from odoo import models
+from odoo.osv.expression import AND
+
class ProductProduct(models.Model):
_inherit = "product.product"
@@ -10,32 +12,28 @@ def _variant_is_mto(self):
self.ensure_one()
return self.is_mto
- def _inverse_is_mto(self):
- res = super()._inverse_is_mto()
- self._archive_orderpoints_on_mto_removal()
- return res
-
- @api.depends("product_tmpl_id.route_ids")
- def _compute_is_mto(self):
- # Archive orderpoints when variant becomes not mto
- res = super()._compute_is_mto()
- self._archive_orderpoints_on_mto_removal()
+ def write(self, vals):
+ res = super().write(vals)
+ if "is_mto" in vals and vals["is_mto"] == False:
+ self._archive_orderpoints_on_mto_removal()
return res
- def _get_orderpoints_to_archive_domain(self):
+ def _get_orderpoints_to_archive_domain(self, warehouse):
# Orderpoints to archive are those where
- warehouses = self.env["stock.warehouse"].search([])
- locations = warehouses._get_locations_for_mto_orderpoints()
- return [
- ("product_id", "in", self.ids),
- ("product_min_qty", "=", 0.0),
- ("product_max_qty", "=", 0.0),
- ("location_id", "in", locations.ids),
- ("product_id.is_mto", "=", False),
- ]
+ domain = warehouse._get_orderpoints_to_archive_domain()
+ if self:
+ domain = AND(
+ [
+ domain,
+ [("product_id", "in", self.ids)],
+ ]
+ )
+ return domain
def _archive_orderpoints_on_mto_removal(self):
- domain = self._get_orderpoints_to_archive_domain()
- ops = self.env["stock.warehouse.orderpoint"].search(domain)
- if ops:
- ops.write({"active": False})
+ warehouses = self.env["stock.warehouse"].search([])
+ for wh in warehouses:
+ domain = self._get_orderpoints_to_archive_domain(wh)
+ ops = self.env["stock.warehouse.orderpoint"].search(domain)
+ if ops:
+ ops.write({"active": False})
diff --git a/sale_stock_mto_as_mts_orderpoint_product_variant/tests/test_mto_as_mts_variant.py b/sale_stock_mto_as_mts_orderpoint_product_variant/tests/test_mto_as_mts_variant.py
index 1dc1eed9d9be..a70c8087e0be 100644
--- a/sale_stock_mto_as_mts_orderpoint_product_variant/tests/test_mto_as_mts_variant.py
+++ b/sale_stock_mto_as_mts_orderpoint_product_variant/tests/test_mto_as_mts_variant.py
@@ -2,11 +2,11 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo.tests import Form
+
from odoo.addons.stock_product_variant_mto.tests.common import TestMTOVariantCommon
class TestMtoAsMtsVariant(TestMTOVariantCommon):
-
@classmethod
def setUpClass(cls):
super().setUpClass()
@@ -25,6 +25,7 @@ def setUpClass(cls):
]
)
cls.warehouse = cls.env.ref("stock.warehouse0")
+ cls.warehouse.mto_as_mts = True
@classmethod
def setUpClassProduct(cls):
@@ -49,12 +50,29 @@ def _get_orderpoint_for_products(self, products, archived=False):
orderpoint = self.env["stock.warehouse.orderpoint"]
if archived:
orderpoint = orderpoint.with_context(active_test=False)
- return orderpoint.search(
- [("product_id", "in", products.ids)]
- )
+ return orderpoint.search([("product_id", "in", products.ids)])
+
+ def test_mto_as_mts_orderpoint_warehouse_archive(self):
+ black_pen = self.black_pen
+ order = self._create_sale_order(black_pen)
+ order.action_confirm()
+ orderpoint = self._get_orderpoint_for_products(black_pen)
+ self.assertTrue(orderpoint)
+ self.warehouse.mto_as_mts = False
+ orderpoint = self._get_orderpoint_for_products(black_pen)
+ self.assertFalse(orderpoint)
+
+ def test_mto_as_mts_orderpoint_product_archive(self):
+ black_pen = self.black_pen
+ order = self._create_sale_order(black_pen)
+ order.action_confirm()
+ orderpoint = self._get_orderpoint_for_products(black_pen)
+ self.assertTrue(orderpoint)
+ self.toggle_is_mto(black_pen)
+ orderpoint = self._get_orderpoint_for_products(black_pen)
+ self.assertFalse(orderpoint)
def test_mto_as_mts_orderpoint(self):
- template_pen = self.template_pen
black_pen = self.black_pen
blue_pen = self.blue_pen
red_pen = self.red_pen
@@ -62,8 +80,11 @@ def test_mto_as_mts_orderpoint(self):
order = self._create_sale_order(black_pen)
orderpoint = self._get_orderpoint_for_products(black_pen)
self.assertFalse(orderpoint)
+ self.assertIn(self.mto_route, black_pen.route_ids)
+ self.assertTrue(black_pen.is_mto)
order.action_confirm()
orderpoint = self._get_orderpoint_for_products(black_pen)
+ self.assertTrue(orderpoint)
self.assertEqual(
orderpoint.location_id,
self.warehouse._get_locations_for_mto_orderpoints(),
@@ -82,17 +103,24 @@ def test_mto_as_mts_orderpoint(self):
self.assertFalse(self._get_orderpoint_for_products(black_pen))
self.assertTrue(self._get_orderpoint_for_products(black_pen, archived=True))
other_pens = red_pen | green_pen | blue_pen
- self.assertEqual(
- len(self._get_orderpoint_for_products(other_pens)), 3
- )
+ self.assertEqual(len(self._get_orderpoint_for_products(other_pens)), 3)
def test_mtp_as_mts_orderpoint_product_no_mto(self):
+ self.assertIn(self.buy_route, self.template_pen.route_ids)
template_pen = self.template_pen
black_pen = self.black_pen
variants_pen = self.variants_pen
+ self.assertIn(self.buy_route, black_pen.route_ids)
# set everything to not mto
- template_pen.route_ids = False
+ template_pen.write({"route_ids": [(3, self.mto_route.id, 0)]})
+ self.assertIn(self.buy_route, black_pen.route_ids)
+ self.assertNotIn(self.mto_route, black_pen.route_ids)
+ self.toggle_is_mto(variants_pen)
+ self.assertIn(self.mto_route, black_pen.route_ids)
+ self.assertIn(self.buy_route, black_pen.route_ids)
self.toggle_is_mto(variants_pen)
+ self.assertNotIn(self.mto_route, black_pen.route_ids)
+ self.assertIn(self.buy_route, black_pen.route_ids)
# then check that no orderpoint is created
order = self._create_sale_order(black_pen)
orderpoint = self.env["stock.warehouse.orderpoint"].search(
diff --git a/stock_product_variant_mto/__manifest__.py b/stock_product_variant_mto/__manifest__.py
index d647fa79f93b..6bb7ae957038 100644
--- a/stock_product_variant_mto/__manifest__.py
+++ b/stock_product_variant_mto/__manifest__.py
@@ -7,7 +7,7 @@
"version": "14.0.1.0.0",
"development_status": "Alpha",
"category": "Inventory",
- "website": "https://github.com/OCA/stock-workflow",
+ "website": "https://github.com/OCA/stock-logistics-workflow",
"author": "Camptocamp SA, Odoo Community Association (OCA)",
"maintainers": ["mmequignon"],
"license": "AGPL-3",
diff --git a/stock_product_variant_mto/models/product_product.py b/stock_product_variant_mto/models/product_product.py
index a2d3037934e4..4cf5b36427df 100644
--- a/stock_product_variant_mto/models/product_product.py
+++ b/stock_product_variant_mto/models/product_product.py
@@ -1,7 +1,7 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-from odoo import api, models, fields
+from odoo import api, fields, models
IS_MTO_HELP = """
Check or Uncheck this field to enable the Make To Order on the variant,
@@ -10,6 +10,7 @@
will reset this setting on its variants.
"""
+
class ProductProduct(models.Model):
_inherit = "product.product"
@@ -25,7 +26,7 @@ class ProductProduct(models.Model):
"stock.location.route",
compute="_compute_route_ids",
domain="[('product_selectable', '=', True)]",
- store=False
+ store=False,
)
def _compute_is_mto(self):
diff --git a/stock_product_variant_mto/models/product_template.py b/stock_product_variant_mto/models/product_template.py
index e1680cc66629..faf0670d98dc 100644
--- a/stock_product_variant_mto/models/product_template.py
+++ b/stock_product_variant_mto/models/product_template.py
@@ -1,7 +1,8 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-from odoo import _, api, models, fields
+from odoo import _, api, models
+
class ProductTemplate(models.Model):
_inherit = "product.template"
diff --git a/stock_product_variant_mto/views/product_product.xml b/stock_product_variant_mto/views/product_product.xml
index 1e5720bae1e8..b83e92d7bfdd 100644
--- a/stock_product_variant_mto/views/product_product.xml
+++ b/stock_product_variant_mto/views/product_product.xml
@@ -8,6 +8,8 @@
product.product
+