fix: serialize Stripe checkout provisioning
This commit is contained in:
59
migrations/017_billing_checkout_invariants.sql
Normal file
59
migrations/017_billing_checkout_invariants.sql
Normal file
@@ -0,0 +1,59 @@
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM users
|
||||
WHERE billing_customer_id IS NOT NULL AND billing_customer_id <> ''
|
||||
GROUP BY billing_customer_id
|
||||
HAVING COUNT(*) > 1
|
||||
) THEN
|
||||
RAISE EXCEPTION 'duplicate users.billing_customer_id values require Stripe reconciliation before migration 017';
|
||||
END IF;
|
||||
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM subscriptions
|
||||
WHERE provider = 'stripe' AND status <> 'canceled'
|
||||
GROUP BY user_id
|
||||
HAVING COUNT(*) > 1
|
||||
) THEN
|
||||
RAISE EXCEPTION 'multiple open Stripe subscriptions per user require reconciliation before migration 017';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_billing_customer_unique
|
||||
ON users(billing_customer_id)
|
||||
WHERE billing_customer_id IS NOT NULL AND billing_customer_id <> '';
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_subscriptions_user_open_stripe_unique
|
||||
ON subscriptions(user_id)
|
||||
WHERE provider = 'stripe' AND status <> 'canceled';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS billing_checkout_sessions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
plan_id UUID NOT NULL REFERENCES plans(id),
|
||||
stripe_customer_id VARCHAR(200),
|
||||
stripe_session_id VARCHAR(200),
|
||||
checkout_url TEXT,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
lease_owner UUID,
|
||||
lease_until TIMESTAMPTZ,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
completed_at TIMESTAMPTZ,
|
||||
CONSTRAINT billing_checkout_sessions_status_check
|
||||
CHECK (status IN ('pending', 'completed', 'expired', 'failed', 'canceled')),
|
||||
CONSTRAINT billing_checkout_sessions_stripe_session_unique
|
||||
UNIQUE (stripe_session_id)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_billing_checkout_sessions_user_pending
|
||||
ON billing_checkout_sessions(user_id)
|
||||
WHERE status = 'pending';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_billing_checkout_sessions_expiry
|
||||
ON billing_checkout_sessions(expires_at)
|
||||
WHERE status = 'pending';
|
||||
Reference in New Issue
Block a user