Scanning
/dashboard/scan is the universal entry point. Hand-held scanners and built-in cameras both work. The page accepts any barcode generated by the system and routes accordingly.
Resolution flow
When a barcode is scanned, the dashboard:
- Decodes the Code 128 payload to a UUID
- Looks the UUID up in
inventory.rolls,inventory.offcuts, andjobs(parallel queries) - Routes to the matching entity’s screen
- If no match, shows “Barcode not recognized” with the raw decoded value
A roll → /dashboard/inventory/rolls/[id]. A job → /dashboard/jobs/[id]. An offcut → /dashboard/inventory/offcuts/[id].
Workflow shortcuts
The scan page also accepts two-step scans for common workflows:
| First scan | Second scan | Action |
|---|---|---|
| Job | Roll | Assign that roll to that job |
| Job | Offcut | Assign that offcut to that job |
| Job | (no second) | Open job detail (default) |
| Cut session | Part barcode | Mark that part as cut |
| Cut session | (timeout) | Auto-close the session |
The “cut session” mode is entered when an operator opens a committed cut from the cut list. From that point, every subsequent scan marks a part scanned-out until the session times out (30 seconds idle) or the operator presses Done.
Hardware
Any USB or Bluetooth Code 128 scanner works. Recommended:
- Zebra DS22 corded (USB, ~$120)
- Honeywell Voyager 1450g (USB, ~$90)
- Socket Mobile 7Ci (Bluetooth, ~$200, useful for moving operators)
For phone/tablet scanning, the dashboard exposes /dashboard/scan?camera=1 which uses the device camera. Less reliable than a dedicated scanner — fine for spot checks, not for production volume.
Scanner timing matters. If the operator double-scans (same barcode within 250 ms), the dashboard treats it as a single scan to avoid duplicate state changes.
Audit
Every scan event writes to audit_log with:
- The decoded UUID
- The action taken (if a state change resulted)
- The operator’s user ID
- IP address + user agent
Scans that don’t result in state changes (e.g., looking up a roll without assigning it) still log, with action = "lookup".