Wiki · NetSuite expansion

NS work order lifecycle

From "production lead opens a WO" to "finished goods on the shelf". Nine phases, two STUB autoflows that still ride paper-and-keyboard, one HITL gate that catches BOM drift before it pollutes the cost surface.

Mixed · 7 real, 2 STUB
What this is

The factory floor in nine beats

The NS work order lifecycle is what happens every time GFS produces an assembly — a Right Start Foods burrito kit, a Melt Mates meal kit, a USDA brown-box pancake run. It starts with a work order opening (either manually or because quantityavailable tripped a reorder point) and ends with finished goods showing up as allocatable inventory.

It exists because manufacturing is the one place where NS is genuinely the system of record — we don't second-guess the build transaction, we mirror it. But the cost rollup, the variance audit, and the BOM-update HITL gate live on our side. So nine phases: NS does six of them, we do three (component reservation mirror, variance audit, FG availability mirror).

The diagram lives at ns-work-order-lifecycle.html. Two phases are still STUB — labor capture autoflow and NS-native component reservation. Those gaps are honest; the recovery path is in Failure modes below.

When to use it

Trigger conditions

Heuristic

Any WO with |actual cost − estimated cost| > 5% at close lands a row in proposed_actions for Mike. Below that, NS posts the build silently and the BOM stays untouched.

Worked example

WO #4821 — build 500 Right Start breakfast burritos

Scenario

Tuesday morning. Inventory shows RS-BURR-10472 at 38 cases — below the 50-case reorder point. NS auto-opens WO-4821 for 500 units. The BOM resolves to 8 components (tortilla, egg patty, cheese, sausage crumble, salsa pack, wrap film, case box, label). Components pull cleanly; the WO releases to the floor at 09:14.

By 14:30, production posts the build. NS rolls actual cost: components $1,842, labor $312 (entered by floor lead Susan via NS UI — STUB autoflow, no scanner kiosk yet), overhead $98. Total $2,252 vs estimated $2,180 — variance of +3.3%, under threshold. NS quietly closes the WO. Inventory shows 538 cases. The cost surface tile on the admin dashboard ticks by half a cent. No HITL was needed.

Contrast: WO-4822 the same week ran +7.1% over — a tortilla vendor cost moved and the BOM was stale. Variance audit fired, proposed_actions queued, Mike approved the BOM update on his phone at lunch. Cost surface re-anchored within 12 minutes.

Step-by-step what happens

The nine phases

  1. 01

    WO intake — manual or auto

    Either a production lead opens the work order in NS, or the reorder-point watcher fires when inventory_balance.quantityavailable drops below the assembly's reorder_point. The auto path emits a workorder.created event for downstream listeners.

    Writes workorder (NS), transactions (D1 mirror)
    Trigger manual or reorder-point
  2. 02

    Component pull — BOM resolution + reservation

    The runner reads assembly_bom for the assembly, walks each line, and checks inventory_balance at the production location. Required qty is logged. STUB: NS-native component reservation is not wired — we read availability but don't lock the rows, so a parallel SO could theoretically grab the components first. In practice this rarely bites because production starts within minutes.

    Reads assembly_bom, inventory_balance
    STUB NS component reservation
  3. 03

    Production start — status flips to 'In Progress'

    The floor lead releases the WO. NS transitions workorder.status='In Progress' and stamps start_timestamp. The D1 transactions row mirrors on the next 2-min hot sync.

    Writes workorder.status, start_ts
    Time mirrored ~2 min
  4. 04

    Labor capture — hours × rate against the WO

    Time entries are booked against the work order. Hours roll up into actual_labor_cost at close. STUB: there is no scanner/kiosk autoflow — floor leads (Susan, Marcus) enter time manually through the NS UI on a laptop in the office. This is the single largest data-quality risk in the lifecycle; it works because we have one shift and two leads, but it won't scale.

    Writes NS time entries
    STUB labor capture autoflow
  5. 05

    Component issue — debit inventory

    NS posts a workorderissue transaction. inventory_balance decrements per BOM line for the build qty. D1 mirrors with negative-qty rows in transaction_lines on the next hot sync.

    Writes workorderissue, inventory_balance--
    Mirror 2-min hot tier
  6. 06

    Build complete — credit finished goods

    Production posts the build. NS records a build transaction; inventory_balance increments at the production location for the assembly item. The credit and the matching debits from step 5 are linked by the NS build transaction id.

    Writes NS build txn, inventory_balance++
  7. 07

    WO close — status='Built', actual cost rollup

    NS flips workorder.status='Built' and rolls the actual cost: components from step 5, labor from step 4, allocated overhead. The rollup writes to the workorder header.

    Writes workorder.status='Built', actual_cost
  8. 08

    Variance audit — HITL if >5% drift

    The platform compares actual_cost vs estimated_cost from the BOM. If abs(diff) / estimated > 0.05, a row is inserted into proposed_actions with action_type='bom_variance_review', risk_level 3. Mike sees the diff at /proposed-actions.html and decides: update the BOM (most common) or flag a production exception (e.g. a one-off scrap).

    HITL risk_level 3
    Writes proposed_actions
  9. 09

    Finished goods — allocatable inventory

    inventory_balance.quantityavailable reflects the new build. Sales orders can now allocate against the SKU. The cost surface tile on the admin dashboard re-anchors with the new actual-cost data point. If Mike approved a BOM update in step 8, the new estimated cost is in effect for the next WO.

    Reads downstream: SO allocation, cost surface
    Mirror 2-min hot
Outcomes

What's different after the WO closes

Inventory
Updated
FG ++, components --
Cost surface
Re-anchored
new actual datapoint
Variance
Audited
HITL if >5%
D1 mirror
In sync
≤ 2 min
Failure modes

What can go wrong

Labor capture STUB — data quality risk

Floor leads forget to enter time, or enter wrong hours. Rollup uses estimated labor when actual is missing. Detection: variance audit flags WOs with labor_hours=0 AND build_qty>0. Manual recovery: backfill via NS UI; re-run cost rollup.

Component reservation STUB — race risk

A parallel SO could allocate a component before the WO consumes it. Detection: workorderissue failure with "insufficient inventory". Recovery: short-pick the SO or short-pack the WO; reorder ASAP.

BOM drift unflagged

Variance ≤ 5% repeated over many WOs can mask sustained cost creep. Detection: cost surface tile shows monotonic drift over 30 days. Recovery: manually trigger bom_variance_review at quarterly cost review.

Build reversed mid-cascade

If NS posts an assemblyunbuild after the variance audit fired, the HITL card may reference a vanished build. The decide endpoint catches this and returns "stale_action".

Related

Adjacent flows + diagrams

For developers

Code paths + invariants

ConcernWhere
WO mirror tabletransactions WHERE recordtype='workorder'
BOM sourceassembly_bom (D1 mirror of NS BOM)
Variance thresholdguardrails.workorder_variance_threshold (default 0.05)
HITL stageproposed_actions.action_type='bom_variance_review'
Cost rollupassembly_cost_rollup (Pillar 4)
Sync tierhot (2 min) for transactions; warm (5 min) for inventory_balance
NS push (BOM update)NS_PUSH_QUEUE, record_type='inventoryitem'
STUB — labor captureno scanner; NS UI manual entry only
STUB — component reservationread-only availability check; no NS row lock
// Variance audit trigger (simplified) const variance = Math.abs(actual_cost - estimated_cost) / estimated_cost; if (variance > 0.05) { stageProposedAction({ action_type: 'bom_variance_review', entity_ref: workorder_id, risk_level: 3, payload: { actual_cost, estimated_cost, variance_pct: variance } }); }