Appointments
Schedule one or many visits per work order — multi-day jobs and follow-ups handled natively.
A service appointment is one scheduled visit. A work order can have many appointments — for multi-day jobs, follow-ups, retries, or when different technicians need to do different parts of the job at different times.
If you've used FSM systems where every job has exactly one schedule, the split takes a minute to internalize. The pay-off: multi-day jobs and follow-up visits stop being workarounds.
When a work order has 1 appointment vs many
| Situation | Modeling |
|---|---|
| One tech, one visit, in and out | 1 appointment (sequence 1) |
| Tech arrives, finds extra work, needs to come back | 2 appointments — original + follow-up (sequence 2, parent_appointment_id set) |
| 3-day install | 3 appointments (sequences 1, 2, 3) — same WO, different dates, possibly different techs |
| Customer no-show, reschedule for next week | 2 appointments — first marked no_show, second scheduled |
| Recurring service contract | 1 appointment per generated visit; all under the same contract-spawned WOs |
Scheduling the first appointment
When a work order is freshly created (draft status), it has no appointments. To schedule the first visit:
- Open the work order at
/fsm/work-orders/[id]. - Click Add appointment on the Appointments card.
- Enter:
- Scheduled start + end (timestamps; multi-day windows allowed)
- Assigned technician (or leave blank for the dispatcher / AI to fill in)
- Location — defaults to the work order's default location, override if needed
- Save.
The appointment starts in status scheduled. The work order auto-flips from draft to scheduled.
Scheduling a follow-up
When a tech is on-site and realizes another visit is needed (parts on order, customer not ready, more time required):
- Open the parent appointment.
- Use Schedule follow-up.
- Inherit the parent's location + tech by default, override as needed.
- The new appointment carries
parent_appointment_idpointing back to the parent, and gets the next sequence number.
You can chain follow-ups — useful for tracking parts that need to ship and a second visit to install them.
Appointment status
| Status | Meaning | Side-effects |
|---|---|---|
scheduled | Booked, not started | — |
en_route | Tech has started travel | — |
on_site | Tech checked in at the location | Stamps actual_start |
paused | Work suspended (waiting on parts / customer / etc.) | — |
completed | Work done for this visit | Stamps actual_end; auto-seeds a service report; fires asset-maintenance bridge per visit (if WO has an asset); auto-completes the WO if no other open appointments |
cancelled | Visit cancelled by dispatcher | Captures cancellation reason |
no_show | Customer not available | Schedule a new appointment to retry |
The flow is lenient — you can transition out of order (e.g. paused → on_site after a customer callback).
What happens when an appointment completes
Marking an appointment completed cascades three side-effects automatically:
- Stamps
actual_endwith the current timestamp. - Auto-seeds a draft service report (one per appointment, idempotent). The technician then fills in the narrative + photos. See Service Reports.
- If the work order has an asset, writes a row to the asset's maintenance log — one entry per visit (not per work order). Multi-visit jobs get one maintenance entry per actual visit, which is what most asset history reports expect.
Then: if this was the last open appointment for the work order, the work order auto-flips to completed. Defensive against re-runs — if the WO is already completed, the cascade no-ops cleanly.
Where appointments appear
| Surface | Shows |
|---|---|
/fsm (dispatcher board) | Kanban by appointment status — drag-free v1; click status buttons to advance |
/fsm/appointments | Flat list of every appointment across all work orders |
/fsm/work-orders/[id] | Appointments tab on the work-order detail page |
/fsm/dispatch | AI suggestions for unassigned scheduled appointments |
Multi-tech crews (current limitation)
Today the appointment carries a single assigned_user_id plus a crew_user_ids array for ad-hoc additional techs. The dispatch view + status transitions are driven by the primary assignee. A proper Crews entity (with crew lead, member windows, crew-level skills) is queued for the next release.
Activity log
Every status change, reschedule, and reassignment auto-appends a row to the work order's activity log. Useful for "what happened to this job between 9am and noon?" investigations.
Related
- Work Orders — the parent entity
- Dispatch — AI-assisted assignment
- Service Reports — what auto-seeds on completion