← back to AbramsOS
db/migrations/0011_health_readings.sql
38 lines
-- 0011_health_readings.sql
-- Health / Vitals tracking: blood pressure history + Apple Watch / device readings.
-- health_reading — one measurement (BP pair, heart rate, weight, SpO2, glucose, …)
-- for a household member, from Apple Health export, the Health Auto
-- Export app (JSON POST), a connected device, or manual entry.
-- Sensitive medical data — same consent/audit posture as the medication tables.
-- Idempotent. Safe to re-run.
BEGIN;
CREATE TABLE IF NOT EXISTS health_reading (
id text PRIMARY KEY,
user_id text NOT NULL REFERENCES user_account(id) ON DELETE CASCADE,
person_id text REFERENCES person(id) ON DELETE SET NULL, -- null = account owner
metric text NOT NULL, -- blood_pressure|heart_rate|resting_heart_rate|weight|
-- spo2|blood_glucose|steps|hrv|respiratory_rate|body_temperature|vo2max
systolic numeric(6,2), -- BP only
diastolic numeric(6,2), -- BP only
value numeric(12,3), -- single-value metrics (hr, weight, spo2, …)
unit text, -- mmHg | bpm | lb | kg | % | mg/dL | count | ms | °F …
category text, -- BP: normal|elevated|hypertension_1|hypertension_2|crisis
measured_at timestamptz NOT NULL,
source text NOT NULL DEFAULT 'manual', -- manual|apple-health-export|health-auto-export|device
device_name text, -- e.g. "Apple Watch", "Omron", "Withings"
external_id text, -- stable id from the source, for dedup on re-import
notes text,
metadata_jsonb jsonb NOT NULL DEFAULT '{}'::jsonb,
created_at timestamptz NOT NULL DEFAULT now()
);
-- Dedup: the same source reading never lands twice.
CREATE UNIQUE INDEX IF NOT EXISTS health_reading_ext_idx
ON health_reading (user_id, external_id) WHERE external_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS health_reading_lookup_idx
ON health_reading (user_id, person_id, metric, measured_at DESC);
COMMIT;