Requests
Written April 2026 — read this first
Still broadly right. Request lists page and search in the database, and a partner request must reference one of that partner's own customers or bookings (PTR-051). Complaints as tracked cases (CX-002) are not built.
Staff-facing triage queue for customer-initiated requests — document uploads, group interest enquiries, and booking-change requests that originate from the customer or agent portals.
Scope
These are customer requests (CustomerRequest model), not HR leave requests, approval queue items, or internal tickets. For ops approval queue see docs/features/approvals.md.
Pages
src/pages/requests/Requests.tsx— queue + detail dialog at/requests.src/pages/requests/requestsMath.ts/requestsMath.test.ts— filter/assignee helpers (pure functions).
Route (src/App.tsx:178):
<Route path="/requests"
element={<ProtectedRoute requiredPermissions={['requests.view']}>
<Requests />
</ProtectedRoute>} />
What kind of requests
From the CustomerRequest.type discriminator (inferred from code and the group_interest filter at Requests.tsx:45):
| Type | Origin | Typical content |
|---|---|---|
group_interest |
Customer or agent portal | "I'd like info on Group X" — optional requested amount, group link |
| Document upload (passport, photo, Aadhaar) | Customer portal | Files attached; ops confirms + stores against the customer record |
| Booking change | Customer portal | Requested mods against an existing booking |
| General enquiry | Any portal | Free-text request, may be converted to a lead |
Each row carries: title, description, status, priority, assignee, requested amount + currency, due date, linked customer / group / booking, notes, attachments.
Workflow
- Submitted from the portal (
POST /portals/customer/requests/neworPOST /portals/agent/requests,src/lib/api.ts:27850+). - Lands in
/requestswith statusopenorsubmitted. - Ops triages:
- Update fields via
PATCH /requests/:id— title, description, status, priority,assignedToId, requested amount, currency, due date. (requests.edit) - Add note via
POST /requests/:id/notes. (requests.edit) - Open attachments — the files a customer sent with a request are on the company Shared Drive (Customers / the customer / Requests); each opens in a viewer on the page through
drive-file(requests.view, ACC-074). - Upload attachments (staff) is not built: the screen offers it, but there is no
/requests/:id/attachmentsroute, so the upload fails. A customer adds files from the portal. - Call / Email —
tel:andmailto:links rendered inline from the customer's phone/email. - Convert to either a
Lead(convertRequestToLead) or aBooking(convertRequestToBooking— opens a mini wizard asking for booking no., group, amount, currency, payment policy).
Status vocabulary (Requests.tsx:33):
| Status | Badge variant |
|---|---|
open |
secondary |
submitted |
default |
approved |
default |
rejected |
destructive |
closed |
outline |
Priority is free-text but the UI defaults to medium.
Sidebar badge
The request count rolls up to the sidebar so the ops team sees the backlog — see HelpBanner copy at Requests.tsx:259.
The list
Search (the request's title, description and the customer's message — not the customer's or the group's name), type (all, group interests), status, a Created date range and a sort (created, last updated, status, title), all in the database and kept in the page address (UX-030). The paging bar under the list shows rows per page (25, 50 or 100), which requests are on screen out of how many ("1–25 of 312") and first, previous, next and last page — even when they all fit on one page (UX-030).
API endpoints
Implemented in src/lib/api.ts:20112+:
| Method | Path | Permission |
|---|---|---|
| GET | /requests |
requests.view (via route) |
| PATCH | /requests/:id |
requests.edit (api.ts:20119) |
| POST | /requests/:id/notes |
requests.edit (api.ts:20144) |
| POST | /portals/customer/requests/new |
Portal-scoped (customer owner) |
| POST | /portals/agent/requests |
Portal-scoped (agent owner) |
Permissions
| Action | Permission | Source |
|---|---|---|
View /requests |
requests.view |
Route guard |
| Edit fields / add note | requests.edit |
Server |
| Create (ops-facing) | requests.create |
Server — the UI does not currently expose an ops-side "new request" button; portals use their dedicated endpoints |
| Open an attachment | requests.view (or the customer who uploaded it) |
drive-file |
| Upload attachments (staff) | — | Not built: no route exists |
| Convert to lead | leads.edit (downstream) |
Server-side when convertRequestToLead() creates the lead |
| Convert to booking | bookings.create (downstream) |
Server-side when convertRequestToBooking() creates the booking |
Related
- Customer portal submission forms → portal docs (
src/pages/customer/). - Agent portal submission → partner docs (
src/pages/partner/). - Leads conversion →
docs/features/leads.md. - Booking creation from request →
docs/features/booking-wizard.md.