Add migration 949 with subscription_plans, user_subscriptions, and subscription_invoices tables. Includes default plan data (Free, Creator $9.99/mo, Premium $19.99/mo with 14-day trial). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81 lines
4.3 KiB
SQL
81 lines
4.3 KiB
SQL
-- v0.12.1: Plans Premium & Abonnements (F001-F030 business)
|
|
-- Subscription plans, user subscriptions, invoices
|
|
|
|
-- Subscription plans definition
|
|
CREATE TABLE IF NOT EXISTS subscription_plans (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(50) NOT NULL UNIQUE, -- 'free', 'creator', 'premium'
|
|
display_name VARCHAR(100) NOT NULL,
|
|
description TEXT,
|
|
price_monthly_cents INTEGER NOT NULL DEFAULT 0,
|
|
price_yearly_cents INTEGER NOT NULL DEFAULT 0,
|
|
currency VARCHAR(3) NOT NULL DEFAULT 'USD',
|
|
upload_limit_monthly INTEGER, -- NULL = unlimited
|
|
storage_limit_bytes BIGINT NOT NULL DEFAULT 0,
|
|
marketplace_commission_rate NUMERIC(5,4) DEFAULT 0, -- 0.15 = 15%
|
|
can_sell_on_marketplace BOOLEAN NOT NULL DEFAULT false,
|
|
has_priority_support BOOLEAN NOT NULL DEFAULT false,
|
|
has_collaboration_tools BOOLEAN NOT NULL DEFAULT false,
|
|
has_distribution BOOLEAN NOT NULL DEFAULT false,
|
|
trial_days INTEGER NOT NULL DEFAULT 0,
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- User subscriptions
|
|
CREATE TABLE IF NOT EXISTS user_subscriptions (
|
|
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 subscription_plans(id),
|
|
status VARCHAR(30) NOT NULL DEFAULT 'active', -- active, trialing, canceled, past_due, expired
|
|
billing_cycle VARCHAR(10) NOT NULL DEFAULT 'monthly', -- monthly, yearly
|
|
current_period_start TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
current_period_end TIMESTAMPTZ NOT NULL,
|
|
trial_start TIMESTAMPTZ,
|
|
trial_end TIMESTAMPTZ,
|
|
canceled_at TIMESTAMPTZ,
|
|
cancel_at_period_end BOOLEAN NOT NULL DEFAULT false,
|
|
hyperswitch_subscription_id VARCHAR(255),
|
|
hyperswitch_customer_id VARCHAR(255),
|
|
payment_method_id VARCHAR(255),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Each user can have only one active subscription at a time
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_user_subscriptions_active
|
|
ON user_subscriptions(user_id)
|
|
WHERE status IN ('active', 'trialing');
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_user ON user_subscriptions(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_status ON user_subscriptions(status);
|
|
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_period_end ON user_subscriptions(current_period_end);
|
|
|
|
-- Subscription invoices
|
|
CREATE TABLE IF NOT EXISTS subscription_invoices (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
subscription_id UUID NOT NULL REFERENCES user_subscriptions(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
amount_cents INTEGER NOT NULL,
|
|
currency VARCHAR(3) NOT NULL DEFAULT 'USD',
|
|
status VARCHAR(30) NOT NULL DEFAULT 'pending', -- pending, paid, failed, refunded
|
|
billing_period_start TIMESTAMPTZ NOT NULL,
|
|
billing_period_end TIMESTAMPTZ NOT NULL,
|
|
hyperswitch_payment_id VARCHAR(255),
|
|
paid_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_subscription_invoices_user ON subscription_invoices(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_subscription_invoices_subscription ON subscription_invoices(subscription_id);
|
|
CREATE INDEX IF NOT EXISTS idx_subscription_invoices_status ON subscription_invoices(status);
|
|
|
|
-- Insert default plans
|
|
INSERT INTO subscription_plans (name, display_name, description, price_monthly_cents, price_yearly_cents, currency, upload_limit_monthly, storage_limit_bytes, marketplace_commission_rate, can_sell_on_marketplace, has_priority_support, has_collaboration_tools, has_distribution, trial_days, sort_order)
|
|
VALUES
|
|
('free', 'Free', 'Get started with Veza. Upload up to 5 tracks per month.', 0, 0, 'USD', 5, 1073741824, 0, false, false, false, false, 0, 0),
|
|
('creator', 'Creator', 'For active creators. Unlimited uploads, sell on the marketplace.', 999, 9999, 'USD', NULL, 53687091200, 0.1500, true, false, false, false, 0, 1),
|
|
('premium', 'Premium', 'Full access. Priority support, collaboration tools, and distribution.', 1999, 19999, 'USD', NULL, 214748364800, 0.1000, true, true, true, true, 14, 2)
|
|
ON CONFLICT (name) DO NOTHING;
|