-- Credit card billing period configuration per account ALTER TABLE accounts ADD COLUMN IF NOT EXISTS closing_day INTEGER CHECK (closing_day BETWEEN 1 AND 28), ADD COLUMN IF NOT EXISTS due_day INTEGER CHECK (due_day BETWEEN 1 AND 28); -- Materialized bill metadata (calculated from transactions) -- One row per (account, billing period start date) CREATE TABLE IF NOT EXISTS credit_bills ( id SERIAL PRIMARY KEY, account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE, period_start DATE NOT NULL, period_end DATE NOT NULL, due_date DATE NOT NULL, paid BOOLEAN NOT NULL DEFAULT FALSE, paid_at TIMESTAMP WITH TIME ZONE, payment_account_id INTEGER REFERENCES accounts(id) ON DELETE SET NULL, created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), UNIQUE(account_id, period_start) );