feat(bridge_mrp): Sub 3 — _resolve_mo_process_tree helper; walker prefers part-cloned tree (Task 3)

This commit is contained in:
gsinghpal
2026-04-22 08:47:41 -04:00
parent dd7c408df3
commit 4beffe9dc1

View File

@@ -495,8 +495,8 @@ class MrpProduction(models.Model):
"""
WorkOrder = self.env['mrp.workorder']
for production in self:
if not production.x_fc_recipe_id:
continue # No recipe assigned
if not production._resolve_mo_process_tree():
continue # No recipe / part tree assigned
if production.workorder_ids:
continue # WOs already exist — don't duplicate
@@ -679,7 +679,11 @@ class MrpProduction(models.Model):
# 'step' nodes at top level are handled by their parent operation
# Start walking from recipe root
walk_node(production.x_fc_recipe_id)
# Sub 3 — resolve via helper (part-cloned tree preferred,
# recipe_id fallback)
root = production._resolve_mo_process_tree()
if root:
walk_node(root)
# Bulk create work orders
if wo_vals_list:
@@ -699,7 +703,7 @@ class MrpProduction(models.Model):
)
production.message_post(
body=_('%d work orders generated from recipe "%s".') % (
len(wo_vals_list), production.x_fc_recipe_id.name),
len(wo_vals_list), (root.name if root else '')),
)
# ------------------------------------------------------------------
@@ -1146,6 +1150,37 @@ class MrpProduction(models.Model):
'target': 'current',
}
# ------------------------------------------------------------------
# Sub 3 — Process tree resolution (single source for WO walker)
# ------------------------------------------------------------------
def _resolve_mo_process_tree(self):
"""Resolve which process-tree root to walk for this MO.
Sub 3 — prefers the linked part's cloned tree
(SO line's x_fc_part_catalog_id.default_process_id); falls back
to the legacy x_fc_recipe_id for MOs without a linked part or
without a composed part tree.
Single entry point so Sub 4 / Sub 5 updates touch one method.
"""
self.ensure_one()
# Resolve part via SO lines (MO's origin → sale.order → first
# line's part). mrp.production has no direct part link; the
# relationship lives on sale.order.line.
part = False
if self.origin:
so = self.env['sale.order'].search(
[('name', '=', self.origin)], limit=1,
)
if so and so.order_line:
first_line = so.order_line[0]
if 'x_fc_part_catalog_id' in first_line._fields:
part = first_line.x_fc_part_catalog_id
if part and part.default_process_id:
return part.default_process_id
# Fallback — legacy recipe lookup (coating config / product match)
return self.x_fc_recipe_id
# ------------------------------------------------------------------
# Sub 2 — Certificate requirement resolution (single source)
# ------------------------------------------------------------------