Skip to main content
Version: v1.0.0(int)

Work orders

Header + output line items + recipe snapshot + receipts. WOs convert materials into finished goods at a work site (a org.locations row). The recipe (which inputs are needed for each output line) is snapshotted from bom_items at the time the WO line is created — see work_order_inputs below. Status is an org.wo_status ENUM stored directly on the row.

ER diagram

org.work_orders

ColumnTypeNotes
idUUID PK
org_idUUID FKplatform.organizations(id).
wo_numberVARCHAR(100)NOT NULL. UNIQUE per (org_id, wo_number).
statuswo_statusNOT NULL. ENUM. See values below.
work_site_idUUID FKNOT NULL. → org.locations(id) ON DELETE RESTRICT.
placed_atDATENOT NULL when status ≥ Placed. Matches the Placed transition.
expected_delivery_dateDATETarget completion date. Not a lifecycle date.
production_started_atDATEMatches Production status.
received_atDATEMatches Received status.
cancelled_atDATEMatches Cancelled status.
notesTEXT
created_atTIMESTAMPTZNOT NULL. Default NOW().
updated_atTIMESTAMPTZNOT NULL. Default NOW(). Auto-updated by trigger.

org.work_order_items

The SKUs the WO is producing.

ColumnTypeNotes
idUUID PK
org_idUUID FK
work_order_idUUID FKNOT NULL. → org.work_orders(id) ON DELETE CASCADE.
sku_idUUID FKNOT NULL. → org.skus(id) ON DELETE RESTRICT.
quantityINTEGERNOT NULL. CHECK ≥ 1. SKU output is in sales-unit integers.
conversion_costNUMERIC(18,6)NOT NULL. CHECK ≥ 0. Default 0. Planned labor / overhead per unit produced. User-entered at WO creation as a planning estimate.
created_atTIMESTAMPTZNOT NULL. Default NOW().

Material cost per unit is not stored on this row — it's derived at consume time from work_order_inputs and current material costs. conversion_cost covers the labor/overhead estimate that doesn't have a derivable source.

org.work_order_inputs

Recipe snapshot. Copied from bom_items at the moment a work_order_items row is created, so future BOM edits don't change what's already in flight.

ColumnTypeNotes
idUUID PK
org_idUUID FKplatform.organizations(id).
work_order_idUUID FKNOT NULL. → org.work_orders(id) ON DELETE CASCADE. Denormalized for query simplicity.
work_order_item_idUUID FKNOT NULL. → org.work_order_items(id) ON DELETE CASCADE. The output line this input feeds.
material_idUUID FKorg.materials(id) ON DELETE RESTRICT. XOR with input_sku_id.
input_sku_idUUID FKorg.skus(id) ON DELETE RESTRICT. XOR with material_id.
quantityNUMERIC(18,6)NOT NULL. CHECK > 0. Per unit of output — total consumption = work_order_items.quantity × work_order_inputs.quantity.
created_atTIMESTAMPTZNOT NULL. Default NOW().

Constraints:

  • XOR CHECK: ((material_id IS NOT NULL AND input_sku_id IS NULL) OR (material_id IS NULL AND input_sku_id IS NOT NULL)).
  • No UI to edit the snapshot rows in v1. Per-WO recipe overrides are deferred — see the L1 Out of scope list.

org.work_order_receipts

ColumnTypeNotes
idUUID PK
org_idUUID FK
work_order_idUUID FKNOT NULL. → org.work_orders(id) ON DELETE CASCADE.
receipt_dateDATENOT NULL. Default CURRENT_DATE.
created_atTIMESTAMPTZNOT NULL. Default NOW().

org.work_order_receipt_items

ColumnTypeNotes
idUUID PK
org_idUUID FK
receipt_idUUID FKNOT NULL. → org.work_order_receipts(id) ON DELETE CASCADE.
sku_idUUID FKNOT NULL. → org.skus(id) ON DELETE RESTRICT.
quantityINTEGERNOT NULL. CHECK ≥ 1. Default 1. SKU output is integer.
unit_costNUMERIC(18,6)NOT NULL. CHECK ≥ 0. Default 0. Actual unit cost at receipt (material + conversion) — flows to FG ledger.
created_atTIMESTAMPTZNOT NULL. Default NOW().

Status values

org.wo_status ENUM: DraftEnteredPlacedProductionIn TransitPartialReceivedCompleted, plus terminal Cancelled.

Documents

Files attached to a work order live in the polymorphic org.documents table with entity_type = 'work_order'. Useful for work instructions, quality control sheets, supplier specs.

Cross-references

  • Drives both inventory ledgers: WO completion writes a RECEIVE event to the finished goods ledger, and the corresponding CONSUME events on the materials ledger for the BOM-resolved inputs.
  • L3 workflow logic reads status directly — the enum value is the stable contract.

Notes

  • No is_active — cancellation is status = Cancelled.
  • Lifecycle dates match statuses: placed_at (Placed), production_started_at (Production), received_at (Received), cancelled_at (Cancelled). Draft has no date — created_at answers that. Partial has no dedicated date — the first receipt's receipt_date is the de facto answer.
  • Material cost is derived, not stored on work_order_items. Conversion cost is the only WO-line cost column.