Skip to content

Commit 1b966b9

Browse files
committed
[FIX] mrp: find child/source MO
When a MO is generated in order to supply another one, the smart buttons "Source MO"/"Child MO" are still invisible. To reproduce the issue: 1. In Settings, enable "Multi-Step Routes" 2. Enable MTO route 3. Edit the warehouse: 3-steps manufacturing 4. Create 3 stored products Super, Sub and Compo: - Sub has two routes: MTO and Manufacture 5. Create two BoMs: - For 1 x Super: - 1 x Sub - For 1 x Sub: - 1 x Compo 6. Create and confirm a MO with 1 x Super Error: On confirmation, a second MO is created to produce one Sub, which is correct. However, neither the first MO nor the generated one has a link with the other one (through the smart button "Source MO"/"Child MO") When confirming the MO, a SM is created to bring one Sub to the pre-production location. Thanks to MTO route, this will generate another SM that brings one Sub from post-production to stock location (this will lead to the creation of the second MO). However, the other SM (1 x Sub from Post to Stock) doesn't have the same procurement group. This is the reason why it is not found by the `_compute` methods. OPW-2730830 closes odoo#94297 X-original-commit: 81e5ce0 Signed-off-by: Arnold Moyaux (arm) <[email protected]> Signed-off-by: Adrien Widart <[email protected]>
1 parent daaa6ab commit 1b966b9

File tree

2 files changed

+77
-6
lines changed

2 files changed

+77
-6
lines changed

addons/mrp/models/mrp_production.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,17 @@ def _get_default_is_locked(self):
274274
compute='_compute_show_allocation',
275275
help='Technical Field used to decide whether the button "Allocation" should be displayed.')
276276

277-
@api.depends('procurement_group_id.stock_move_ids.created_production_id.procurement_group_id.mrp_production_ids')
277+
@api.depends('procurement_group_id.stock_move_ids.created_production_id.procurement_group_id.mrp_production_ids',
278+
'procurement_group_id.stock_move_ids.move_orig_ids.created_production_id.procurement_group_id.mrp_production_ids')
278279
def _compute_mrp_production_child_count(self):
279280
for production in self:
280-
production.mrp_production_child_count = len(production.procurement_group_id.stock_move_ids.created_production_id.procurement_group_id.mrp_production_ids - production)
281+
production.mrp_production_child_count = len(production._get_children())
281282

282-
@api.depends('move_dest_ids.group_id.mrp_production_ids')
283+
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.mrp_production_ids',
284+
'procurement_group_id.stock_move_ids.move_dest_ids.group_id.mrp_production_ids')
283285
def _compute_mrp_production_source_count(self):
284286
for production in self:
285-
production.mrp_production_source_count = len(production.procurement_group_id.mrp_production_ids.move_dest_ids.group_id.mrp_production_ids - production)
287+
production.mrp_production_source_count = len(production._get_sources())
286288

287289
@api.depends('procurement_group_id.mrp_production_ids')
288290
def _compute_mrp_production_backorder(self):
@@ -1110,9 +1112,21 @@ def _autoconfirm_production(self):
11101112

11111113
self.workorder_ids.filtered(lambda w: w.state not in ['done', 'cancel'])._action_confirm()
11121114

1115+
def _get_children(self):
1116+
self.ensure_one()
1117+
procurement_moves = self.procurement_group_id.stock_move_ids
1118+
child_moves = procurement_moves.move_orig_ids
1119+
return (procurement_moves | child_moves).created_production_id.procurement_group_id.mrp_production_ids - self
1120+
1121+
def _get_sources(self):
1122+
self.ensure_one()
1123+
dest_moves = self.procurement_group_id.mrp_production_ids.move_dest_ids
1124+
parent_moves = self.procurement_group_id.stock_move_ids.move_dest_ids
1125+
return (dest_moves | parent_moves).group_id.mrp_production_ids - self
1126+
11131127
def action_view_mrp_production_childs(self):
11141128
self.ensure_one()
1115-
mrp_production_ids = self.procurement_group_id.stock_move_ids.created_production_id.procurement_group_id.mrp_production_ids.ids
1129+
mrp_production_ids = self._get_children().ids
11161130
action = {
11171131
'res_model': 'mrp.production',
11181132
'type': 'ir.actions.act_window',
@@ -1132,7 +1146,7 @@ def action_view_mrp_production_childs(self):
11321146

11331147
def action_view_mrp_production_sources(self):
11341148
self.ensure_one()
1135-
mrp_production_ids = self.procurement_group_id.mrp_production_ids.move_dest_ids.group_id.mrp_production_ids.ids
1149+
mrp_production_ids = self._get_sources().ids
11361150
action = {
11371151
'res_model': 'mrp.production',
11381152
'type': 'ir.actions.act_window',

addons/mrp/tests/test_order.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,3 +2518,60 @@ def test_qty_update_and_method_reservation(self):
25182518
wizard.change_prod_qty()
25192519

25202520
self.assertFalse(mo.move_raw_ids.move_line_ids)
2521+
2522+
def test_source_and_child_mo(self):
2523+
"""
2524+
Suppose three manufactured products A, B and C. C is a component of B
2525+
and B is a component of A. If B and C have the routes MTO + Manufacture,
2526+
when producing one A, it should generate a MO for B and C. Moreover,
2527+
starting from one of the MOs, we should be able to find the source/child
2528+
MO.
2529+
(The test checks the flow in 1-step, 2-steps and 3-steps manufacturing)
2530+
"""
2531+
warehouse = self.env['stock.warehouse'].search([('company_id', '=', self.env.company.id)], limit=1)
2532+
mto_route = warehouse.mto_pull_id.route_id
2533+
manufacture_route = warehouse.manufacture_pull_id.route_id
2534+
mto_route.active = True
2535+
2536+
grandparent, parent, child = self.env['product.product'].create([{
2537+
'name': n,
2538+
'type': 'product',
2539+
'route_ids': [(6, 0, mto_route.ids + manufacture_route.ids)],
2540+
} for n in ['grandparent', 'parent', 'child']])
2541+
component = self.env['product.product'].create({
2542+
'name': 'component',
2543+
'type': 'consu',
2544+
})
2545+
2546+
self.env['mrp.bom'].create([{
2547+
'product_tmpl_id': finished_product.product_tmpl_id.id,
2548+
'product_qty': 1,
2549+
'type': 'normal',
2550+
'bom_line_ids': [
2551+
(0, 0, {'product_id': compo.id, 'product_qty': 1}),
2552+
],
2553+
} for finished_product, compo in [(grandparent, parent), (parent, child), (child, component)]])
2554+
2555+
none_production = self.env['mrp.production']
2556+
for steps, case_description, in [('mrp_one_step', '1-step Manufacturing'), ('pbm', '2-steps Manufacturing'), ('pbm_sam', '3-steps Manufacturing')]:
2557+
warehouse.manufacture_steps = steps
2558+
2559+
grandparent_production_form = Form(self.env['mrp.production'])
2560+
grandparent_production_form.product_id = grandparent
2561+
grandparent_production = grandparent_production_form.save()
2562+
grandparent_production.action_confirm()
2563+
2564+
child_production, parent_production = self.env['mrp.production'].search([('product_id', 'in', (parent + child).ids)], order='id desc', limit=2)
2565+
2566+
for source_mo, mo, product, child_mo in [(none_production, grandparent_production, grandparent, parent_production),
2567+
(grandparent_production, parent_production, parent, child_production),
2568+
(parent_production, child_production, child, none_production)]:
2569+
2570+
self.assertEqual(mo.product_id, product, '[%s] There should be a MO for product %s' % (case_description, product.display_name))
2571+
self.assertEqual(mo.mrp_production_source_count, len(source_mo), '[%s] Incorrect value for product %s' % (case_description, product.display_name))
2572+
self.assertEqual(mo.mrp_production_child_count, len(child_mo), '[%s] Incorrect value for product %s' % (case_description, product.display_name))
2573+
2574+
source_action = mo.action_view_mrp_production_sources()
2575+
child_action = mo.action_view_mrp_production_childs()
2576+
self.assertEqual(source_action.get('res_id', False), source_mo.id, '[%s] Incorrect value for product %s' % (case_description, product.display_name))
2577+
self.assertEqual(child_action.get('res_id', False), child_mo.id, '[%s] Incorrect value for product %s' % (case_description, product.display_name))

0 commit comments

Comments
 (0)