Work Orders
The committed job — customer, asset, lines, and a workflow that drives appointments through to billing.
A work order is the committed job. It captures who the customer is, which asset (if any) is being serviced, the line items (labor, parts, expense, flat fees) that will be billed, and a workflow gate from draft → billed.
Work orders do not carry scheduling themselves — that lives on appointments. One work order can have many appointments (multi-day, follow-ups, retries). Even single-visit jobs are modeled as a work order + one sequence-1 appointment.
Creating a work order
Three paths:
| When | How |
|---|---|
| Customer asked, no quote needed | Open a request → Convert to work order |
| Customer approved a quote | Open an estimate → Convert to work order (lines copy across) |
| Ad-hoc / dispatcher-initiated | /fsm/work-orders/new — fill title, description, priority, service type, then schedule the first appointment from the detail page |
Every work order is auto-numbered WO-YYYY-NNNN.
What's on a work order
| Field | Notes |
|---|---|
| Number | WO-YYYY-NNNN, auto-allocated |
| Title + Description | What the job is |
| Service type | Free-text label (drives skill matching in dispatch) |
| Priority | low / medium / high / urgent |
| Status | Workflow gate — see below |
| Customer | Contact and/or company from CRM |
| Asset | Linked asset under service (optional) — when present, completion writes to the asset's maintenance log |
| Service contract | When the WO was generated from a recurring contract |
| Default location | Address + lat/lng — copied to the first appointment by default |
| SLA | Response due + resolution due timestamps; daily breach scan |
| Estimated | Duration (minutes) + total (money) |
| Currency | 3-letter ISO |
Work order status
The work order status is the workflow gate. The appointment status is the operational state of each visit. Don't conflate the two.
| Status | Meaning | Transitions to |
|---|---|---|
draft | Created, no appointments scheduled yet | scheduled, cancelled |
scheduled | At least one appointment booked | dispatched, cancelled |
dispatched | A technician has been notified for at least one appointment | in_progress, cancelled |
in_progress | Work is happening | completed, cancelled |
completed | All appointments done; ready to bill | billed |
billed | Finance invoice generated (manual today; auto-bridge queued for Phase 4.8) | — |
cancelled | Cancelled; no work performed | — |
When the last open appointment transitions to completed, the work order auto-rolls up to completed. You don't need to flip it manually.
Line items
Work-order line items live on fsm_work_order_lines. Four types:
| Line type | Use for | Driven by |
|---|---|---|
labor | Tech time on the job | hours × rate_per_hour |
parts | Materials consumed | quantity × unit_price (FK to a Stock product) |
expense | Reimbursable pass-through | quantity × unit_price |
flat_fee | Fixed-price items | quantity × unit_price |
When you convert an estimate to a work order, all active estimate lines copy here automatically.
Parts pulls
When a technician consumes a part on site, log it via Parts pulls on the work-order detail page. Each pull:
- Writes a
fsm_parts_pullsrow with the product, quantity, and source location (truck or warehouse). - Fires the fsm_stock bridge to write a
stock_movementsrow (kind=consumption,source_type=fsm_parts_pull). - Reduces stock inventory in the source location.
Parts pulls are idempotent on an idempotency key — replaying the same pull (e.g. on retry) doesn't double-deduct.
Asset maintenance log
If the work order has an asset_id, every completed appointment automatically writes a row to the asset's maintenance log via the assets_fsm bridge. Multi-visit jobs log one maintenance entry per visit (per-appointment marker — idempotent).
SLA tracking
Each work order can have a response due (when a tech must be assigned) and resolution due (when the job must be complete) deadline. A daily cron at 14:30 UTC scans for work orders past either deadline and logs the breach. Webhook delivery + Slack/Teams notification is queued for Phase 4.10.
Cancelling a work order
Open the work-order detail → use the status transitions card → cancel. Cancellation is a terminal state for the work order. In-flight appointments are not auto-cancelled — cancel them individually if needed (e.g. tech is already on site and you want to keep the visit log).
Related
- Appointments — scheduled visits attached to this work order
- Estimates — pre-WO pricing and approval
- Dispatch — assigning technicians to appointments
- Service Reports — post-visit signed PDF