[IMP] mrp_sale_info: Materialize link between sale order lines and created MOs

Improve test with 3 steps delivery route and use RecordCapturer
This commit is contained in:
Akim Juillerat
2024-07-01 20:17:57 +02:00
parent 6161253e92
commit 9500eaa46d
4 changed files with 153 additions and 7 deletions

View File

@@ -2,4 +2,6 @@
from . import mrp_production
from . import mrp_workorder
from . import sale_order_line
from . import stock_move
from . import stock_rule

View File

@@ -0,0 +1,57 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo import api, fields, models
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
created_production_ids = fields.Many2many(
"mrp.production",
compute="_compute_created_production_ids",
store=True,
)
@api.depends(lambda sol: sol._created_prod_move_deps())
def _compute_created_production_ids(self):
for line in self:
delivery_moves = line.move_ids
mrp_production_ids = set()
for move in delivery_moves:
mrp_production_ids.update(move._get_orig_created_production_ids().ids)
# Consider MO Backorders for serial numbers
mrp_production_ids.update(
self.env["mrp.production"]
.browse(mrp_production_ids)
.mapped("procurement_group_id.mrp_production_ids")
.ids
)
line.created_production_ids = [fields.Command.set(list(mrp_production_ids))]
def _created_prod_move_deps(self):
fnames = [
"move_ids",
"move_ids.created_production_id",
"move_ids.created_production_id.procurement_group_id.mrp_production_ids",
]
# Allow customizing how many levels of recursive moves must be considered to
# compute the created_production_ids field on sale.order.line.
# This value must be at least equal to the number of:
# delivery steps + post manufacturing operations of the warehouse - 1.
# FIXME: Check if there's a way to recompute the dependency without having to
# restart Odoo.
try:
levels = int(
self.env["ir.config_parameter"]
.sudo()
.get_param("mrp_sale_info.compute.created_prod_ids_move_dep_levels", 3)
)
except ValueError:
levels = 3
for num in range(1, levels + 1):
fnames.append("move_ids.%screated_production_id" % ("move_orig_ids." * num))
fnames.append(
"move_ids.%screated_production_id.procurement_group_id.mrp_production_ids"
% ("move_orig_ids." * num)
)
return fnames

View File

@@ -0,0 +1,16 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo import models
class StockMove(models.Model):
_inherit = "stock.move"
def _get_orig_created_production_ids(self):
self.ensure_one()
if self.created_production_id:
return self.created_production_id
mrp_production_ids = set()
for move in self.move_orig_ids:
mrp_production_ids.update(move._get_orig_created_production_ids().ids)
return self.env["mrp.production"].browse(mrp_production_ids)

View File

@@ -1,13 +1,17 @@
# Copyright 2020 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.tests import common
from odoo.tests import RecordCapturer, common
class TestMrpSaleInfo(common.TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
warehouse = cls.env.ref("stock.warehouse0")
warehouse.write(
{"delivery_steps": "pick_pack_ship", "manufacture_steps": "pbm_sam"}
)
route_manufacture_1 = cls.env.ref("mrp.route_warehouse0_manufacture")
route_manufacture_2 = cls.env.ref("stock.route_warehouse0_mto")
route_manufacture_2.active = True
@@ -21,6 +25,26 @@ class TestMrpSaleInfo(common.TransactionCase):
],
}
)
cls.product_kit = cls.env["product.product"].create(
{
"name": "Test kit",
"type": "product",
"route_ids": [
(4, route_manufacture_1.id),
(4, route_manufacture_2.id),
],
}
)
cls.product_kit_comp = cls.env["product.product"].create(
{
"name": "Test kit comp",
"type": "product",
"route_ids": [
(4, route_manufacture_1.id),
(4, route_manufacture_2.id),
],
}
)
cls.bom = cls.env["mrp.bom"].create(
{
"product_tmpl_id": cls.product.product_tmpl_id.id,
@@ -36,6 +60,28 @@ class TestMrpSaleInfo(common.TransactionCase):
],
}
)
cls.bom_kit = cls.env["mrp.bom"].create(
{
"product_tmpl_id": cls.product_kit.product_tmpl_id.id,
"type": "phantom",
"bom_line_ids": [
(
0,
0,
{
"product_id": cls.product.id,
},
),
(
0,
0,
{
"product_id": cls.product_kit_comp.id,
},
),
],
}
)
cls.partner = cls.env["res.partner"].create({"name": "Test client"})
cls.sale_order = cls.env["sale.order"].create(
{
@@ -56,17 +102,42 @@ class TestMrpSaleInfo(common.TransactionCase):
)
def test_mrp_sale_info(self):
prev_productions = self.env["mrp.production"].search([])
self.sale_order.action_confirm()
production = self.env["mrp.production"].search([]) - prev_productions
with RecordCapturer(self.env["mrp.production"], []) as capture:
self.sale_order.action_confirm()
production = capture.records
self.assertEqual(production.sale_id, self.sale_order)
self.assertEqual(production.partner_id, self.partner)
self.assertEqual(production.client_order_ref, self.sale_order.client_order_ref)
self.assertEqual(self.sale_order.order_line.created_production_ids, production)
def test_mrp_workorder(self):
prev_workorders = self.env["mrp.workorder"].search([])
self.sale_order.action_confirm()
workorder = self.env["mrp.workorder"].search([]) - prev_workorders
with RecordCapturer(self.env["mrp.workorder"], []) as capture:
self.sale_order.action_confirm()
workorder = capture.records
self.assertEqual(workorder.sale_id, self.sale_order)
self.assertEqual(workorder.partner_id, self.partner)
self.assertEqual(workorder.client_order_ref, self.sale_order.client_order_ref)
def test_kit(self):
self.sale_order.write(
{
"order_line": [
(
0,
0,
{
"product_id": self.product_kit.id,
"product_uom_qty": 2,
"price_unit": 1,
},
)
]
}
)
with RecordCapturer(self.env["mrp.production"], []) as capture:
self.sale_order.action_confirm()
productions = capture.records
for order_line in self.sale_order.order_line:
for created_prod in order_line.created_production_ids:
self.assertIn(created_prod, productions)
self.assertEqual(created_prod.product_qty, order_line.product_uom_qty)