🧩 Module Spec · M3 CLOC · Clinic Locator · DETAIL · 26 April 2026
← Modules M3 · CLOC DETAIL Phase 3 · 1-14 Oct 2026

M3 — Clinic Locator & Smart Routing

GPS pesakit → klinik berhampiran dlm rangkaian · queue length live · ETA · digital referral letter · 1st-responder routing untuk MERAH triage. Network effect feature.

1. 📌 Overview & Purpose

Goal: Pesakit dpt clarity ke klinik mana terdekat dgn capacity sedia ada. Klinik dpt pre-qualified leads (already triaged + intent confirmed). Hospital ED dpt pre-arrival packet untuk MERAH triage emergency cases.

Network effect: Lebih banyak klinik join rangkaian = lebih bermakna untuk pesakit. M3 = the magnet that grows network value beyond single-clinic SaaS.

Per Doc Zam mock: "Guided to Nearest Hospital / 1st Responder · System Assist · Doctor Assist" workflow direct integration.

2. 👤 User Stories

US-3.1 (Pesakit · Routine)

Sebagai pesakit Kuning triage dari M1, saya nak top 3 klinik berhampiran dgn queue indicator + jarak + ETA — pilih, book, gerak.

US-3.2 (Pesakit · Emergency)

Saya MERAH triage (sakit dada) — saya nak hospital ED nearest dgn cath-lab + pre-arrival packet auto-hantar ke ED supaya cardio standby.

US-3.3 (Klinik admin)

Sebagai klinik admin, saya nak update klinik info (services · doctor · hours · queue cap) dlm panel mudah.

US-3.4 (Doktor · Refer)

Pesakit perlu specialist · saya nak generate digital referral letter terus dari M4 encounter, hantar via M3 ke klinik specialist receiving.

US-3.5 (Klinik owner · Analytics)

Saya nak dashboard: berapa lead M3 hantar bulan ni · conversion rate (lead → encounter) · NPS pesakit referred.

3. ✅ Functional Requirements

MUSTFR-3.1: Klinik directory CRUD (admin · per-tenant) · 25+ data fields (name · address · GPS · services · doctors · hours · panel · halal-cert)
MUSTFR-3.2: Geo-search (PostGIS) · radius query lat/lng · sort by distance + queue + ETA
MUSTFR-3.3: Live queue count (integration via M7 ADPA queue API) · TTL 60s cache
MUSTFR-3.4: ETA via Maps API (Google atau Mapbox) · adjust real-time traffic
MUSTFR-3.5: Service filter (GP · paeds · gynae · dermat · pakar etc)
MUSTFR-3.6: Booking deep-link → M7 appointment
MUSTFR-3.7: Digital referral letter compose (specialist/hospital) · letterhead branded · digital signature · PDF + structured data
MUSTFR-3.8: Emergency 1st-responder routing (MERAH triage → nearest ED hospital · pre-arrival packet via M3 integration with hospital systems)
MUSTFR-3.9: Multi-tenant scope · cross-tenant referral dgn explicit consent
MUSTFR-3.10: Klinik analytics dashboard (lead source · conversion · NPS · revenue contribution)
SHOULDFR-3.11: Telemedicine option flag (klinik offer video consult? deep-link)
SHOULDFR-3.12: WhatsApp-first booking (klinik bukan dlm rangkaian still able receive WAHA referral)
SHOULDFR-3.13: Walk-in vs appointment indicator
SHOULDFR-3.14: Insurance panel filter (MySalam · AIA · Allianz match patient panel)

4. ⚙️ Non-Functional Requirements

AspectTargetNotes
Geo search latency<500ms p99PostGIS HNSW + GIN index
Live queue refresh60s cache TTLReal enough; reduce M7 load
ETA freshness5min cacheMaps API call cost concern
Klinik directory size≥1000 klinik searchablePhase 3 ambition
Maps API cost≤RM 0.05/searchAggressive caching · ETA only on book
Pre-arrival packet delivery<30sMERAH critical path
Referral letter generation<5sDoctor in-encounter usage

5. 🗄️ Data Model

TableKey fieldsPurpose
clinicsid, tenant_id, name, address, lat, lng (PostGIS POINT), phone, email, hours_json, services_json, doctors_json, panel_json, halal_cert, walk_in, telemedicine, established_yearMaster directory
clinic_doctorsclinic_id, user_id, specialty, mmc_no, available_hours_jsonDoctor roster
clinic_queue_snapshotclinic_id, snapshot_at, queue_count, avg_wait_minFR-3.3 cached snapshot
referralsid, encounter_id, from_doctor_id, to_clinic_id?, to_specialty, urgency, summary, pdf_url, status (sent · acknowledged · accepted · declined)FR-3.7 referral records
prearrival_packetsid, session_id (M1 RED), patient_id, hospital_id, ed_unit, summary_json, eta_min, sent_at, acknowledged_atFR-3.8 ED notify
clinic_leadsclinic_id, source (M1 patient_pa · M3 self-search), lead_type, generated_at, converted_to_encounter_id?FR-3.10 analytics

5a. PostGIS Index

CREATE EXTENSION postgis;
ALTER TABLE clinics ADD COLUMN location geography(POINT, 4326);
UPDATE clinics SET location = ST_MakePoint(lng, lat)::geography;
CREATE INDEX clinics_location_gix ON clinics USING GIST (location);
CREATE INDEX clinics_services_gin ON clinics USING GIN (services_json);
CREATE INDEX clinics_panel_gin ON clinics USING GIN (panel_json);

-- Geo query example
SELECT id, name, ST_Distance(location, ST_MakePoint(101.6869, 3.1390)::geography) AS distance_m
FROM clinics
WHERE ST_DWithin(location, ST_MakePoint(101.6869, 3.1390)::geography, 10000)
  AND services_json @> '["gp"]'
ORDER BY distance_m
LIMIT 10;

6. 🔌 API + Maps Integration

GET    /api/v1/clinics/nearby
       Query: lat, lng, radius_km=10, service_type=gp, panel=mysalam
       Returns: [{ clinic_id, name, distance_km, queue_count, eta_min, booking_url }, ...]

GET    /api/v1/clinics/{id}                       # detail (services · doctors · hours)
POST   /api/v1/clinics                            # create (clinic admin)
PATCH  /api/v1/clinics/{id}                       # update
DELETE /api/v1/clinics/{id}                       # soft delete

POST   /api/v1/referrals                          # doctor compose referral
       Body: { encounter_id, to_clinic_id?, to_specialty, urgency, summary }
       Returns: { referral_id, pdf_url, sent_at }

GET    /api/v1/referrals/incoming                 # for receiving clinic
POST   /api/v1/referrals/{id}/acknowledge

POST   /api/v1/prearrival/dispatch                # M1 RED triage trigger
       Body: { session_id, hospital_id, ed_unit }
       Returns: { packet_id, eta_min, ed_acknowledged }

GET    /api/v1/clinics/{id}/analytics             # lead · conversion · NPS

# MCP Tools
clinic_finder           Geo-search + filter
queue_lookup            Live queue per clinic
eta_calc                Maps API · cached
referral_compose        Letter generator
prearrival_dispatch     ED packet send

6a. Maps API Strategy

  • Primary: Google Maps Distance Matrix API (real-time traffic) — RM 0.005/element
  • Fallback: Mapbox Directions API (cheaper bulk · no traffic)
  • Caching: 5-minute TTL · key = {from_h3_index}_{to_clinic_id} · H3 hex grid for spatial caching
  • Cost cap: per-tenant monthly budget · alert at 80% · soft-fail to straight-line distance

7. 🔁 State Machine

Patient flow:
PATIENT_TRIAGED ──► CLINIC_SEARCH ──► RESULTS_SHOWN ──► SELECTION ──► BOOK_VIA_M7

  IF triage = RED:
    ──► EMERGENCY_ROUTING ──► HOSPITAL_ED_NEAREST ──► PREARRIVAL_DISPATCH
                              + 999 advisory shown to patient

Referral flow (doctor-initiated):
ENCOUNTER_DECISION ──► COMPOSE_REFERRAL ──► PDF_GENERATE ──► DISPATCH ──► ACKNOWLEDGE

Klinik admin flow:
CLINIC_SETUP ──► HOURS/SERVICES/DOCTORS ──► PUBLISH ──► [LEAD_RECEIVE loop]

8. 🤖 Agent Specification

M3 mostly rule-based + Maps API. LLM hanya untuk: (a) referral letter compose, (b) clinic recommendation explanation ke pesakit ("klinik ni nearest, queue 3 orang, ETA 12 min"), (c) pre-arrival packet structuring untuk ED.

  • Model: Llama 8B (rule-based heavy) untuk recommendation explanation; Llama 70B untuk referral letter compose (clinical quality)
  • Memory: klinik directory (read-heavy cache) · patient preferences (last clinic visited)

9. 🎨 UI/UX

  • Patient PWA: Map view (Mapbox GL atau Google Maps embedded) + list view toggle · clinic cards dgn name · distance · queue · "Book now" button
  • Emergency screen (RED): Big red banner · 999 phone button · Hospital ED card dgn "Tap to share GPS + send pre-arrival" · live ETA
  • Klinik admin (Filament): CRUD form · location picker (map drag) · services multi-select · hours week-grid · panel insurer multi-select
  • Doctor referral compose: One-click from M4 encounter · LLM draft + edit · target clinic search · digital signature · send
  • Klinik analytics dashboard: Cards (leads received · conversion % · NPS) · trend chart · per-source breakdown

10. ✔️ Acceptance Criteria

  • AC-3.1: Geo search returns top-10 results <500ms pada 1000-clinic database
  • AC-3.2: RED triage emergency routing: pre-arrival packet ke ED <30s
  • AC-3.3: Clinic directory CRUD: 95%+ form completion success (no validation friction)
  • AC-3.4: Referral letter PDF gen <5s · clinical content accurate
  • AC-3.5: Maps API cost <RM 100/bulan @ 1000 searches/day
  • AC-3.6: Cross-tenant consent flow tested · zero unauthorised access
  • AC-3.7: Klinik analytics 30-day metrics within 24h refresh
  • AC-3.8: Mobile PWA Map view 60fps pan/zoom

11. 🧪 Test Plan

TierCasesCoverage
UnitGeo distance calc · service filter · queue snapshot fetch · referral letter template≥80%
IntegrationAPI endpoints · Maps API integration (mocked + real) · cross-tenant referral100% endpoints
E2E3 patient journeys: nearby search · RED emergency · doctor referral3/3 pass
Load100 concurrent geo searches · 10 simultaneous referralsp99 <1s
Geographic50 clinic samples KL/Selangor/Johor — verify accuracy distance + ETA±5% accuracy
CostMaps API budget tracking · soft-fail when exceededBudget control verified

12. 🔗 Dependencies

  • Hard: M9 (audit + RBAC · cross-tenant consent) · M7 ADPA (queue + appointment API)
  • Soft: M1 PSPA (lead source · trigger emergency routing) · M4 DRPA (referral consumer)
  • External: Google Maps API atau Mapbox GL · MOH directory of registered clinics (data seed) · postal services API (for ED hospital list)

13. 🏃 Sprint Allocation

Sprint 3.1 · 1-14 Oct 2026 (2 minggu)
  • Day 1-3: Klinik directory schema · CRUD admin UI · seed data 100 sample clinics
  • Day 4-5: PostGIS geo-search · service filter · panel filter
  • Day 6-7: Maps API integration · ETA · live queue snapshot
  • Day 8-9: Patient PWA Map view · list view · booking deep-link
  • Day 10-11: Referral letter compose (M4 integration) · PDF gen
  • Day 12: Pre-arrival packet workflow (RED triage path)
  • Day 13: Klinik analytics dashboard
  • Day 14: E2E test · sprint review
Capacity: 2 backend + 1 frontend · GIS specialist consult Day 4-5

14. ⚠️ Module-Specific Risks

RiskLikelihoodImpactMitigation
Klinik gaming queue counts (always show "0 waiting")Med🟠 Trust lossAudit trail queue updates · M7 ADPA single source · spot check via 30-min refresh
Maps API cost explosionMed🟢 BudgetAggressive caching · H3 spatial index · per-tenant budget cap · soft-fail to straight line
Pre-arrival packet not received by EDMed🔴 Patient harmMulti-channel: API + email + WAHA + SMS · ED ack required · audit FN rate
False advertising klinik (services not actually available)Med🟠 Patient frustrationPatient feedback loop · NPS · inactive clinic auto-hide · admin verify checkbox
Cross-tenant data leak (referral)Low🔴 PDPA breachExplicit consent per referral · audit cross-tenant access · receiving clinic acknowledge
Geocoding inaccurate (rural Malaysia)Med🟢 UXManual address override · clinic admin set GPS pin · MOH directory cross-ref