Files
mailadmin/backend/migrations/003_mailbox_billing_events.sql
2026-04-28 17:59:51 -05:00

60 lines
2.2 KiB
SQL

-- ============================================================
-- 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
);