# 05 — Roadmap (Phases 2–5)

Continues from `04-early-pages.md` (Phase 1). Each phase ends with a manual QA pass and a commit
— matching the established preference for sequential, task-by-task builds with a commit per
completed task, confirming on consequential forks along the way.

## Phase 2 — Patient-facing booking & payment

- [ ] `clinic_patient_profiles` migration + `PatientProfile` model (`models/PatientProfile.md`)
- [ ] `Site\Clinic\PatientProfileController` — medical-history form (history/surgical/medication/allergies)
- [ ] `clinic_bookings` migration + `Booking` model (`models/Booking.md`)
- [ ] `Site\Clinic\SearchController` — specialty + branch filter, matching doctors via `clinic_doctor_branch`
- [ ] `Site\Clinic\DoctorProfileController` — public doctor/clinic page
- [ ] `BookingService::availableSlots()` — reads `clinic_doctor_schedules` + existing `clinic_bookings` to compute open slots
- [ ] `Site\Clinic\BookingController` — create booking (visit or online), enforce slot availability
- [ ] `clinic_payments` migration + `Payment` model (`models/Payment.md`)
- [ ] `Site\Clinic\BookingPaymentController` — wraps `PaymentGatewayManager`, see `flows/03-payment-flow.md`
- [ ] `Site\Clinic\MyBookingController` — list/cancel/reschedule within the configured policy window
- [ ] Cancellation/reschedule policy read from `clinic.policies.*` (Super Admin defaults, per-clinic override optional)
- [ ] Admin-side `Admin\Clinic\BookingController` (Clinic Admin/Receptionist: view/confirm/cancel, branch-scoped)
- [ ] Admin-side `Admin\Clinic\PatientController` (booking-linked patient list, no medical fields — see `03-permissions-and-roles.md` §4)

**Definition of done**: a patient can complete their medical profile, search a doctor by
specialty+branch, book a clinic visit, pay, and see it in "My Bookings"; the booking is visible
to the right Clinic Admin/Receptionist (branch-scoped) and the right Doctor.

## Phase 3 — Doctor portal

- [ ] `doctor` guard + `clinic_doctors` provider in `config/auth.php`
- [ ] `EnsureDoctorActive` middleware (copy of `EnsureEmployeeActive`), alias in `bootstrap/app.php`
- [ ] `routes/doctor.php` (copy of `routes/portal.php`'s structure), required from `routes/web.php`
- [ ] `Doctor\Auth\AuthenticatedSessionController`, `resources/views/doctor/layouts/app.blade.php` + `auth/login.blade.php`
- [ ] `Doctor\DashboardController`, `Doctor\ScheduleController` — today's/upcoming bookings across all their branches
- [ ] `Doctor\PatientController` — read patient basic data + `clinic_patient_profiles` medical history for their own patients only
- [ ] `clinic_medical_records` migration + `MedicalRecord` model (`models/MedicalRecord.md`)
- [ ] `Doctor\VisitController` — record diagnosis/prescription/report; edits after publish logged to `ActivityLog` with a "notify patient" side-effect (via `NotificationService`)
- [ ] `Site\Clinic\MedicalRecordController` — patient reads their own prescriptions/reports

**Definition of done**: a doctor logs into their own portal, sees only their bookings/patients,
records a diagnosis+prescription+report for a completed visit, edits it later (patient gets
notified), and the patient can read it from their account.

## Phase 4 — Chat, Reviews, Reports, Offers

- [ ] Add `laravel/reverb`, configure `BROADCAST_CONNECTION=reverb`
- [ ] `clinic_chat_messages` migration + `ChatMessage` model (`models/ChatMessage.md`)
- [ ] `ChatService` + a `NewClinicChatMessage` broadcast event; `Doctor\ChatController` + `Site\Clinic\ChatController`
- [ ] `clinic_reviews` migration + `Review` model (`models/Review.md`)
- [ ] `Site\Clinic\ReviewController` — two-step rating shown after a booking's status becomes `completed`
- [ ] Recompute `clinic_profiles.avg_rating` (and a doctor-level average) on new review — via `ReviewService`, matching how other computed aggregates are handled in this codebase (check for an existing precedent, e.g. anything recalculated in `Sales`/`Finance` on save, before inventing a new pattern)
- [ ] `Admin\Clinic\Reports\ClinicReportController` — bookings/revenue/performance/ratings, filterable by branch+period, mirrors the shape of existing Finance/HR report controllers
- [ ] `clinic_offers` migration + `Offer` model (`models/Offer.md`); `Admin\Clinic\OfferController` (Super Admin: platform-wide; Clinic Admin: own-branch only, enforced by the same branch scope)

**Definition of done**: doctor and patient can message each other in near-real-time; a patient
rates the doctor then the clinic after a completed booking, both averages update; Super Admin and
Clinic Admin each see the reports and offers relevant to their scope.

## Phase 5 — Mobile API + Video Consultations

- [ ] Add `laravel/sanctum`, publish config, add `routes/api.php`, register in `bootstrap/app.php`
- [ ] `Api\Clinic\*` controllers mirroring `Site\Clinic\*` + `Doctor\*` as JSON endpoints, token-authenticated
- [ ] Agora account/project set up (outside this codebase); a small `AgoraTokenService` generating join tokens per `clinic_bookings.id` (channel name) + role (doctor/patient)
- [ ] `Doctor\ConsultationController` + `Api\Clinic\ConsultationController` — issue Agora token, mark booking as "in progress" / "completed"
- [ ] Push notifications for booking confirmations/reminders (FCM) — new dependency, evaluate against the existing `NotificationService` pattern (likely a new delivery channel on top of the same service, not a replacement)

**Definition of done**: the mobile app can authenticate, search/book/pay, and join a live Agora
video consultation with the doctor at the scheduled time; push notifications fire for booking
confirmation and a pre-appointment reminder.

## Cross-cutting, do throughout (not a separate phase)

- Every new admin screen: sidebar entry + `permission:` middleware + Spatie permission seeded (per `03-permissions-and-roles.md`).
- Every new table: audit columns (`created_by`/`updated_by`) where the ERP convention has them.
- Every sensitive medical field: never selected/loaded outside Doctor/Patient-facing code paths (see `03-permissions-and-roles.md` §4) — treat this as a review checklist item on every PR touching `clinic_medical_records` or `clinic_patient_profiles`.
