-- ============================================================ -- 003_mailbox_billing_events.sql -- Append-only event log for inbox billing. -- -- Each row records that a mailbox was created or deleted at a -- specific point in time. The aggregation per month is computed -- on the fly from these events. -- ============================================================ CREATE TABLE IF NOT EXISTS mailbox_billing_events ( id BIGSERIAL PRIMARY KEY, occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(), domain TEXT NOT NULL, email TEXT NOT NULL, action TEXT NOT NULL CHECK (action IN ('created', 'deleted')), actor_email TEXT, notes TEXT ); CREATE INDEX IF NOT EXISTS idx_billing_events_domain_time ON mailbox_billing_events(domain, occurred_at); CREATE INDEX IF NOT EXISTS idx_billing_events_email ON mailbox_billing_events(email); -- ------------------------------------------------------------ -- Backfill: synthesize 'created' events for every mailbox that -- already exists when this migration runs, so we have correct -- historical data right from the first deploy. -- -- We use the mailbox's created_at as the event timestamp. -- For mailboxes that are already soft-deleted, also synthesize -- the matching 'deleted' event using deleted_at. -- -- The WHERE NOT EXISTS guards make this migration idempotent -- in case it is re-run. -- ------------------------------------------------------------ INSERT INTO mailbox_billing_events (occurred_at, domain, email, action, actor_email, notes) SELECT m.created_at, m.domain, m.email_address, 'created', NULL, 'backfill from migration 003' FROM mailboxes m WHERE NOT EXISTS ( SELECT 1 FROM mailbox_billing_events b WHERE b.email = m.email_address AND b.action = 'created' AND b.occurred_at = m.created_at ); INSERT INTO mailbox_billing_events (occurred_at, domain, email, action, actor_email, notes) SELECT m.deleted_at, m.domain, m.email_address, 'deleted', NULL, 'backfill from migration 003' FROM mailboxes m WHERE m.status = 'deleted' AND m.deleted_at IS NOT NULL AND NOT EXISTS ( SELECT 1 FROM mailbox_billing_events b WHERE b.email = m.email_address AND b.action = 'deleted' AND b.occurred_at = m.deleted_at );