-- Custom Page Templates Schema -- Reusable page templates that can be applied to multiple events CREATE TABLE custom_page_templates ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, -- Template configuration name VARCHAR(255) NOT NULL, description TEXT, is_active BOOLEAN DEFAULT true, -- Craft.js configuration page_data JSONB NOT NULL DEFAULT '{}', -- Stores the Craft.js page structure custom_css TEXT, -- Additional custom CSS -- Template preview preview_image_url TEXT, -- Tracking created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), created_by UUID REFERENCES users(id), updated_by UUID REFERENCES users(id) ); -- Custom Sales Pages Schema -- Links events to custom page templates with custom URLs CREATE TABLE custom_sales_pages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE, template_id UUID REFERENCES custom_page_templates(id) ON DELETE SET NULL, -- Custom URL configuration custom_slug VARCHAR(100) NOT NULL UNIQUE, -- For blackcanyontickets.com/xxxx is_active BOOLEAN DEFAULT false, is_default BOOLEAN DEFAULT false, -- If true, this page is used instead of default /e/[slug] -- Page-specific overrides (if different from template) page_data JSONB, -- If set, overrides template page_data custom_css TEXT, -- Additional CSS on top of template -- SEO and metadata meta_title VARCHAR(255), meta_description TEXT, og_image_url TEXT, -- Analytics view_count INTEGER DEFAULT 0, last_viewed_at TIMESTAMP WITH TIME ZONE, -- Tracking created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), created_by UUID REFERENCES users(id), updated_by UUID REFERENCES users(id) ); -- Custom Pricing System Schema -- Special pricing controls for superusers CREATE TABLE custom_pricing_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE, -- Stripe account configuration stripe_account_id VARCHAR(255), -- Personal Stripe account ID use_personal_stripe BOOLEAN DEFAULT false, -- Pricing overrides can_override_pricing BOOLEAN DEFAULT false, can_set_custom_fees BOOLEAN DEFAULT false, -- Custom fee structure custom_platform_fee_type VARCHAR(20) CHECK (custom_platform_fee_type IN ('percentage', 'fixed', 'none')), custom_platform_fee_percentage DECIMAL(5,2), custom_platform_fee_fixed INTEGER, -- in cents created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Event-specific pricing overrides CREATE TABLE event_pricing_overrides ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE, custom_pricing_profile_id UUID NOT NULL REFERENCES custom_pricing_profiles(id) ON DELETE CASCADE, -- Override settings use_custom_stripe_account BOOLEAN DEFAULT false, override_platform_fees BOOLEAN DEFAULT false, -- Custom fee values for this event platform_fee_type VARCHAR(20) CHECK (platform_fee_type IN ('percentage', 'fixed', 'none')), platform_fee_percentage DECIMAL(5,2), platform_fee_fixed INTEGER, -- in cents created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- RLS Policies ALTER TABLE custom_page_templates ENABLE ROW LEVEL SECURITY; ALTER TABLE custom_sales_pages ENABLE ROW LEVEL SECURITY; ALTER TABLE custom_pricing_profiles ENABLE ROW LEVEL SECURITY; ALTER TABLE event_pricing_overrides ENABLE ROW LEVEL SECURITY; -- Custom page templates policies CREATE POLICY "Users can view custom page templates for their organization" ON custom_page_templates FOR SELECT USING ( organization_id IN ( SELECT organization_id FROM users WHERE id = auth.uid() ) ); CREATE POLICY "Users can manage custom page templates for their organization" ON custom_page_templates FOR ALL USING ( organization_id IN ( SELECT organization_id FROM users WHERE id = auth.uid() ) ); -- Custom sales pages policies CREATE POLICY "Users can view custom sales pages for their organization" ON custom_sales_pages FOR SELECT USING ( organization_id IN ( SELECT organization_id FROM users WHERE id = auth.uid() ) ); CREATE POLICY "Users can manage custom sales pages for their organization" ON custom_sales_pages FOR ALL USING ( organization_id IN ( SELECT organization_id FROM users WHERE id = auth.uid() ) ); -- Custom pricing profiles policies - restricted to superusers CREATE POLICY "Only superusers can view custom pricing profiles" ON custom_pricing_profiles FOR SELECT USING ( user_id = auth.uid() AND auth.uid() IN (SELECT id FROM users WHERE role = 'admin') ); CREATE POLICY "Only superusers can manage custom pricing profiles" ON custom_pricing_profiles FOR ALL USING ( user_id = auth.uid() AND auth.uid() IN (SELECT id FROM users WHERE role = 'admin') ); -- Event pricing overrides policies CREATE POLICY "Users can view event pricing overrides for their events" ON event_pricing_overrides FOR SELECT USING ( event_id IN ( SELECT e.id FROM events e JOIN users u ON e.organization_id = u.organization_id WHERE u.id = auth.uid() ) ); CREATE POLICY "Only superusers can manage event pricing overrides" ON event_pricing_overrides FOR ALL USING ( custom_pricing_profile_id IN ( SELECT id FROM custom_pricing_profiles WHERE user_id = auth.uid() AND auth.uid() IN (SELECT id FROM users WHERE role = 'admin') ) ); -- Indexes for performance CREATE INDEX idx_custom_page_templates_organization_id ON custom_page_templates(organization_id); CREATE INDEX idx_custom_page_templates_active ON custom_page_templates(is_active) WHERE is_active = true; CREATE INDEX idx_custom_sales_pages_organization_id ON custom_sales_pages(organization_id); CREATE INDEX idx_custom_sales_pages_event_id ON custom_sales_pages(event_id); CREATE INDEX idx_custom_sales_pages_template_id ON custom_sales_pages(template_id); CREATE INDEX idx_custom_sales_pages_slug ON custom_sales_pages(custom_slug) WHERE is_active = true; CREATE INDEX idx_custom_sales_pages_active ON custom_sales_pages(is_active) WHERE is_active = true; CREATE INDEX idx_custom_pricing_profiles_user_id ON custom_pricing_profiles(user_id); CREATE INDEX idx_event_pricing_overrides_event_id ON event_pricing_overrides(event_id); -- Insert initial custom pricing profiles for superusers INSERT INTO custom_pricing_profiles (user_id, can_override_pricing, can_set_custom_fees) SELECT id, true, true FROM users WHERE role = 'admin' ON CONFLICT (user_id) DO UPDATE SET can_override_pricing = true, can_set_custom_fees = true;