Files
ten31-database/backend/scripts/contacts_census.sql
T
Keysat 9ffd4a1c6a Add contacts A/B/C census script (counts-only ops diagnostic)
For the deferred contacts <-> fundraising_contacts consolidation (ROADMAP backlog):
counts the linked (A), contacts-only (B), and pill-only (C) populations plus the
communications/opportunities repointing surface. Counts only -- no names/PII -- so it
can be run on the box's /data/crm.db without anything sensitive leaving.
2026-06-20 21:18:17 -05:00

44 lines
2.7 KiB
SQL

-- contacts_census.sql — A/B/C census for the contacts <-> fundraising_contacts consolidation.
-- COUNTS ONLY: no names, emails, or amounts — nothing identifying leaves the box.
--
-- Run wherever you have the DB:
-- on the box (container shell): sqlite3 /data/crm.db < contacts_census.sql
-- against a local copy: sqlite3 data/crm.db < contacts_census.sql
--
-- Canonical link: fundraising_contacts.contact_id -> contacts.id (migration 0004).
-- A = contact linked to >=1 grid pill (healthy overlap — already done)
-- B = live contact with NO grid pill (needs a grid row/pill created)
-- C = grid pill with contact_id IS NULL (needs a contacts row created)
-- Sanity: A + B should equal "total live contacts".
.headers on
.mode column
WITH
linked AS ( -- contacts referenced by at least one grid pill
SELECT DISTINCT c.id
FROM contacts c
WHERE c.deleted_at IS NULL
AND EXISTS (SELECT 1 FROM fundraising_contacts fc WHERE fc.contact_id = c.id)
),
unlinked AS ( -- B: live contacts with no pill pointing at them
SELECT c.id, c.contact_type
FROM contacts c
WHERE c.deleted_at IS NULL
AND NOT EXISTS (SELECT 1 FROM fundraising_contacts fc WHERE fc.contact_id = c.id)
)
SELECT 'total live contacts' AS metric, (SELECT COUNT(*) FROM contacts WHERE deleted_at IS NULL) AS n
UNION ALL SELECT 'A: linked (contact <-> grid pill)', (SELECT COUNT(*) FROM linked)
UNION ALL SELECT 'B: contacts-only (no grid pill)', (SELECT COUNT(*) FROM unlinked)
UNION ALL SELECT ' ...of B, contact_type=investor', (SELECT COUNT(*) FROM unlinked WHERE contact_type='investor')
UNION ALL SELECT ' ...of B, contact_type=prospect', (SELECT COUNT(*) FROM unlinked WHERE contact_type='prospect')
UNION ALL SELECT ' ...of B, with >=1 live communication', (SELECT COUNT(*) FROM unlinked u WHERE EXISTS (SELECT 1 FROM communications cm WHERE cm.contact_id=u.id AND cm.deleted_at IS NULL))
UNION ALL SELECT ' ...of B, with >=1 live opportunity', (SELECT COUNT(*) FROM unlinked u WHERE EXISTS (SELECT 1 FROM opportunities o WHERE o.contact_id=u.id AND o.deleted_at IS NULL))
UNION ALL SELECT 'C: pill-only (contact_id IS NULL)', (SELECT COUNT(*) FROM fundraising_contacts WHERE contact_id IS NULL)
UNION ALL SELECT ' dangling pills (contact_id set, no live contact)',
(SELECT COUNT(*) FROM fundraising_contacts fc
WHERE fc.contact_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM contacts c WHERE c.id=fc.contact_id AND c.deleted_at IS NULL))
UNION ALL SELECT 'context: total grid pills (fundraising_contacts)', (SELECT COUNT(*) FROM fundraising_contacts)
UNION ALL SELECT 'context: total grid rows (fundraising_investors)', (SELECT COUNT(*) FROM fundraising_investors);