Feature list for the dental version of the patient Personal Web App (PWA) —
the patient portal currently shipped with the GP booking app, to be reused
and reworked for the dental app (dental_booking_app,veripath_dentalDB).
Target market: town and village community dental surgeries (UK).
Status: DRAFT — awaiting user review (2026-08-22). Once approved, this
page becomes the instruction pack for OpenCode.
patient-portal-pwa) as the base;dental_fp17claim). VERIFY it can serveCustomUser/patient chart modelDentalRecallRule + NICE recall engine + DentalScheduleBlockdental_dentalclinicalnote — VERIFY treatment-plan data can bedental_dentalclinicalnote — VERIFY safedental_dentaltransaction (Stripe) — VERIFY deposit/waiverPatientImage-style model — VERIFY and confirm PII-safe storage.NHS flow (EPS):
clinical_data/integrations/eps_fhir.py) → NHS Spine validateseps_fhir.py accepts the GDC number viaprofessional_registration_number; Dental Practitioners' Formulary (DPF)PrescriptionDispenseLedger (ISSUED → VIEWED →Private flow (no Spine):
NHS_NOTIFY/ReminderLog exist on the backend —ai_priority_score emergency routing.| # | Dependency | Status (verified 2026-08-22) |
|---|---|---|
| 1 | dental_fp17claim banding → patient-facing cost info |
✅ EXISTS — FP17Claim model + dental/fp17.py::get_band_charge() with NHS_BAND_CHARGES (1: £26.80, 2: £73.50, 3: £319.10). Can serve cost up front. |
| 2 | Household/family linking (none exists) | 🔴 NEW BUILD — confirmed, no linking model anywhere in the dental repo. |
| 3 | DentalRecallRule + NICE recall engine + DentalScheduleBlock |
✅ ALL EXIST — DentalRecallRule (NICE intervals 3–24mo), dental/recall.py (get_due_recalls()), DentalScheduleBlock + dental/slots.py slot engine, Celery recall notification tasks. |
| 4 | Emergency-slot-management module | ⚠️ PARTIAL — is_emergency flag on DentalAppointmentCategory + suggest_best_slot() in dental/slots.py. No dedicated patient-facing emergency request module — build it. |
| 5 | Digital intake + medical-history-verification modules | ⚠️ PARTIAL — medical_history_view (session-confirm flag) exists; no patient-facing intake form and no structured allergies/medications/conditions model — build it. |
| 6 | dental_dentalclinicalnote tooth-level read-only data |
✅ EXISTS — DentalClinicalNote.tooth_map (FDI) + surface_charting; PatientDentalClinicalNoteViewSet (read-only) already in the portal. |
| 7 | dental_dentaltransaction (Stripe) deposit/waiver/balance |
✅ EXISTS — DentalTransaction (deposit_paid, payment_status, stripe_payment_intent_id) + dental/payment.py (create_payment_intent, confirm_deposit, handle_webhook_event). Balance = total − deposit_paid. |
| 8 | PatientImage-style upload, PII-safe |
⚠️ EXISTS with caveat — clinical_data.PatientImage uses a local FileField → MEDIA_ROOT (NOT MinIO). Dental radiographs already use MinIO. For PII-safe patient uploads, follow the radiograph pattern (MinIO + authenticated proxy). |
| 9 | PrescriptionDispenseLedger usable from dental sector DB |
🔴 MISSING — the ledger model exists only in gp_booking_app/patient_portal. The dental repo's patient_portal has only Conversation/Message/PushSubscription. clinical_data.Prescription (dental repo) has status DRAFT/ISSUED/CANCELLED/DISPENSED/EXPIRED but no dispense-ledger table. Needs adding. |
| 10 | eps_fhir.py GDC-number plumbing + DPF filter |
🔴 MISSING — eps_fhir.py only sends NHSD-Session-URID; no professional_registration_number/GDC plumbing and no DPF (Dental Practitioners' Formulary) filter. DentalProvider.gdc_number + CustomUser.professional_registration_number exist to wire in. |
| 11 | NHS_NOTIFY/ReminderLog push extendability |
⚠️ PARTIAL — notifications.ReminderLog (SMS/EMAIL; PUSH commented out), patient_portal.PushSubscription + push_service.py exist. Extendable for Tier 3 push. |
| 12 | Any messaging infra for two-way chat | ✅ EXISTS — patient_portal.Conversation/Message models + patient + staff messaging viewsets in both the dental repo and the GP repo. |
Key discovery (2026-08-22): the dental_booking_app already contains a full
patient_portal backend app (installed, migrated, wired at /api/patient/…) with
dental-aware read-only viewsets (PatientDentalAppointmentViewSet,
PatientDentalClinicalNoteViewSet, PatientDentalTransactionViewSet,
PatientPrescriptionViewSet, profile, messaging, push) and the
patient-portal-pwa frontend already fetches /dental/appointments/,
/dental/clinical-notes/ and /dental/transactions/. So the "reuse the GP
portal" base is largely already in place on the backend — the build is mainly:
frontend dental UX rework, plus write endpoints (booking/cancel/reschedule),
household linking, recall-driven booking, emergency request, intake form,
prescriptions (ledger + GDC/DPF), PII-safe document upload.
Backend commits on dental_booking_app develop, all verified live on
test-client-dental and synced to VPS2:
| Item | Commit | What |
|---|---|---|
| Household/family accounts | 6d9e451e |
DentalHousehold + DentalHouseholdMember models (account holder + family members, per-member can_book/sign/pay); portal household API; tenant-aware DRF token auth (PatientAwareTokenAuthentication) + /api/patient/token-auth/ |
| Patient-facing booking | 7510d463 |
/api/patient/dental/booking/ (create, triage), /slots/, /cost/ (FP17 band £26.80/£73.50/£319.10 up front); books for self or a household member |
| Recall-driven booking | 026b4ea3 |
/dental/booking/recalls/ (due for self + household members), /recall_slots/ |
| Emergency request | a09319f2 |
/dental/booking/emergency_slots/, /emergency/ (EMERGENCY appt + triage) |
| Appointment management | 6f54213c |
/dental/booking/<pk>/cancel/, /reschedule/ |
Frontend (patient-portal-pwa): auth store now uses the tenant-aware token
endpoint; new DentalBookView (booking + cost + household member switch +
recalls + emergency), DentalHouseholdView, DentalAppointmentDetailView
(cancel/reschedule); nav "Book" item; rebuilt + redeployed.
Shared-PWA token support also applied to gp_booking_app (commit d4425a3)
so the same PWA build logs in on both the GP and dental backends.
Deployed (2026-08-22): dental patient PWA is LIVE — the ONLY
customer-facing URL is https://test-client-dental.patient.veripath.co.uk
(demo client tenant). A record added at Fasthosts DNS; Let's Encrypt cert
issued for this hostname only (nginx plugin); nginx routes the PWA frontend
(patient-portal-pwa :8081) and proxies /api/ to the dental app
(127.0.0.1:8011). Verified live: login via /api/patient/token-auth/,
household create, booking cost all work over the public HTTPS URL.
Tenant/URL policy: only CLIENT tenants get a public patient-portal URL
({tenant}.patient.veripath.co.uk). The shared/dev dental tenant
(dental) has no public patient portal — its PWA hostname
(dental.patient.veripath.co.uk) was removed from nginx and its DNS A
record deleted at Fasthosts to avoid confusion. The shared tenant remains
reachable internally via the staff URLdental.veripath.co.uk.
Remaining (later session): digital intake form + structured
allergies/medications model (Tier 2 item 6); prescriptions (ledger + GDC/DPF);
PII-safe document upload via MinIO.
APPROVED 2026-08-22 (user) — build instruction pack. Backend verification
checklist completed by OpenCode on 2026-08-22 (see table above). Tier 1
backend + frontend built and committed (see Build status); Tier 2+ pending.