-- Drop the generic professionals table approach; use per-profession profile tables -- Portfolio and services stay shared (referenced by user_id + profession_key) -- 1. PHOTOGRAPHER PROFILES CREATE TABLE IF NOT EXISTS photographer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, display_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific specialties TEXT[] DEFAULT '{}', -- e.g. ['Wedding', 'Portrait', 'Commercial'] camera_brands TEXT[] DEFAULT '{}', -- e.g. ['Sony', 'Canon'] studio_available BOOLEAN NOT NULL DEFAULT false, outdoor_shoots BOOLEAN NOT NULL DEFAULT true, travel_radius_km INTEGER DEFAULT 50, starting_price_inr INTEGER DEFAULT 0, -- in paise -- Verification & status status VARCHAR(50) NOT NULL DEFAULT 'PENDING', -- PENDING, APPROVED, REJECTED, SUSPENDED rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- 2. TUTOR PROFILES CREATE TABLE IF NOT EXISTS tutor_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, display_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific subjects TEXT[] DEFAULT '{}', -- e.g. ['Math', 'Physics', 'Hindi'] board_types TEXT[] DEFAULT '{}', -- e.g. ['CBSE', 'ICSE', 'IB'] qualification VARCHAR(255), -- e.g. 'B.Tech IIT Delhi' teaches_online BOOLEAN NOT NULL DEFAULT true, teaches_offline BOOLEAN NOT NULL DEFAULT true, experience_years INTEGER DEFAULT 0, hourly_rate_inr INTEGER DEFAULT 0, -- in paise status VARCHAR(50) NOT NULL DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- 3. MAKEUP ARTIST PROFILES CREATE TABLE IF NOT EXISTS makeup_artist_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, display_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific specializations TEXT[] DEFAULT '{}', -- e.g. ['Bridal', 'Editorial', 'SFX'] kit_brands TEXT[] DEFAULT '{}', -- e.g. ['MAC', 'NARS', 'NYX'] home_service BOOLEAN NOT NULL DEFAULT true, studio_available BOOLEAN NOT NULL DEFAULT false, starting_price_inr INTEGER DEFAULT 0, status VARCHAR(50) NOT NULL DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- 4. DEVELOPER PROFILES CREATE TABLE IF NOT EXISTS developer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, display_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific tech_stack TEXT[] DEFAULT '{}', -- e.g. ['Rust', 'React', 'PostgreSQL'] github_url VARCHAR(500), portfolio_url VARCHAR(500), experience_years INTEGER DEFAULT 0, availability VARCHAR(50) DEFAULT 'FULL_TIME', -- FULL_TIME, PART_TIME, FREELANCE hourly_rate_inr INTEGER DEFAULT 0, remote_ok BOOLEAN NOT NULL DEFAULT true, status VARCHAR(50) NOT NULL DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- 5. VIDEO EDITOR PROFILES CREATE TABLE IF NOT EXISTS video_editor_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, display_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific software_skills TEXT[] DEFAULT '{}', -- e.g. ['Premiere Pro', 'DaVinci Resolve'] style_tags TEXT[] DEFAULT '{}', -- e.g. ['Cinematic', 'Corporate', 'Reels'] turnaround_days INTEGER DEFAULT 7, reel_url VARCHAR(500), starting_price_inr INTEGER DEFAULT 0, status VARCHAR(50) NOT NULL DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- 6. GRAPHIC DESIGNER PROFILES CREATE TABLE IF NOT EXISTS graphic_designer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, display_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific design_tools TEXT[] DEFAULT '{}', -- e.g. ['Figma', 'Illustrator', 'Photoshop'] style_tags TEXT[] DEFAULT '{}', -- e.g. ['Minimalist', 'Bold', 'Corporate'] brand_experience BOOLEAN NOT NULL DEFAULT false, portfolio_url VARCHAR(500), starting_price_inr INTEGER DEFAULT 0, status VARCHAR(50) NOT NULL DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- 7. SOCIAL MEDIA MANAGER PROFILES CREATE TABLE IF NOT EXISTS social_media_manager_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, display_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific platforms TEXT[] DEFAULT '{}', -- e.g. ['Instagram', 'LinkedIn', 'YouTube'] industries TEXT[] DEFAULT '{}', -- e.g. ['F&B', 'Fashion', 'Real Estate'] content_types TEXT[] DEFAULT '{}', -- e.g. ['Reels', 'Carousels', 'Stories'] avg_follower_growth_pct INTEGER DEFAULT 0, starting_price_inr INTEGER DEFAULT 0, status VARCHAR(50) NOT NULL DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- 8. FITNESS TRAINER PROFILES CREATE TABLE IF NOT EXISTS fitness_trainer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, display_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific disciplines TEXT[] DEFAULT '{}', -- e.g. ['Yoga', 'HIIT', 'Zumba', 'CrossFit'] certifications TEXT[] DEFAULT '{}', -- e.g. ['ACE', 'NASM', 'Yoga Alliance RYT'] online_sessions BOOLEAN NOT NULL DEFAULT true, home_visits BOOLEAN NOT NULL DEFAULT false, gym_based BOOLEAN NOT NULL DEFAULT false, per_session_rate_inr INTEGER DEFAULT 0, status VARCHAR(50) NOT NULL DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- 9. CATERING SERVICES PROFILES CREATE TABLE IF NOT EXISTS catering_service_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, business_name VARCHAR(255) NOT NULL, bio TEXT, location VARCHAR(255), -- Profession-specific cuisine_types TEXT[] DEFAULT '{}', -- e.g. ['North Indian', 'Continental', 'Vegan'] event_types TEXT[] DEFAULT '{}', -- e.g. ['Wedding', 'Corporate', 'Birthday'] min_guests INTEGER DEFAULT 10, max_guests INTEGER DEFAULT 500, has_setup_team BOOLEAN NOT NULL DEFAULT true, has_serving_staff BOOLEAN NOT NULL DEFAULT true, price_per_head_inr INTEGER DEFAULT 0, -- in paise status VARCHAR(50) NOT NULL DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Shared: portfolio_items now uses user_id + profession_key (no foreign key to professionals) -- Drop the professionals-table FK if it was added before ALTER TABLE portfolio_items ADD COLUMN IF NOT EXISTS user_id UUID REFERENCES users(id) ON DELETE CASCADE, ADD COLUMN IF NOT EXISTS profession_key VARCHAR(50); ALTER TABLE services ADD COLUMN IF NOT EXISTS user_id UUID REFERENCES users(id) ON DELETE CASCADE, ADD COLUMN IF NOT EXISTS profession_key VARCHAR(50); -- Lead requests: use user_id instead of professional_id foreign key ALTER TABLE lead_requests ADD COLUMN IF NOT EXISTS professional_user_id UUID REFERENCES users(id) ON DELETE CASCADE; -- Backfill columns when legacy minimal profile tables already exist. -- This keeps migrations idempotent while upgrading old schemas to the new profile shape. ALTER TABLE photographer_profiles ADD COLUMN IF NOT EXISTS display_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS bio TEXT, ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS specialties TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS camera_brands TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS studio_available BOOLEAN NOT NULL DEFAULT false, ADD COLUMN IF NOT EXISTS outdoor_shoots BOOLEAN NOT NULL DEFAULT true, ADD COLUMN IF NOT EXISTS travel_radius_km INTEGER DEFAULT 50, ADD COLUMN IF NOT EXISTS starting_price_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE tutor_profiles ADD COLUMN IF NOT EXISTS display_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS bio TEXT, ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS subjects TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS board_types TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS qualification VARCHAR(255), ADD COLUMN IF NOT EXISTS teaches_online BOOLEAN NOT NULL DEFAULT true, ADD COLUMN IF NOT EXISTS teaches_offline BOOLEAN NOT NULL DEFAULT true, ADD COLUMN IF NOT EXISTS hourly_rate_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE makeup_artist_profiles ADD COLUMN IF NOT EXISTS display_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS specializations TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS kit_brands TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS home_service BOOLEAN NOT NULL DEFAULT true, ADD COLUMN IF NOT EXISTS studio_available BOOLEAN NOT NULL DEFAULT false, ADD COLUMN IF NOT EXISTS starting_price_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE developer_profiles ADD COLUMN IF NOT EXISTS display_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS tech_stack TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS github_url VARCHAR(500), ADD COLUMN IF NOT EXISTS portfolio_url VARCHAR(500), ADD COLUMN IF NOT EXISTS availability VARCHAR(50) DEFAULT 'FULL_TIME', ADD COLUMN IF NOT EXISTS hourly_rate_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS remote_ok BOOLEAN NOT NULL DEFAULT true, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE video_editor_profiles ADD COLUMN IF NOT EXISTS display_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS software_skills TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS style_tags TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS turnaround_days INTEGER DEFAULT 7, ADD COLUMN IF NOT EXISTS reel_url VARCHAR(500), ADD COLUMN IF NOT EXISTS starting_price_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE graphic_designer_profiles ADD COLUMN IF NOT EXISTS display_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS design_tools TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS style_tags TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS brand_experience BOOLEAN NOT NULL DEFAULT false, ADD COLUMN IF NOT EXISTS portfolio_url VARCHAR(500), ADD COLUMN IF NOT EXISTS starting_price_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE social_media_manager_profiles ADD COLUMN IF NOT EXISTS display_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS platforms TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS industries TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS content_types TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS avg_follower_growth_pct INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS starting_price_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE fitness_trainer_profiles ADD COLUMN IF NOT EXISTS display_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS disciplines TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS certifications TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS online_sessions BOOLEAN NOT NULL DEFAULT true, ADD COLUMN IF NOT EXISTS home_visits BOOLEAN NOT NULL DEFAULT false, ADD COLUMN IF NOT EXISTS gym_based BOOLEAN NOT NULL DEFAULT false, ADD COLUMN IF NOT EXISTS per_session_rate_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE catering_service_profiles ADD COLUMN IF NOT EXISTS business_name VARCHAR(255) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS location VARCHAR(255), ADD COLUMN IF NOT EXISTS cuisine_types TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS event_types TEXT[] DEFAULT '{}', ADD COLUMN IF NOT EXISTS min_guests INTEGER DEFAULT 10, ADD COLUMN IF NOT EXISTS max_guests INTEGER DEFAULT 500, ADD COLUMN IF NOT EXISTS has_setup_team BOOLEAN NOT NULL DEFAULT true, ADD COLUMN IF NOT EXISTS has_serving_staff BOOLEAN NOT NULL DEFAULT true, ADD COLUMN IF NOT EXISTS price_per_head_inr INTEGER DEFAULT 0, ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'PENDING', ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ; ALTER TABLE lead_requests ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(); -- Indexes CREATE INDEX IF NOT EXISTS idx_photographer_profiles_status ON photographer_profiles(status); CREATE INDEX IF NOT EXISTS idx_tutor_profiles_status ON tutor_profiles(status); CREATE INDEX IF NOT EXISTS idx_makeup_artist_profiles_status ON makeup_artist_profiles(status); CREATE INDEX IF NOT EXISTS idx_developer_profiles_status ON developer_profiles(status); CREATE INDEX IF NOT EXISTS idx_video_editor_profiles_status ON video_editor_profiles(status); CREATE INDEX IF NOT EXISTS idx_graphic_designer_profiles_status ON graphic_designer_profiles(status); CREATE INDEX IF NOT EXISTS idx_social_media_manager_profiles_status ON social_media_manager_profiles(status); CREATE INDEX IF NOT EXISTS idx_fitness_trainer_profiles_status ON fitness_trainer_profiles(status); CREATE INDEX IF NOT EXISTS idx_catering_service_profiles_status ON catering_service_profiles(status); CREATE INDEX IF NOT EXISTS idx_portfolio_items_user_id ON portfolio_items(user_id); CREATE INDEX IF NOT EXISTS idx_services_user_id ON services(user_id);