IPD Command Center Deployment
Operator handoff for getting the IPD command center to show real data on a fresh Supabase project.
This is the operator handoff for getting /ipd/command-center to show real data on a fresh Supabase project (PH demo or otherwise).
What ships in the codebase (already merged)
- Page at
/ipd/command-center(5 view modes + left rail + right slider) /ipd/quick-entrymini-app — emits all 4 EMRAM events directly intohospital_eventsso the orchestrator picks them up- 4 new orchestrator handlers —
handleVitalsDocumented/handleLabResultFiled/handleMedicationAdministered/handleAntibioticTimingininfrastructure/medbase/functions/encounter-orchestrator/ - Migration
054_ipd_command_center_projections.sql— adds the partial location index + (ifcron_jobsregistry exists) seeds the daily antibiotic-day-count cron
Deploy steps (manual — CLI access only on operator machine)
1. Apply migrations
In the Supabase SQL editor (or psql):
# If the cron_jobs registry isn't there yet, apply 036 first (safe to re-run):
psql "$SUPABASE_DB_URL" -f infrastructure/medbase/migrations/036_cron_jobs_registry.sql
# Always apply 054 (idempotent — guard checks for cron_jobs):
psql "$SUPABASE_DB_URL" -f infrastructure/medbase/migrations/054_ipd_command_center_projections.sql
# Apply the read-model schema (idempotent):
psql "$SUPABASE_DB_URL" -f web/supabase/migrations/20260209_ipd_dashboard_tables.sql
2. Deploy the orchestrator
supabase functions deploy encounter-orchestrator
This is the deploy that activates the 4 new handlers — without it, vitals/MAR/lab/antibiotic events written to hospital_events will be ignored.
3. Verify the read model is reachable
-- Should return 0 rows on a fresh project, and an existing row count on a populated one.
SELECT count(*) FROM ipd_admissions_dashboard;
-- Should return the partial index from migration 054:
SELECT indexname FROM pg_indexes
WHERE indexname = 'idx_journey_cache_location_partial';
Backfill (the most important part if your dashboard is empty)
The 5 PH [DEMO] patients (HN 6–10/69) have admissions in MongoDB but probably no rows in ipd_admissions_dashboard. There are two paths:
Path A — Seed sample rows directly (fastest, demo-friendly)
-- Seed 5 demo IPD admissions matching the PH [DEMO] patients.
-- Safe to re-run (ON CONFLICT DO NOTHING).
INSERT INTO public.ipd_admissions_dashboard
(admission_id, encounter_id, hn, patient_name, ward_id, ward_name,
bed_number, admission_date, los_days, primary_doctor, payor, status)
VALUES
('demo-adm-006', 'demo-enc-006', '6/69', '[DEMO] Maria Santos', 'ward-1', 'General Ward 1', '101', now() - interval '2 days', 2, 'Dr. Cruz', 'PhilHealth', 'in-progress'),
('demo-adm-007', 'demo-enc-007', '7/69', '[DEMO] Juan Dela Cruz', 'ward-1', 'General Ward 1', '102', now() - interval '3 days', 3, 'Dr. Reyes', 'PhilHealth', 'in-progress'),
('demo-adm-008', 'demo-enc-008', '8/69', '[DEMO] Anna Reyes', 'ward-1', 'General Ward 1', '103', now() - interval '1 day', 1, 'Dr. Cruz', 'Self-pay', 'in-progress'),
('demo-adm-009', 'demo-enc-009', '9/69', '[DEMO] Pedro Garcia', 'ward-2', 'General Ward 2', '201', now() - interval '5 days', 5, 'Dr. Lim', 'HMO', 'in-progress'),
('demo-adm-010', 'demo-enc-010', '10/69', '[DEMO] Sofia Mendoza', 'ward-2', 'General Ward 2', '202', now() - interval '4 days', 4, 'Dr. Lim', 'PhilHealth', 'in-progress')
ON CONFLICT (admission_id) DO NOTHING;
After running, /ipd/command-center should immediately show 5 patients across 2 wards.
Path B — Backfill from real MongoDB admissions (production path)
If the demo patients already have admission records in MongoDB and you want to drive everything end-to-end, fire manifest.admission.updated events for each. The orchestrator’s handleAdmissionUpdated will then write to encounter_journey_cache, and a follow-up trigger projects to ipd_admissions_dashboard (only if your project has the projection trigger — check web/supabase/migrations/20260209_ipd_dashboard_tables.sql).
Easiest way to test this path: open /ipd/quick-entry, paste an encounter ID, and click “Send admission-updated event” (provided as a button in the mini-app).
Testing the full flow with /ipd/quick-entry
Once Path A or B is done and the orchestrator is deployed:
- Open
/ipd/command-center— see 5 patients in grid view. - Click any patient → right slider opens with 8 tabs.
- In a second tab, open
/ipd/quick-entry. - Pick the same patient’s
encounter_id. - Submit a vitals reading → Command Center NEWS2 chip updates within 2 seconds (realtime).
- Submit a critical lab result →
AcknowledgementInboxFAB badge increments; the patient’s row gets a tier-3 alert chip. - Submit a med-administered scan → BCMA % column updates.
- Submit antibiotic-started → safety-indicator card on the card view shows “Day 1” stewardship.
What’s still missing (production gap, not a demo blocker)
- Backend emitters for events 3 & 4:
services/medication/.../medicationAdministration.controller.mixin.tsand the antibiotic order placement controller don’t callemitMedicationAdministered()/ emit antibiotic_started yet. The Quick Entry mini-app fills this gap for demos, but production needs the controller wiring (~10 LOC each, requires PH backend deploy). antibiotic-day-recomputeedge function: the cron entry references it but the function doesn’t exist. Either build it (~50 LOC Deno) or leave the cron disabled (default in migration 054).