Reference for exploring the dental app on the client instance. Prepared 2026-08-03 as part of the dental-app walk-through.
test-client-dental (client dental-booking-app) — login redirects to auth.veripath.co.uk/realms/test-client-dentalsector_client_test-client-dental (test_client_dental on the client VPS via SSH tunnel)TESTCD01)role + org_id user attributes on first login.test123The five dental roles are distinct from GP roles (CLINICIAN, RECEPTIONIST, PRACTICE_MANAGER, …) and VeriPath partner roles (PARTNER_*). They are defined in users/models.py (CustomUser.Roles) and dashboards/models.py (FormalRole.ROLE_CHOICES).
| Keycloak username | Role (Django) | Purpose | |
|---|---|---|---|
admin.test-client-dental |
admin@test-client-dental.co.uk | DENTAL_ADMIN |
Full system control, settings, seats, finance |
manager.test-client-dental |
manager@test-client-dental.co.uk | DENTAL_PRACTICE_MANAGER |
Rotas, staff, CQC reporting, finance |
dentist.test-client-dental |
dentist.sarah@test-client-dental.co.uk | DENTAL_CLINICIAN |
Clinical records, charting, perio, FP17 |
hygienist.test-client-dental |
hygienist.amy@test-client-dental.co.uk | DENTAL_HYGIENIST |
Hygiene-scope clinical records |
reception.test-client-dental |
reception@test-client-dental.co.uk | DENTAL_RECEPTIONIST |
Calendar, payments, recalls, patient details |
patient.james … patient.elena (×6) |
james.carter@test-client-dental.co.uk etc. | PATIENT |
Test patients (data + optional login) |
| Item | Count | Notes |
|---|---|---|
| Dental practices | 1 | Test Client Dental Practice (TESTCD01) |
| Providers | 3 | 2× DENTIST, 1× HYGIENIST (GDC-linked) |
| Appointments | 14 | 6 future (BOOKED) + 8 attended (incl. 2 old ones that trigger recalls) |
| Patients (profiles) | 6 | Mixed LOW/MODERATE/HIGH/COMPLEX risk; 3 due for recall ≤30d |
| Transactions | 8 | NHS band 1/2 + private; PENDING/PAID |
| FP17 claims | 4 | DRAFT / TRANSMITTED / ACCEPTED / REJECTED (one per state) |
| Clinical charts | 8 | FDI 5-surface (M/D/O/B/L) entries |
| Perio exams | 2 | 6-point pocket/BOP/plaque matrices |
| Radiographs | 2 | Bite-wing, placeholder image |
| Zones + schedule blocks | 4 zones / 65 blocks | NHS Check-up, NHS Filling, Hygiene, Private Suite |
| Recall rules | 4 | NICE intervals (3–12 months) |
Reseed any time:
docker exec dental_app python manage.py seed_dental_demo --tenant test-client-dental --reset
Verified server-side (actual HTTP statuses through the RBAC middleware). This is the current enforcement:
| View | ADMIN | Prac Mgr | Clinician | Hygienist | Reception |
|---|---|---|---|---|---|
| Practices / Appointments | ✅ | ✅ | ✅ | ✅ | ✅ |
| Recalls | ✅ | ✅ | ✅ | ✅ | ✅ |
| Financial | ✅ | ✅ | ❌ 403 | ❌ 403 | ❌ 403 |
| FP17 claims | ✅ | ✅ | ✅ | ❌ 403 | ❌ 403 |
| Webhooks | ✅ | ✅ | ❌ 403 | ❌ 403 | ❌ 403 |
| Charting / Perio / Radiographs / Triage / Staff / Seats / Settings | ✅ | ✅ | ✅ | ✅ | ✅ ⚠️ |
core/middleware.py ROLE_REQUIREMENTS covers /dental/practices/, /appointments/, /financial/, /fp17/, /recalls/, /webhooks/, /api/ only. The clinical/admin paths /dental/charts/, /perio/, /radiographs/, /triage/, /staff/, /providers/, /seats/, /settings/*, /slots/ have no server-side role gate — a DENTAL_RECEPTIONIST (or any role) can open them by URL even though the nav hides them. For DSPT data segregation, receptionists must be blocked from clinical paths (charts/perio/radiographs).dashboards/ required_roles mixins and DashboardPermission.clean() (dashboards/models.py) recognise GP roles only; dental roles cannot currently be granted GP-style dashboard permissions. Dental users stay in the dental module (routed to dental:practice_list), so this is only relevant if dental roles should surface on the GP dashboards.dental/templates/dental/base_dental.html) is more restrictive than the middleware for receptionists — good, but not an enforcement boundary.The dental nav is role-based (dental/templates/dental/base_dental.html) and renders on every dental page. The GP "My Appointments" header link is replaced by a "Dental Dashboard" link for all dental roles.
| Role | Menu (nav links) |
|---|---|
DENTAL_ADMIN (admin.test-client-dental) |
Dashboard, Practices, Appointments, Staff, Providers, Triage, Recalls, Charting, Periodontal, Radiographs, Financial, Seats, FP17, Scheduling, Settings → Zones/Schedules |
DENTAL_PRACTICE_MANAGER (manager.test-client-dental) |
same as Admin |
DENTAL_CLINICIAN (dentist.test-client-dental) |
Dashboard, Practices, Appointments, Staff, Providers, Triage, Recalls, Charting, Periodontal, Radiographs, FP17, Scheduling |
DENTAL_HYGIENIST (hygienist.test-client-dental) |
Dashboard, Practices, Appointments, Staff, Providers, Triage, Recalls, Charting, Periodontal, Scheduling |
DENTAL_RECEPTIONIST (reception.test-client-dental) |
Dashboard, Practices, Appointments, Staff, Providers, Recalls, Scheduling |
Every dental role lands on /dental/practices/ after login (dashboards/routing.py).
dental/fp17.py build_fp17_payload returned units_of_dental_activity_uda as a Decimal, which is not JSON-serializable, so queue_claim crashed and the claim stayed DRAFT. Fixed with float(...). Verified end-to-end: DRAFT → TRANSMITTED through the mock NHSBSA gateway (use USE_MOCK_NHSBSA=true, the default).{% block content %} in base_dental.html, but every dental page overrides that same block, so the menu was wiped out. Moved it into a new {% block pre_content %} in templates/base.html so it renders on every dental page. Also added a dental-role branch to the global navbar (kills the GP "My Appointments" link) and a Seats link (admin/PM). Note: after template edits, restart the dental_app container — stale gunicorn workers served old templates until a docker restart dental_app.reception.test-client-dental → Appointments, Recalls, then try /dental/financial/ → expect 403.dentist.test-client-dental → open the DRAFT FP17 claim → Submit → becomes TRANSMITTED via mock; view a chart + perio exam; upload radiograph.manager.test-client-dental → Financial dashboard, Staff, seat management (/dental/seats/).admin.test-client-dental → Settings (zones/schedules), providers, subscription./dental/recalls/ shows 3 due (James Carter ×2, Elena Popova).All demo data lives in the client DB only — the shared veripath_dental DB (used by dental.veripath.co.uk) remains empty (0 practices). This confirms per-client tenancy isolation.
Related: Dental App — Developer Plan, Dental App — ERPNext Integration Plan