feat(v0.12.1): database migrations for subscription plans

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>
This commit is contained in:
senke 2026-03-10 19:36:29 +01:00
parent bf9ae4068f
commit 45d92d291d
2 changed files with 85 additions and 0 deletions

View file

@ -0,0 +1,81 @@
-- 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;

View file

@ -0,0 +1,4 @@
-- v0.12.1: Rollback subscription plans
DROP TABLE IF EXISTS subscription_invoices;
DROP TABLE IF EXISTS user_subscriptions;
DROP TABLE IF EXISTS subscription_plans;