-- Stripe subscription management system
-- Depends on: 001_000_initial_auth_setup.sql
-- Create subscription status enum (only if it doesn't exist)
DO $$ BEGIN
CREATE TYPE subscription_status AS ENUM (
'incomplete',
'incomplete_expired',
'trialing',
'active',
'past_due',
'canceled',
'unpaid'
);
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
-- Create subscriptions table for Stripe integration
CREATE TABLE IF NOT EXISTS subscriptions (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
stripe_customer_id TEXT,
stripe_subscription_id TEXT UNIQUE,
status subscription_status NOT NULL,
price_id TEXT NOT NULL,
current_period_start TIMESTAMPTZ,
current_period_end TIMESTAMPTZ,
cancel_at_period_end BOOLEAN DEFAULT FALSE,
canceled_at TIMESTAMPTZ,
trial_start TIMESTAMPTZ,
trial_end TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);
-- Enable RLS on subscriptions
ALTER TABLE subscriptions ENABLE ROW LEVEL SECURITY;
-- Create policies for subscriptions
CREATE POLICY "Users can view their own subscription" ON subscriptions
FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "Users can insert their own subscription" ON subscriptions
FOR INSERT WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update their own subscription" ON subscriptions
FOR UPDATE USING (auth.uid() = user_id);
-- Create indexes for better performance
CREATE INDEX idx_subscriptions_user_id ON subscriptions(user_id);
CREATE INDEX idx_subscriptions_stripe_subscription_id ON subscriptions(stripe_subscription_id);
CREATE INDEX idx_subscriptions_status ON subscriptions(status);
-- Create trigger to automatically update updated_at
CREATE TRIGGER update_subscriptions_updated_at
BEFORE UPDATE ON subscriptions
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- Create function to get user subscription
CREATE OR REPLACE FUNCTION get_user_subscription(user_uuid UUID)
RETURNS TABLE (
id UUID,
status subscription_status,
price_id TEXT,
current_period_end TIMESTAMPTZ,
cancel_at_period_end BOOLEAN
)
LANGUAGE SQL
SECURITY DEFINER
AS $$
SELECT
s.id,
s.status::subscription_status,
s.price_id,
s.current_period_end,
s.cancel_at_period_end
FROM subscriptions s
WHERE s.user_id = user_uuid
AND s.status IN ('active', 'trialing', 'past_due');
$$;
-- Create function to check if user has active subscription
CREATE OR REPLACE FUNCTION user_has_active_subscription(user_uuid UUID)
RETURNS BOOLEAN
LANGUAGE SQL
SECURITY DEFINER
AS $$
SELECT EXISTS(
SELECT 1
FROM subscriptions
WHERE user_id = user_uuid
AND status IN ('active', 'trialing')
AND (current_period_end IS NULL OR current_period_end > NOW())
);
$$;
-- Add helpful comments
COMMENT ON TABLE subscriptions IS 'Stores user subscription information for Stripe integration';
COMMENT ON COLUMN subscriptions.user_id IS 'Reference to the user who owns this subscription';
COMMENT ON COLUMN subscriptions.stripe_customer_id IS 'Stripe customer ID';
COMMENT ON COLUMN subscriptions.stripe_subscription_id IS 'Stripe subscription ID';
COMMENT ON COLUMN subscriptions.status IS 'Current subscription status from Stripe';
COMMENT ON COLUMN subscriptions.price_id IS 'Stripe price ID for the subscription';
COMMENT ON COLUMN subscriptions.current_period_start IS 'Start of current billing period';
COMMENT ON COLUMN subscriptions.current_period_end IS 'End of current billing period';
COMMENT ON COLUMN subscriptions.cancel_at_period_end IS 'Whether subscription will cancel at period end';
COMMENT ON COLUMN subscriptions.canceled_at IS 'When the subscription was canceled';
COMMENT ON COLUMN subscriptions.trial_start IS 'Start of trial period';
COMMENT ON COLUMN subscriptions.trial_end IS 'End of trial period';