Appointments
A booked consultation between a patient and a specialist — from the moment of booking through the end of the session, with forms, video, and documentation all tied together.
What this enables
- A patient books an appointment through the public booking page (no account required at booking time)
- The specialist or admin onboards the patient afterward — creating their account and generating the required forms
- The appointment moves through a clear lifecycle: booked → upcoming → confirmed → in-progress → done
- A video call room opens automatically when the appointment is onboarded — no manual setup
- Patients and specialists can review and complete all forms tied to the appointment in one place
- After completion, patients can leave a star rating — low ratings trigger an alert for the admin to review
- Appointment history is permanent and soft-deletable only — clinical records are never erased
How it works
The two-phase booking model
Booking and patient onboarding are intentionally separate:
Phase 1 — Public booking (no login required)
Patient picks a time and fills in name, email, phone
→ patient_persons record created with name and phone
→ Appointment created with status: booked
→ contact_email stored for confirmation notification
Phase 2 — Onboarding (admin or specialist)
Staff opens the booking and registers the patient
→ Clerk account created (if not existing)
→ patient_persons.user_id linked to the new account
→ Patient record (org-patient link) created
→ Required forms generated automatically, pre-filled from patient_persons profile
→ Video room created
→ Status: booked → upcomingThis design lets clinics accept bookings from people who don't yet have an account, which is the most common real-world situation.
Lifecycle at a glance
| Status | What it means |
|---|---|
booked | Booking confirmed, contact info captured, no patient account yet |
upcoming | Patient onboarded, forms ready, video room active |
confirmed | Patient confirmed they'll attend |
inprogress | Specialist has opened the session |
done | Session complete, forms signed |
cancelled | Appointment cancelled |
noshow | Patient didn't attend |
Forms on appointments
Forms come from two sources and are merged automatically:
- Service forms — defined on the service being booked (intrinsic to the procedure)
- Calendar forms — additional forms specific to the booking channel (e.g., a promotional disclaimer)
Form types that can exist on an appointment: surveys, disclaimers, parameters, analysis, advice, report, prescription.
Reviews
After an appointment is done, the patient can submit a rating (1–5 stars) and optional comment. Ratings below 5 trigger an alert in the org dashboard. Admins acknowledge the alert after reviewing.
Technical Reference
Everything below is intended for developers.
Key schema additions
Service & Calendar references:
service_id(UUID) — always set; defines what was bookedcalendar_id(UUID, nullable) — which calendar was used (NULLfor direct registrations)
Contact info (pre-onboarding):
contact_email— stored for booking confirmation emails before the patient has an accountbooking_client_id— anonymous client ID used for rate limitingcontact_nameandcontact_phoneare not stored here — they live onpatient_persons, created at booking time
Add-ons:
additional_service_ids(UUID[]) — services added during appointmentadditional_product_ids(UUID[]) — physical products sold
Multi-session plans:
patient_service_plan_id(bigint, nullable) — links to enrolled service planplan_session_number(int) — "Session 3 of 10"
Status machine
State transitions have validation and side effects:
| Transition | Side effects |
|---|---|
booked → upcoming | Create patient + user (if new), generate forms, create Daily.co room |
upcoming → confirmed | Notify specialist |
any → cancelled / noshow | Delete Daily.co room |
reinstated from cancelled/noshow | Recreate Daily.co room |
See Lifecycle → for the full state machine with all validations.
Videocall integration
- Room name format:
restartix-{orgID}-{appointmentID} - Expires at
appointment.ended_at - Deleted automatically on cancellation or noshow
- Recreated on reinstatement
See Videocall → for Daily.co integration details.
Calendar views
- Month view: aggregate appointment counts per day
- Week view: full appointment details with time slots
- Filtering: by specialist, status, date range
- RLS applied: patients see own appointments, specialists see assigned, admins see all
Forms generation on onboarding
1. Collect service_forms WHERE service_id = appointment.service_id
2. Collect calendar_forms WHERE calendar_id = appointment.calendar_id
3. Merge and deduplicate
4. Generate form instances with snapshotted fields and auto-fill from patient profilePatient identity on appointments
Appointments reference patient_person_id (not user_id). This supports:
- Patients without accounts — a daughter booking for her elderly father who has no login
- Family management — one login managing appointments for multiple people
The RLS helper current_user_patient_person_ids() returns all patient person IDs the current user can act on behalf of (themselves + managed dependents), so patients and their managers can see the appointments they're involved in.
Access control
Patients can only see their own appointments (and those of anyone they manage). Specialists see appointments assigned to them. Admins see all appointments in their org. Enforced by RLS.