feat(plating): seed 5 fresh MOs with mixed states + priorities
Stage filler gains step 6g — spins up five new manufacturing orders so the Manager Desk has a busy shop floor instead of the single in-flight MO that came out of the base seeder. Plan, in order of creation: WH/MO/00012 HOT Cyclone Manufacturing qty 25 unassigned WH/MO/00013 Urgent Westin Manufacturing qty 60 unassigned WH/MO/00014 Normal Honeywell Aerospace qty 18 auto-routed WH/MO/00015 Normal Amphenol Canada qty 40 routed + first WO started WH/MO/00016 Normal Magellan Aerospace qty 32 auto-routed Each MO is created via mrp.production.create() and confirmed through the bridge_mrp action_confirm() override, which auto-creates the portal job and generates ~9 WOs from the recipe with role-aware auto-routing. Post-create the script stamps priority on every WO and optionally clears assignments (HOT + Urgent) or starts the first WO (MO_00015) for variety. Recipe lookup was previously by code='ENP-ALUM-BASIC' which silently failed because the seed file uses code='ENP_ALUM_BASIC' (underscores) while the display name has dashes. Switched to "first available recipe of node_type=recipe" so the script works regardless of which spelling is canonical. Idempotent — bails early if there are already five-plus active MOs, so re-runs don't keep stacking new jobs. Verified on entech: Manager Desk now shows - 6 active MOs (was 1) - 23 unassigned active WOs (was 2) - 30 active+assigned WOs (was 6) - 2 WOs in progress now - all 7 operators with open queue (Marie 2, James 1, Carlos 8, etc.) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -451,6 +451,112 @@ def _add_paused_wo(env):
|
||||
print(f"[6b] Paused-WO marker set on {progress.display_name}")
|
||||
|
||||
|
||||
def _seed_fresh_mos(env):
|
||||
"""Spin up five new MOs in mixed states so the Manager Desk and the
|
||||
Tablet Station have a busy shop floor to look at, not just one
|
||||
in-flight job.
|
||||
|
||||
Each MO generates ~9 WOs from the ENP-ALUM-BASIC recipe via the
|
||||
bridge_mrp action_confirm() override (auto-create portal job +
|
||||
auto-route workers by role). After confirmation we tweak the
|
||||
result so the demo has visible variety:
|
||||
|
||||
- MO_A HOT priority, all WOs unassigned (Needs a Worker pile)
|
||||
- MO_B Urgent, all WOs unassigned (Needs a Worker pile)
|
||||
- MO_C Normal, auto-routed (team queues)
|
||||
- MO_D Normal, auto-routed + first WO started (live workload)
|
||||
- MO_E Normal, auto-routed (team queues)
|
||||
|
||||
Idempotent: runs only when fewer than 13 active MOs exist (3 baseline
|
||||
+ 5 created here + a small buffer).
|
||||
"""
|
||||
Production = env['mrp.production']
|
||||
SO = env['sale.order']
|
||||
Product = env['product.product']
|
||||
Recipe = env['fusion.plating.process.node']
|
||||
|
||||
active_mo_count = Production.search_count([('state','not in',('done','cancel'))])
|
||||
if active_mo_count >= 5:
|
||||
print(f"[6g] Already have {active_mo_count} active MOs — skipping")
|
||||
return
|
||||
|
||||
product = Product.search([('default_code', '=', 'FP-WIDGET')], limit=1)
|
||||
# Recipe code stores underscores (ENP_ALUM_BASIC) while the
|
||||
# display name uses dashes — historical drift between the two
|
||||
# data files. Just take the first available recipe so the seed
|
||||
# works regardless of which spelling is canonical today.
|
||||
recipe = Recipe.search([('node_type', '=', 'recipe')], limit=1)
|
||||
if not product or not recipe:
|
||||
print("[6g] Missing product/recipe — skipping (need FP-WIDGET + a recipe)")
|
||||
return
|
||||
|
||||
# Customer + qty + priority + post-create tweaks for each MO.
|
||||
customer_names = [
|
||||
'Cyclone Manufacturing Inc.',
|
||||
'Westin Manufacturing Ltd',
|
||||
'Honeywell Aerospace Toronto',
|
||||
'Amphenol Canada Corp.',
|
||||
'Magellan Aerospace',
|
||||
]
|
||||
plan = [
|
||||
# (customer_idx, qty, priority, unassign_all, start_first)
|
||||
(0, 25, '2', True, False), # HOT, unassigned
|
||||
(1, 60, '1', True, False), # Urgent, unassigned
|
||||
(2, 18, '0', False, False), # Normal, auto-routed
|
||||
(3, 40, '0', False, True), # Normal, auto-routed, first WO started
|
||||
(4, 32, '0', False, False), # Normal, auto-routed
|
||||
]
|
||||
|
||||
created = 0
|
||||
for cust_idx, qty, prio, unassign_all, start_first in plan:
|
||||
partner = env['res.partner'].search(
|
||||
[('name', '=', customer_names[cust_idx])], limit=1,
|
||||
)
|
||||
# Sale order origin lookup — fall back to a synthetic ref if no
|
||||
# SO exists for this customer (just so the demo card has text).
|
||||
so = SO.search([('partner_id', '=', partner.id)], limit=1) if partner else None
|
||||
origin = so.name if so else f'DEMO-{customer_names[cust_idx][:6].upper()}'
|
||||
|
||||
vals = {
|
||||
'product_id': product.id,
|
||||
'product_qty': qty,
|
||||
'product_uom_id': product.uom_id.id,
|
||||
'origin': origin,
|
||||
'x_fc_recipe_id': recipe.id,
|
||||
'company_id': env.company.id,
|
||||
}
|
||||
# Some installs put partner_id on mrp.production; use it if present.
|
||||
if partner and 'partner_id' in Production._fields:
|
||||
vals['partner_id'] = partner.id
|
||||
|
||||
try:
|
||||
mo = Production.create(vals)
|
||||
mo.action_confirm() # bridge override generates WOs + routes them
|
||||
except Exception as exc:
|
||||
print(f" !! MO create failed for {customer_names[cust_idx]}: {exc!r}")
|
||||
continue
|
||||
|
||||
# Stamp priority on every generated WO so the Manager Desk
|
||||
# cards show the badge.
|
||||
mo.workorder_ids.write({'x_fc_priority': prio})
|
||||
|
||||
if unassign_all:
|
||||
mo.workorder_ids.write({'x_fc_assigned_user_id': False})
|
||||
|
||||
if start_first:
|
||||
first = mo.workorder_ids.sorted('sequence')[:1]
|
||||
if first and first.state in ('ready', 'pending', 'waiting'):
|
||||
try:
|
||||
first.button_start()
|
||||
except Exception:
|
||||
# Cert gate or similar — not fatal for the demo seed.
|
||||
pass
|
||||
|
||||
created += 1
|
||||
|
||||
print(f"[6g] Created {created} fresh MOs (HOT/Urgent unassigned + 3 auto-routed)")
|
||||
|
||||
|
||||
def _populate_active_wos(env):
|
||||
"""Make sure the Manager Desk's three columns all have visible data.
|
||||
|
||||
@@ -630,6 +736,7 @@ _safe('6c. add quote requests', _add_quote_requests)
|
||||
_safe('6d. mark one quote sent', _mark_quote_sent)
|
||||
_safe('6e. populate active WOs', _populate_active_wos)
|
||||
_safe('6f. SO awaiting-manager', _mark_so_awaiting_manager)
|
||||
_safe('6g. seed fresh MOs', _seed_fresh_mos)
|
||||
print("=========================================================")
|
||||
print("Done. Re-run anytime — script is idempotent.")
|
||||
print("=========================================================\n")
|
||||
|
||||
Reference in New Issue
Block a user