-- Phase 4 - Reminders expansion (POST-AUDIT-SPEC §2 + MASTER-PLAN §D). -- -- Adds: -- 1. interests.reminder_note - cadence note surfaced in notification body + inbox row. -- 2. reminders.yacht_id - fourth supported entity link (was: client/interest/berth). -- 3. reminders.fired_at - worker idempotency; set once the firing notification is -- created so a parallel worker can't double-fire. -- 4. user_profiles.preferences gains `digest_time_of_day` (JSONB key; no DDL). -- -- The existing reminders table already carries title/note/dueAt/priority/assignedTo/ -- snoozedUntil/googleCalendarEventId - those columns are reused unchanged. No new -- table; standalone tasks set client_id/interest_id/berth_id/yacht_id all NULL. ALTER TABLE interests ADD COLUMN IF NOT EXISTS reminder_note text; ALTER TABLE reminders ADD COLUMN IF NOT EXISTS yacht_id text, ADD COLUMN IF NOT EXISTS fired_at timestamptz; -- Yacht FK with the same ON DELETE behaviour as the other entity links. DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'reminders_yacht_id_fkey' ) THEN ALTER TABLE reminders ADD CONSTRAINT reminders_yacht_id_fkey FOREIGN KEY (yacht_id) REFERENCES yachts(id) ON DELETE SET NULL; END IF; END $$; -- Index supports the worker scan: "give me every pending reminder whose -- due_at has passed and we haven't fired yet." CREATE INDEX IF NOT EXISTS idx_reminders_due_unfired ON reminders (port_id, due_at) WHERE fired_at IS NULL AND status IN ('pending', 'snoozed'); -- Comments for downstream readers. COMMENT ON COLUMN interests.reminder_note IS 'Phase 4: optional cadence note surfaced in reminder notification body + inbox row. NULL = use the default cadence copy.'; COMMENT ON COLUMN reminders.yacht_id IS 'Phase 4: link to a yacht for yacht-scoped reminders. Mirrors client_id/interest_id/berth_id semantics.'; COMMENT ON COLUMN reminders.fired_at IS 'Phase 4: set by the worker once the due-reminder notification has been created. NULL = not yet fired; used as the worker idempotency gate (alongside the partial index above).';