From 9ffd4a1c6a8965cdea9c7c8d4f3075151ba21fd8 Mon Sep 17 00:00:00 2001 From: Keysat Date: Sat, 20 Jun 2026 21:18:17 -0500 Subject: [PATCH] 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. --- backend/scripts/contacts_census.sql | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 backend/scripts/contacts_census.sql diff --git a/backend/scripts/contacts_census.sql b/backend/scripts/contacts_census.sql new file mode 100644 index 0000000..4d0bcfc --- /dev/null +++ b/backend/scripts/contacts_census.sql @@ -0,0 +1,43 @@ +-- 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);