Skip to main content

Customer Requests

A customer request is the inbox entry for "someone wants something done on this unit." It captures intent against a specific piece of equipment so the office can triage on its own schedule.

Request vs. work order

The difference is intentional and worth being precise about:

Customer RequestWork Order
PurposeCaptures intent — "AC is broken"Captures action — "Tech assigned, parts costed, visit scheduled"
Created byCustomer (via QR scan), or office (logging a phone call)Office or supervisor
Tied to a unit?Always — unit_id is requiredYes (one work order per unit)
Has a price?NoYes (line items)
Has a tech?NoYes (or queued for assignment)
Status setopen, ongoing, closedEight statuses (see Work Order Lifecycle)

The split exists because requests come in faster than they can be acted on. Treating every request as a half-built work order would clutter the dispatch queue with unprocessed noise. Keeping requests in their own queue means dispatch sees clean, triaged work.

How requests are created

A customer request is born one of two ways:

  1. QR scan — a customer scans a unit's QR code and submits the request form on the public unit page (/u/<guid>). The request is pre-tagged with that unit, and the form requires a description, a preferred date and time, and contact info.
  2. Manual entry — a phone call or email comes in, and the office logs it via Customer Requests → Add Request. The same fields are required, plus the office picks the unit from a search.

There is no generic "request service" web form — TuffOps only opens a public intake when there's a QR-tagged unit to attach the request to. That keeps every request anchored to a specific piece of equipment, which is what makes triage tractable.

Required fields, in both paths:

  • unit_id (set automatically from the QR GUID, or picked by the office)
  • request (the customer's description, up to 2000 characters)
  • schedule_at (preferred date)
  • schedule_time (All Day, Morning, or Afternoon)
  • contact_info (free-text phone or email — kept as a string so the customer can write whatever's easiest)

The three statuses

StatusMeaning
openNew, not yet looked at.
ongoingThe office is actively triaging it (or a work order has been spawned).
closedTriaged. Either resolved without dispatch or converted to a work order.

Closing a request is final — it doesn't reopen. If the same problem comes back, it's a new request.

The triage flow

Triage is the bridge between intent and action. The office runs through the open queue and decides, for each request, one of three outcomes:

  1. Convert to a work order. The request becomes a dispatched job. The work order picks up the request text in its customer_requests field and the source unit. The request flips to closed automatically as part of the conversion.
  2. Close as resolved. Sometimes a request gets answered by a phone call ("turn off the breaker, then back on") and no truck-roll is needed. The office sets the status dropdown to closed and saves. There's no separate "Close" button — closing is just a status change, with an internal note added if needed.
  3. Leave open or move to ongoing. If the request needs more info (the description is unclear, the customer hasn't been reached), the office adds notes and either leaves the status at open or moves it to ongoing while they chase the missing details.

Triage is the most-skipped concept by new TuffOps users — they tend to either treat every request as a work order (overdispatch) or ignore them (drop the ball). The middle path is the right one.

Verified vs. unverified contacts

The customer for a request comes from the unit it's attached to — every request has a unit, every unit has at most one customer. The contact_info field on the request is a free string for the person the technician should call back, which may or may not be the customer-of-record (a tenant calling about their landlord's equipment, an on-site facilities manager rather than the building owner, etc.).

To help the office tell those apart, TuffOps shows a Verified badge on the request edit page when the contact_info value matches a phone or email already on the unit's customer record:

  • Phone matching is normalized — (340) 555-1212 matches 3405551212.
  • Email matching is case-insensitive.
  • Anything else shows as Unverified, which is a useful signal that the technician should confirm identity on the call.

The badge is informational; it doesn't change permissions or routing.

Why requests don't carry prices

A request is a signal, not a contract. Pricing happens during triage when the office decides what items are needed and what labor codes apply. Putting prices on requests would either anchor expectations prematurely (the customer "knew" the price before the office saw the equipment) or invite disagreements when the actual work scope diverges from the request description.

If the customer wants a price up front, that's a quotation, not a request. See Quotation Lifecycle.