Skip to content

Ticket State Machine

Every repair ticket in RepairOps follows a defined state machine. This page documents every status, the allowed transitions between them, which roles can perform each transition, and the gate requirements that must be satisfied before leaving certain statuses.

Click any status node to see its details, allowed transitions, permitted roles, and gate requirements. Gated statuses have dashed borders and an amber dot.

Standard status Exit gate Terminal Forward transition Retry / backstep

RepairOps defines 13 ticket statuses. Every ticket starts at INTAKE and ends at CLOSED or VOIDED.

#StatusDescription
1INTAKETicket created, awaiting initial data collection
2TRIAGEManager reviews and assigns tech
3DIAGNOSTICSTech investigates the issue
4WAITING_APPROVALQuote sent, awaiting customer approval
5APPROVEDCustomer approved the quote
6WAITING_ON_PARTSParts ordered, waiting for delivery
7IN_REPAIRActive repair in progress
8QC_REVIEWQuality check before release
9QC_FAILEDQC found issues, returns to repair
10READY_FOR_PICKUPRepair complete, awaiting customer
11PICKED_UPCustomer collected the device
12CLOSEDFinal state — ticket complete
13VOIDEDCancelled at any stage

The following diagram shows every valid transition. Dashed lines indicate backsteps and retries.

stateDiagram-v2
[*] --> INTAKE
INTAKE --> TRIAGE
INTAKE --> VOIDED
TRIAGE --> DIAGNOSTICS
TRIAGE --> VOIDED
DIAGNOSTICS --> WAITING_APPROVAL
DIAGNOSTICS --> TRIAGE : backstep
DIAGNOSTICS --> VOIDED
WAITING_APPROVAL --> APPROVED
WAITING_APPROVAL --> VOIDED
APPROVED --> WAITING_ON_PARTS
APPROVED --> IN_REPAIR
APPROVED --> VOIDED
WAITING_ON_PARTS --> IN_REPAIR
WAITING_ON_PARTS --> VOIDED
IN_REPAIR --> QC_REVIEW
IN_REPAIR --> VOIDED
QC_REVIEW --> READY_FOR_PICKUP
QC_REVIEW --> QC_FAILED
QC_REVIEW --> VOIDED
QC_FAILED --> IN_REPAIR : retry
QC_FAILED --> VOIDED
READY_FOR_PICKUP --> PICKED_UP
READY_FOR_PICKUP --> VOIDED
PICKED_UP --> CLOSED
CLOSED --> [*]
VOIDED --> [*]

Not every role can trigger every transition. The table below shows which roles are allowed to move a ticket into each target status.

Target StatusOWNERMANAGERFRONT_DESKTECHQCACCOUNTINGDISPATCHER
INTAKE
TRIAGE
DIAGNOSTICS
WAITING_APPROVAL
APPROVED
WAITING_ON_PARTS
IN_REPAIR
QC_REVIEW
QC_FAILED
READY_FOR_PICKUP
PICKED_UP
CLOSED
VOIDED

OWNER and MANAGER can perform any transition. Other roles are limited to transitions relevant to their responsibilities.

Certain statuses have exit gates — conditions that must be met before a ticket can leave that status. Gates enforce data quality and ensure no ticket moves forward with incomplete information.

Gate (Exit From)Required FieldsDescription
INTAKEcustomer_id, device_identifier, issue_category, consent_signed, photos_min_2Basic intake data must be collected before triage
DIAGNOSTICSdiagnostic_checklist_complete, findings_summary, evidence_attachments_min_1Diagnostic results must be documented with evidence
WAITING_APPROVALquote_total, line_items, approval_link_sentQuote must be prepared and sent to the customer
QC_REVIEWqc_checklist_complete, verification_evidence_min_1, qc_outcomeQC must be completed with evidence and a pass/fail outcome

When a transition fails, the API returns one of the following error codes.

CodeMeaning
INVALID_TRANSITIONThe from-to transition is not in the state graph. For example, you cannot go directly from INTAKE to IN_REPAIR.
PERMISSION_DENIEDThe user’s role cannot move tickets to the target status. Check the permission matrix above.
GATE_NOT_METThe exit gate for the current status has unmet requirements. Complete the required fields before transitioning.
CONFLICTThe ticket’s current status does not match the expectedStatus parameter. This means another user changed the ticket since you last loaded it (optimistic concurrency check). Reload the ticket and try again.

All ticket status changes flow through a single code path:

  1. Client calls the transitionTicket server action with ticketId, newStatus, and expectedStatus.
  2. Server Action validates the user’s role and checks permissions.
  3. Postgres function transition_ticket() atomically validates the transition graph, checks gates, and updates the status.
  4. A ticket_events row is created to record the transition in the audit trail.
  5. Outbox events fire to trigger notifications (SMS, email, push) based on the new status.

This architecture ensures that no ticket can ever reach an invalid state, even under concurrent access.