Skip to content

Commit

Permalink
[FIX] mto_as_mts_orderpoint_product_variant: Refactor for archival
Browse files Browse the repository at this point in the history
  • Loading branch information
grindtildeath committed Feb 10, 2025
1 parent d634638 commit 4ed01c0
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 54 deletions.
1 change: 1 addition & 0 deletions sale_stock_mto_as_mts_orderpoint/models/product_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from odoo import models


class ProductProduct(models.Model):
_inherit = "product.product"

Expand Down
37 changes: 21 additions & 16 deletions sale_stock_mto_as_mts_orderpoint/models/stock_warehouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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),
]
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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})
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -25,6 +25,7 @@ def setUpClass(cls):
]
)
cls.warehouse = cls.env.ref("stock.warehouse0")
cls.warehouse.mto_as_mts = True

@classmethod
def setUpClassProduct(cls):
Expand All @@ -49,21 +50,41 @@ 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
green_pen = self.green_pen
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(),
Expand All @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion stock_product_variant_mto/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 3 additions & 2 deletions stock_product_variant_mto/models/product_product.py
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -10,6 +10,7 @@
will reset this setting on its variants.
"""


class ProductProduct(models.Model):
_inherit = "product.product"

Expand All @@ -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):
Expand Down
3 changes: 2 additions & 1 deletion stock_product_variant_mto/models/product_template.py
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
2 changes: 2 additions & 0 deletions stock_product_variant_mto/views/product_product.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<!-- TODO: Set route_ids as readonly here to avoid any mess?
And add tooltip to mention it is to be configured on product template -->
<group name="operations" position="inside">
<field name="is_mto"/>
</group>
Expand Down

0 comments on commit 4ed01c0

Please sign in to comment.