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:
parent
bf9ae4068f
commit
45d92d291d
2 changed files with 85 additions and 0 deletions
81
veza-backend-api/migrations/949_subscription_plans_v0121.sql
Normal file
81
veza-backend-api/migrations/949_subscription_plans_v0121.sql
Normal 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;
|
||||
|
|
@ -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;
|
||||
Loading…
Reference in a new issue