# 09 — Roadmap (Phase 6–13): Medical Center Expansion

Continues from `05-roadmap.md` (Phase 2–5) without renumbering it — Phase 5 (mobile API + Agora
video) stays reserved whether or not it's built before this track starts. 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/financial forks along the
way (see the repo's own build-workflow convention).

## Phase 6 — Structured Clinical Core (EMR)

- [ ] `clinic_encounters` migration + `Encounter` model (`models/Encounter.md`)
- [ ] `clinic_vitals` migration + `Vital` model (`models/Vital.md`), BMI computed on save
- [ ] `clinic_diagnoses` migration + `Diagnosis` model (`models/Diagnosis.md`)
- [ ] `EncounterService` (new, `app/Services/Clinic/EncounterService.php`) — create/finalize an encounter, attach vitals, attach diagnoses; extends the existing `MedicalRecordService` pattern rather than duplicating it
- [ ] Rebuild `resources/views/doctor/visits/edit.blade.php` (currently two plain `<textarea>` fields) into structured sections: vitals inputs, chief complaint/history/exam/assessment/plan fields, active problem list — see `flows/08-clinical-documentation-flow.md`
- [ ] Keep `Doctor\VisitController::store()/update()` writing to the old `clinic_medical_records` row too (dual-write) **only if** existing patient-facing "My Medical Records" screens still read from it — otherwise cut over `Site\Clinic\MedicalRecordController` to read `clinic_encounters` directly and stop writing the old table for new visits

**Definition of done**: a doctor records a structured encounter (vitals + chief complaint +
assessment/plan + at least one diagnosis) for a visit; the patient can still read their record via
the existing patient portal; a weight/BP/glucose trend for one patient can be pulled from
`clinic_vitals` with a plain query (proves the data is actually structured, not just re-labeled
text boxes).

## Phase 7 — Specialty Modules

- [ ] `clinic_diabetes_screenings` migration + model (`models/DiabetesScreening.md`)
- [ ] `clinic_bariatric_assessments` migration + model (`models/BariatricAssessment.md`)
- [ ] `clinic_nutrition_plans` migration + model (`models/NutritionPlan.md`)
- [ ] Seed a "Therapeutic Nutrition" row into `clinic_specialties` (no code change needed beyond a seeder entry — `Doctor`/`Specialty` already support this)
- [ ] Add tabs to the encounter screen (Diabetes Screening / Bariatric Assessment / Nutrition Plan), shown conditionally based on the doctor's own specialty or explicit user action — not forced on every visit
- [ ] Weight/BMI trend view on the patient's clinical summary (reads `clinic_vitals`, no new table)
- [ ] HbA1c/glucose trend view (reads `clinic_lab_results` — **stub with manual entry until Phase 9 ships**, or build Phase 9 first if diabetes trending is the priority; note the dependency explicitly when scheduling)

**Definition of done**: for a patient flagged as diabetic, a doctor completes a complications
screening and it's visible on the patient's chart; for a bariatric-surgery candidate, a doctor
records a structured assessment including proposed procedure type; a nutrition follow-up records a
calorie target and diet type.

## Phase 8 — Pharmacy & e-Prescriptions

- [ ] `clinic_medications` migration + model (`models/Medication.md`), seed a starter drug list
- [ ] `clinic_prescriptions` + `clinic_prescription_items` migrations + models (`models/Prescription.md`)
- [ ] `PrescriptionService` (new) — create a prescription from an encounter, add/remove line items
- [ ] Prescription section on the doctor's encounter screen — same cascading-picker AJAX pattern as `resources/views/dashboard/admin/clinic/schedules/index.blade.php` (pick medication → dose/frequency/duration fields appear)
- [ ] `Site\Clinic\MedicalRecordController` (or a new `PrescriptionController`) — patient reads their structured prescriptions, not just the old free-text field

**Definition of done**: a doctor writes a prescription with at least one structured line item
(medication + dose + frequency + duration); the patient can see it in their portal; **no**
inventory table is touched anywhere in this phase (verify by grep — no `Inventory\*` reference
should appear in any new file).

## Phase 9 — Lab & Radiology Orders

- [ ] `clinic_lab_test_catalog` migration + model, seeded with HbA1c, Fasting Glucose, Lipid Profile, TSH/T3/T4, Creatinine/eGFR, Microalbumin (`models/LabOrder.md`)
- [ ] `clinic_lab_orders` + `clinic_lab_results` migrations + models (`models/LabOrder.md`)
- [ ] `LabOrderService` (new) — create an order with one or more requested tests from an encounter; enter results against an order (manual entry, no device integration)
- [ ] Result entry flags each value normal/high/low against the catalog's reference range
- [ ] Wire the Phase 7 HbA1c/glucose trend view to real `clinic_lab_results` data

**Definition of done**: a doctor orders a lab panel from an encounter, later enters the results,
and the values feed the diabetes/lipid trend view built in Phase 7 without further code changes to
that view.

## Phase 10 — Surgery Scheduling & Documentation

- [ ] `clinic_surgery_cases` migration + model (`models/SurgeryCase.md`)
- [ ] `clinic_surgery_preop_assessments` migration + model (`models/SurgeryCase.md`, same file)
- [ ] Add `surgery_case_id` (nullable FK) to `clinic_encounters` for the post-op note link
- [ ] `SurgeryCaseService` (new) — schedule a case, record the pre-op assessment/consent, mark completed
- [ ] "Surgery Schedule" admin screen — same list/calendar-by-date pattern as the existing Doctor Schedules picker screen (`resources/views/dashboard/admin/clinic/schedules/index.blade.php`)
- [ ] Post-op documentation reuses the Phase 6 encounter screen with `encounter_type = post_op`, linked via `surgery_case_id` — no separate screen built

**Definition of done**: a surgery case is scheduled with a surgeon and date; a pre-op checklist +
consent is recorded before the case can be marked completed; a post-op note exists as a linked
encounter. No bed/room field exists anywhere in the new schema (verify against
`06-overview-medical-center-expansion.md`'s explicit no-admissions decision).

## Phase 11 — Finance Integration

- [ ] `ClinicPatientCustomerProvisioningService` (new, `app/Services/Clinic/Finance/`) — finds or creates a `Sales\Customer` for a patient's `User`, following the same construction `CustomerService::create()` uses
- [ ] `clinic_invoices` + `clinic_invoice_items` migrations + models (`models/ClinicInvoice.md`)
- [ ] Auto-create a draft `clinic_invoices` row when a booking is confirmed / an encounter with billable items (consultation, procedure, surgery, lab test) is finalized
- [ ] Settings keys added via the existing `SettingService` UI: `clinic_journal_id`, `default_clinic_ar_account_id`, `default_clinic_revenue_account_id` (same gating pattern as `sales_journal_id` — throws if unset when an invoice is posted)
- [ ] `ClinicPostingService` (new, `app/Services/Clinic/Finance/`) — mirrors `SalesPostingService::postInvoice()` exactly: resolve AR account, resolve revenue account per line (item-level → Setting default → throw), build balanced lines, `JournalEntryService::create()` + `JournalPostingService::post()`, update `clinic_invoices.journal_entry_id`/`status`/`posted_at`
- [ ] Migration: add nullable `clinic_invoice_id` FK to `finance_receipt_vouchers`
- [ ] Update `ReceiptVoucherPostingService::post()` — if `clinic_invoice_id` is set, update that invoice's `paid_amount`/`payment_status` after the voucher posts
- [ ] Receipt Voucher creation flow triggered from the invoice screen (nudges the user toward `clinic_invoice_id` instead of the old free-text `invoice_reference`)
- [ ] Manually create Revenue/AR accounts for the clinic in the existing chart-of-accounts screen (no seeder — confirmed none exists in this project)

**Definition of done**: booking → completed visit → auto-drafted clinic invoice → posted invoice
(journal entry balanced, visible on the trial balance) → receipt voucher for the payment → voucher
posted → invoice's `paid_amount`/`payment_status` updates automatically. This is the single
highest-risk phase — test end to end on a non-production database before considering it done.

## Phase 12 — Print & Document Center

- [ ] Confirm whether a PDF library (`dompdf`/`mpdf`/similar) already exists in `composer.json` before adding one; if none, default to browser print (`window.print()` + a print stylesheet) for the first cut
- [ ] Prescription print view (from `clinic_prescriptions`)
- [ ] Lab order print view (from `clinic_lab_orders`)
- [ ] Invoice/receipt print view (from `clinic_invoices` + linked `ReceiptVoucher`)
- [ ] Surgical consent print view (from `clinic_surgery_preop_assessments`)
- [ ] Medical summary report print view (from `clinic_encounters` + `clinic_diagnoses`, patient-level)

**Definition of done**: each of the five documents above can be generated and printed from its
respective screen; A4 layout, clinic branding (reuse `clinic_profiles.logo`), no broken layout in
print preview.

## Phase 13 — Specialty Reporting & Analytics

- [ ] Extend `app/Services/Clinic/Reports/ClinicReportService.php` with: diabetes-control rate (% of diabetic patients with latest HbA1c within target), average weight-loss trend for bariatric patients, surgical case volume by month/procedure, revenue by specialty (depends on Phase 11's per-line revenue accounts)
- [ ] Corresponding sections on `Admin\Clinic\Reports\ClinicReportController` / its view, filterable by branch + period, matching the shape of existing Finance/HR report screens

**Definition of done**: each new report renders real numbers from Phase 6–11 data on the existing
Clinic Reports screen, filterable the same way the existing bookings/revenue reports already are.

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

- Every new admin/doctor screen: sidebar entry (admin side only — doctor portal has its own nav) + `permission:` middleware where applicable + Spatie permission seeded, per `08-permissions-and-roles-expansion.md`.
- Every new table: `created_by`/`updated_by` where the ERP convention has them (see `07-database-schema-expansion.md`).
- Every clinical table (`clinic_encounters`, `clinic_vitals`, `clinic_diagnoses`, the three specialty tables, `clinic_prescriptions`, `clinic_lab_orders`/`results`): never selected/loaded outside Doctor/Patient-facing code paths — treat as a review checklist item on every PR touching them, exactly as `05-roadmap.md` already mandates for `clinic_medical_records`/`clinic_patient_profiles`.
- Phase 11 specifically: never bypass `ClinicPostingService`/`ReceiptVoucherPostingService` to hand-write a journal entry — every clinic financial document posts through the same pipeline Sales uses, so the trial balance stays trustworthy.
