Bookings & Operations
Visa pipeline
Visa requests move through a defined state machine: new inquiry → pending documents → embassy processing → approved/rejected → passport collected. Requests capture entry type (single/multiple entry, transit) sourced from a shared lookup table.
Daily Approved Visas & Passport Handover Manifest (A4 Printable)
When a visa application is approved by the consulate/embassy:
- Approval Timestamp (
approved_at): The backend records the exact timestamp of approval (approved_at = now()) when transitioning status toapproved. - Dynamic Visa Short Codes: Generates compact standardized codes dynamically from reference data (e.g.
IND-B-3M-M-S,UK-S-1Y-M-S,UAE-T-1M-S-E) capturing Country, Type, Validity, Entry Type, and Sticker/eVisa format. - A4 Landscape Printable Manifest: Formatted specifically for physical reception counters to capture client signatures during passport handover. Columns include Sequence Number, Customer Name, Traveler Name, Visa Code, Visa/Sticker Number, Handover Date, Staff Name, and Customer Signature box, complete with a formal custody acknowledgment clause.
- Automated Daily Email (20:00 Asia/Colombo): Fires every evening at 8:00 PM Sri Lanka time to dispatch an HTML summary and attached A4 PDF (
Approved_Visas_Handover_Manifest_YYYY-MM-DD.pdf) to agency managers and owners. - On-Demand API (
GET /api/v1/visas/daily-approved/pdf): Allows generating and streaming the A4 printable manifest for today or any past calendar date on-demand.
Rejected Visa Operational Lifecycle
When an embassy or consulate refuses a visa application:
- Status Transition: The application moves to
rejectedstatus. - Client Decision Notification: Staff can send an official rejection notification email directly to the customer containing the embassy remarks, assigned consultant contact details, and passport collection instructions.
- Passport Return Finalization: Staff click “Return Passport”, which transitions the status to
passport_collected, flagsis_visa_request_rejected = true, and records the completion timestamp (completed_at). Approval emails remain suppressed. - Visual Red Dot Indicator: On the Task Tracker, Admin Table, and Client Dossier, rejected applications whose passport has been collected display a distinct red dot indicator (
bg-red-600 ring-2 ring-red-200) and red status badges instead of the green checkmark icon. - Dossier & Active Services Visibility: In the customer’s Active Services panel, rejected applications are clearly badged in red as
REJECTEDalongsidePASSPORT RETURNED. They are strictly omitted from active held visas in the Passport Vault.
Flight bookings
Flight requests are created and tracked against a customer, moving through their own status lifecycle including issued tickets.
Ticket cancellation & reschedule
- Cancellation — staff can cancel an issued ticket with a manual cancellation fee, refund amount, and reason (a judgment call per booking, not a rules engine); the cancelled state is shown inline on the case.
- Reschedule — staff can change a ticketed booking’s flight date, with a reason field. The full change history (previous date, new date, who, when) is kept server-side.
Task tracker & Document Management
- Admins see an aggregated, filterable table of every ongoing case across the agency.
- Consultants see a Kanban board of their own assigned cases.
- Finalized Status Indicators & Strict Commercial Invariant:
- A case is only marked finalized (
is_finalised = truewith a green checkmark) when both operational fulfillment is complete AND all associated invoices (direct and group-linked) are fully settled (PAID). - Approved Visas: Display a green checkmark circle (
CheckCircle2) andFINALIZEDbadge when visa number is issued, passport collection is finalized (completed_attimestamp or statuspassport_collected), and all linked invoices are fully paid. - Rejected Visas: Display a solid red dot indicator and
Passport Returned (Rejected)badge whenis_visa_request_rejectedis true, passport collection is finalized, and any rejection settlement invoice is resolved. - Flights: Ticket number is issued (
ticketNumberis present), the booking is not cancelled, and all linked invoices are fully settled. - If an invoice is issued or updated without full settlement (unpaid/partial), the finalized status is automatically revoked until payment receipt is recorded.
- A case is only marked finalized (
- Task Detail Drawer:
- Anti-Flicker Drawer Loader: Opens with a unified loading state powered by concurrent fetches (
Promise.allSettled), avoiding UI jumps between “Issue Invoice” and “View Invoice”. - Contextual Document Checklist & Downloadable Templates: Displays both required checklist items and matched downloadable templates/forms from Staff Utilities (e.g. embassy visa forms, NOC templates, flight vouchers) with direct downloads formatted as
customer_name_visatype_doc_type_doc_name.ext.
- Anti-Flicker Drawer Loader: Opens with a unified loading state powered by concurrent fetches (
- Service Issuance & Update Workflows:
- Seamless Visa Issuance & Finalization: Moving a visa to
passport_collectedwithout a previously entered visa number directly surfaces an inline issue form with primary action “Issue Visa & Finalize (Passport Collected)”, uploading documents and finalizing in one atomic action. - Issue / Update Visa Flow: Staff enter visa numbers and dates while directly attaching finalized Visa PDF(s). Before any network upload, all required fields are validated. Existing uploaded documents are listed with file sizes, instant download, and Delete actions backed by styled React
ConfirmModaldialogs. - Issue / Update Ticket Flow: Staff enter ticket numbers and prices while attaching e-ticket PDFs. Existing documents are displayed directly in the drawer with download and delete controls.
- Permanent Purge on Request Deletion: Deleting a flight or visa request permanently purges all attached documents from Cloudflare R2 and deletes rows from PostgreSQL.
- All files uploaded via the drawer automatically link to the customer dossier and receive structured R2 keys.
- Seamless Visa Issuance & Finalization: Moving a visa to
Dashboard
The app serves a role-specific dashboard automatically on login — a high-level admin view for owners, an operational view for consultants. Core dashboard data is fetched once at login (not refetched on every tab switch), with a manual “Refresh” button on each consuming page.
Reference data
- Lookup values — a single generic table backs job titles, departments, branches, commission tiers, employment types, and visa entry types.
- Sequential codes — a row-locked counter table generates human-readable, prefix-based codes for employee IDs and quotation numbers.