-- Migration: Subscriptions tables for Stripe integration -- Creates: subscriptions, subscription_events, donations, tier_vehicle_selections -- Enable uuid-ossp extension if not already enabled CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- Create subscription status enum CREATE TYPE subscription_status AS ENUM ('active', 'past_due', 'canceled', 'unpaid'); -- Create billing cycle enum CREATE TYPE billing_cycle AS ENUM ('monthly', 'yearly'); -- Create donation status enum CREATE TYPE donation_status AS ENUM ('pending', 'succeeded', 'failed', 'canceled'); -- Create updated_at trigger function if not exists CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; -- Main subscriptions table CREATE TABLE IF NOT EXISTS subscriptions ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id VARCHAR(255) NOT NULL, stripe_customer_id VARCHAR(255) UNIQUE NOT NULL, stripe_subscription_id VARCHAR(255) UNIQUE, tier subscription_tier NOT NULL DEFAULT 'free', billing_cycle billing_cycle, status subscription_status NOT NULL DEFAULT 'active', current_period_start TIMESTAMP WITH TIME ZONE, current_period_end TIMESTAMP WITH TIME ZONE, grace_period_end TIMESTAMP WITH TIME ZONE, cancel_at_period_end BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_subscriptions_user_id FOREIGN KEY (user_id) REFERENCES user_profiles(auth0_sub) ON DELETE CASCADE ); -- Subscription events table (webhook event logging) CREATE TABLE IF NOT EXISTS subscription_events ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), subscription_id UUID NOT NULL, stripe_event_id VARCHAR(255) UNIQUE NOT NULL, event_type VARCHAR(100) NOT NULL, payload JSONB NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_subscription_events_subscription_id FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE CASCADE ); -- Donations table (one-time payments) CREATE TABLE IF NOT EXISTS donations ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id VARCHAR(255) NOT NULL, stripe_payment_intent_id VARCHAR(255) UNIQUE NOT NULL, amount_cents INTEGER NOT NULL, currency VARCHAR(3) NOT NULL DEFAULT 'usd', status donation_status NOT NULL DEFAULT 'pending', created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_donations_user_id FOREIGN KEY (user_id) REFERENCES user_profiles(auth0_sub) ON DELETE CASCADE ); -- Tier vehicle selections table (tracks which vehicles user selected to keep during downgrade) CREATE TABLE IF NOT EXISTS tier_vehicle_selections ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id VARCHAR(255) NOT NULL, vehicle_id UUID NOT NULL, selected_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_tier_vehicle_selections_user_id FOREIGN KEY (user_id) REFERENCES user_profiles(auth0_sub) ON DELETE CASCADE, CONSTRAINT fk_tier_vehicle_selections_vehicle_id FOREIGN KEY (vehicle_id) REFERENCES vehicles(id) ON DELETE CASCADE ); -- Create indexes for performance CREATE INDEX idx_subscriptions_user_id ON subscriptions(user_id); CREATE INDEX idx_subscriptions_stripe_customer_id ON subscriptions(stripe_customer_id); CREATE INDEX idx_subscriptions_stripe_subscription_id ON subscriptions(stripe_subscription_id); CREATE INDEX idx_subscriptions_status ON subscriptions(status); CREATE INDEX idx_subscriptions_tier ON subscriptions(tier); CREATE INDEX idx_subscription_events_subscription_id ON subscription_events(subscription_id); CREATE INDEX idx_subscription_events_stripe_event_id ON subscription_events(stripe_event_id); CREATE INDEX idx_subscription_events_event_type ON subscription_events(event_type); CREATE INDEX idx_subscription_events_created_at ON subscription_events(created_at); CREATE INDEX idx_donations_user_id ON donations(user_id); CREATE INDEX idx_donations_stripe_payment_intent_id ON donations(stripe_payment_intent_id); CREATE INDEX idx_donations_status ON donations(status); CREATE INDEX idx_donations_created_at ON donations(created_at); CREATE INDEX idx_tier_vehicle_selections_user_id ON tier_vehicle_selections(user_id); CREATE INDEX idx_tier_vehicle_selections_vehicle_id ON tier_vehicle_selections(vehicle_id); -- Add updated_at triggers CREATE TRIGGER update_subscriptions_updated_at BEFORE UPDATE ON subscriptions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_donations_updated_at BEFORE UPDATE ON donations FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();