-- ============================================================ -- Allow contact deletion without wiping history. -- -- broadcast_recipients.contact_id and deals.contact_id were declared -- NOT NULL REFERENCES contacts(id) with no ON DELETE action, so -- Postgres defaults to NO ACTION. The first time a user tried to -- delete a contact that had ever received a broadcast or been -- attached to a deal, the delete failed with: -- -- ERROR 23503: update or delete on table "contacts" violates -- foreign key constraint ... on table -- -- CASCADE is the wrong fix — it would silently wipe historical -- broadcast recipient rows (breaking audit + retroactively moving -- broadcasts.sent_count / delivered_count / read_count etc. via the -- aggregate trigger) and deal rows. -- -- SET NULL is the right fix: history rows survive with a NULL -- contact_id. The UI is already null-safe (contact?.name ?? 'Unknown', -- contact?.phone, etc.). -- -- Idempotent — safe to run multiple times. -- ============================================================ -- ── broadcast_recipients.contact_id ──────────────────────────── ALTER TABLE broadcast_recipients ALTER COLUMN contact_id DROP NOT NULL; DO $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'broadcast_recipients_contact_id_fkey' AND conrelid = 'broadcast_recipients'::regclass ) THEN ALTER TABLE broadcast_recipients DROP CONSTRAINT broadcast_recipients_contact_id_fkey; END IF; END $$; ALTER TABLE broadcast_recipients ADD CONSTRAINT broadcast_recipients_contact_id_fkey FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE SET NULL; -- ── deals.contact_id ─────────────────────────────────────────── ALTER TABLE deals ALTER COLUMN contact_id DROP NOT NULL; DO $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'deals_contact_id_fkey' AND conrelid = 'deals'::regclass ) THEN ALTER TABLE deals DROP CONSTRAINT deals_contact_id_fkey; END IF; END $$; ALTER TABLE deals ADD CONSTRAINT deals_contact_id_fkey FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE SET NULL;