← All manuals Operator Guide for this screen IM2

Rush Material Request — Technical Spec

Handheld — Rush Material Request
Technical Spec Ver 4 Updated 2026-09-06 Matches the live screen

Rush Material Request — Technical Spec

app/rush.py, templates ro_rush.html. Mounted before ro_router, same reason as ro_import.py (literal /ro/rush must not fall into ro.py's catch-alls).

Routes

What gets written

One ro_header row:

ColumnValue
job_nameThe tapped match's name, or the raw typed/dictated text if nothing matched
bom_nameGenerated: Rush <UTC timestamp> #<6 hex> — see "Open questions"
ro_type'Service' — hardcoded, see "Open questions"
source_system'FP' if a FieldPulse job was matched, else 'MANUAL'
source_id / fp_job_idSet only when source_system = 'FP'
entry_source'Rush' — new column, see ddl/rush_ro.sql
priority_code'R' — always, this is the only path in the app that writes it besides the new Workbench toggle
notesThe optional Note field, or NULL
ro_type valueRUSH_RO_TYPE = 'Service'
created_byThe submitting user's username

One ro_detail row per line, origin = 'Manual', line_no in submission order. A line whose SKU was accepted (matched and re-validated server-side against the item master) is INV; every other line — non-stock, or a SKU that failed server-side validation — is NONINV, with a ro_issue ('SKU not in QB') raised on the latter case only, mirroring /ro/new's existing fallback. suggested_vendor carries the per-line vendor hint verbatim. Duplicate SKUs within one submission are merged (quantities summed) before insert — ro_detail_order_sku_uniq allows a SKU only once per order.

One ro_audit row on the header (action = 'rush_create', field priority_code, new value R) noting line count and whether the job match was confirmed by a tap or left as the automatic guess. Plus, per line, one extra ro_audit row (field = 'description') whenever the tech's dictated words (said) differ from the description actually stored — tapping a SKU replaces the box with the catalog description, and the tech's own words have to survive in the trail (Dave, 2026-09-05). [Ver 2, 2026-09-06]

Never written by this screen: any cost field, any QuickBooks call, any PO object. Rule 0 of the brief.

Payload shape (POST /ro/rush)

{ "job_name": "Ernest Gabriel — 4162 Durham", "job_source": "FP", "job_source_id": "4548", "fp_job_id": 918822, "job_guessed": false, "note": "", "lines": [ {"description": "20 ft of 10-3 MC cable", "qty": 20, "sku": "51310", "non_stock": false, "sku_guessed": true, "uom": "FT", "vendor_hint": "Elliott", "said": "twenty feet of ten three MC"} ] }

Validation: job_name required (400), at least one line (400), per line a non-blank description and a numeric qty > 0 (400 naming the line). uom defaults to the matched item's UOM, else EA.

job_guessed / sku_guessed are read-back state only — the server never trusts sku blindly regardless of these flags (see lookup_item() re-validation above).

Notifications

app/notify.py: notify_slack(), notify_sms(), notify_rush() (assembler), notify_release() (written, not called — see its own docstring). Fired after the RO transaction commits, wrapped in try/except in rush.py's route handler — a notify failure can never roll back or fail the request. Config via env (RUSH_SLACK_WEBHOOK_URL, CLICKSEND_USERNAME, CLICKSEND_API_KEY, CLICKSEND_SENDER_NUMBER) — unset means a logged warning, not an error.

Open questions for Viktor/Dave (see the handoff README for the numbered list)

Alert delivery is now recorded (added 2026-09-06)

notify.notify_rush() returns {"slack": …, "sms": …} where each value is True (delivered), False (tried and failed, including missing configuration) or None (switched off in System Controls). rush.py writes that outcome to ro_audit as action rush_notify and, if either channel failed, appends a warning to the operator's confirmation: the request is saved but the office was not alerted. Before this, a missing webhook or missing credentials meant the request was filed and nobody was told, with nothing on the RO to show it.

CLICKSEND_USERNAME / CLICKSEND_API_KEY / CLICKSEND_SENDER_NUMBER are now set in /opt/im2/env, so SMS works as soon as Text rush alerts is switched on and at least one rush contact is active. RUSH_SLACK_WEBHOOK_URL is still unset — Slack alerts are switched on but every one of them is dropped and now audited as "not delivered" until someone creates an Incoming Webhook for the channel.