-- Minimal setup migration - creates essential tables needed by complete migration BEGIN; -- Users table CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, phone VARCHAR(50), password_hash TEXT, full_name VARCHAR(255), account_type VARCHAR(50) DEFAULT 'USER', email_verified BOOLEAN DEFAULT false, phone_verified BOOLEAN DEFAULT false, status VARCHAR(50) DEFAULT 'ACTIVE', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_login_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ ); -- Roles table CREATE TABLE IF NOT EXISTS roles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(100) NOT NULL UNIQUE, code VARCHAR(50) NOT NULL UNIQUE, description TEXT, can_approve_requests BOOLEAN DEFAULT false, can_manage_system_settings BOOLEAN DEFAULT false, audience VARCHAR(50) DEFAULT 'USER', is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- User roles table CREATE TABLE IF NOT EXISTS user_roles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE, status VARCHAR(50) NOT NULL DEFAULT 'ACTIVE', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Role permissions table CREATE TABLE IF NOT EXISTS role_permissions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE, permission VARCHAR(100) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Departments table CREATE TABLE IF NOT EXISTS departments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, code VARCHAR(50), description TEXT, department_head UUID REFERENCES users(id), department_email VARCHAR(255), visibility VARCHAR(50) DEFAULT 'VISIBLE', transfers_enabled BOOLEAN DEFAULT false, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Designations table CREATE TABLE IF NOT EXISTS designations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, code VARCHAR(50), department_id UUID REFERENCES departments(id) ON DELETE SET NULL, description TEXT, level INTEGER DEFAULT 1, can_manage_team BOOLEAN DEFAULT false, can_approve BOOLEAN DEFAULT false, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Employees table CREATE TABLE IF NOT EXISTS employees ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, department_id UUID REFERENCES departments(id) ON DELETE SET NULL, designation_id UUID REFERENCES designations(id) ON DELETE SET NULL, status VARCHAR(50) DEFAULT 'ACTIVE', joining_date DATE, employment_status VARCHAR(50), manager_employee_id UUID REFERENCES employees(id), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Refresh tokens table CREATE TABLE IF NOT EXISTS refresh_tokens ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, token_hash VARCHAR(255) NOT NULL UNIQUE, expires_at TIMESTAMPTZ NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Notification preferences table CREATE TABLE IF NOT EXISTS notification_preferences ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, email_enabled BOOLEAN DEFAULT true, push_enabled BOOLEAN DEFAULT true, sms_enabled BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Profile extension tables (with user_role_profile_id for new schema) CREATE TABLE IF NOT EXISTS photographer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, equipment_list TEXT, years_of_experience INTEGER, hourly_rate INTEGER, specialties TEXT[] DEFAULT '{}', camera_brands TEXT[] DEFAULT '{}', studio_available BOOLEAN DEFAULT false, outdoor_shoots BOOLEAN DEFAULT true, travel_radius_km INTEGER DEFAULT 50, starting_price_inr INTEGER DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS tutor_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, subjects TEXT[] DEFAULT '{}', board_types TEXT[] DEFAULT '{}', qualification VARCHAR(255), teaches_online BOOLEAN DEFAULT true, teaches_offline BOOLEAN DEFAULT true, experience_years INTEGER DEFAULT 0, hourly_rate_inr INTEGER DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS makeup_artist_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, specialties TEXT[] DEFAULT '{}', experience_years INTEGER DEFAULT 0, hourly_rate INTEGER DEFAULT 0, willing_to_travel BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS developer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, skills TEXT[] DEFAULT '{}', experience_years INTEGER DEFAULT 0, hourly_rate INTEGER DEFAULT 0, preferred_roles TEXT[] DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS video_editor_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, software_expertise TEXT[] DEFAULT '{}', experience_years INTEGER DEFAULT 0, hourly_rate INTEGER DEFAULT 0, portfolio_url TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS graphic_designer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, design_specialties TEXT[] DEFAULT '{}', experience_years INTEGER DEFAULT 0, hourly_rate INTEGER DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS social_media_manager_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, platforms_managed TEXT[] DEFAULT '{}', experience_years INTEGER DEFAULT 0, hourly_rate INTEGER DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS fitness_trainer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, certifications TEXT[] DEFAULT '{}', specializations TEXT[] DEFAULT '{}', experience_years INTEGER DEFAULT 0, hourly_rate INTEGER DEFAULT 0, offers_online_sessions BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS catering_service_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, cuisine_types TEXT[] DEFAULT '{}', min_order_amount INTEGER DEFAULT 0, experience_years INTEGER DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS ugc_content_creator_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID, platforms TEXT[] DEFAULT '{}', follower_count INTEGER DEFAULT 0, niche TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Company profiles CREATE TABLE IF NOT EXISTS company_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, company_name VARCHAR(255) NOT NULL, registration_number VARCHAR(100), industry VARCHAR(150), website_url VARCHAR(255), employee_count INTEGER, business_type VARCHAR(100), gst_number VARCHAR(50), contact_name VARCHAR(255), contact_email VARCHAR(255), contact_phone VARCHAR(50), address_line1 TEXT, city VARCHAR(100), state VARCHAR(100), country VARCHAR(100) DEFAULT 'India', postal_code VARCHAR(20), status VARCHAR(50) DEFAULT 'ACTIVE', free_job_slots INTEGER DEFAULT 3, purchased_job_slots INTEGER DEFAULT 0, free_contact_views INTEGER DEFAULT 10, purchased_contact_views INTEGER DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE(user_id) ); -- Customer profiles CREATE TABLE IF NOT EXISTS customer_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, full_name VARCHAR(255), phone VARCHAR(50), city VARCHAR(100), area VARCHAR(100), preferred_professions TEXT[] DEFAULT '{}', active_requirement_count INTEGER DEFAULT 0, status VARCHAR(50) DEFAULT 'ACTIVE', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE(user_id) ); -- Job seeker profiles CREATE TABLE IF NOT EXISTS job_seeker_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, full_name VARCHAR(255), location VARCHAR(255), summary TEXT, experience_years INTEGER DEFAULT 0, skills TEXT[] DEFAULT '{}', resume_url TEXT, active_application_count INTEGER DEFAULT 0, status VARCHAR(50) DEFAULT 'ACTIVE', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE(user_id) ); -- Jobs table CREATE TABLE IF NOT EXISTS jobs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), company_id UUID REFERENCES company_profiles(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, description TEXT, requirements TEXT, location VARCHAR(255), job_type VARCHAR(50), experience_min INTEGER DEFAULT 0, experience_max INTEGER DEFAULT 0, salary_min INTEGER, salary_max INTEGER, status VARCHAR(50) DEFAULT 'ACTIVE', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Job applications table CREATE TABLE IF NOT EXISTS job_applications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), job_id UUID NOT NULL REFERENCES jobs(id) ON DELETE CASCADE, applicant_user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, cover_letter TEXT, resume_url TEXT, status VARCHAR(50) DEFAULT 'PENDING', applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Create user_role_profiles first (needed by leads table) CREATE TABLE IF NOT EXISTS user_role_profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, role_key VARCHAR(50) NOT NULL, display_name TEXT, bio TEXT, location TEXT, avatar_url TEXT, phone TEXT, email TEXT, status VARCHAR(50) NOT NULL DEFAULT 'ACTIVE', verification_status VARCHAR(50) DEFAULT 'PENDING', approval_status VARCHAR(50) DEFAULT 'PENDING', rejection_reason TEXT, approved_at TIMESTAMPTZ, verified_at TIMESTAMPTZ, is_profile_public BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE(user_id, role_key) ); CREATE INDEX IF NOT EXISTS idx_user_role_profiles_user_id ON user_role_profiles(user_id); CREATE INDEX IF NOT EXISTS idx_user_role_profiles_role_key ON user_role_profiles(role_key); CREATE INDEX IF NOT EXISTS idx_user_role_profiles_status ON user_role_profiles(status); -- Leads table (renamed from requirements) CREATE TABLE IF NOT EXISTS leads ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID REFERENCES user_role_profiles(id), customer_id UUID REFERENCES users(id), profession_key VARCHAR(50), title VARCHAR(255) NOT NULL, description TEXT, location VARCHAR(255), budget_min INTEGER, budget_max INTEGER, urgency VARCHAR(50) DEFAULT 'NORMAL', status VARCHAR(50) DEFAULT 'OPEN', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Other essential tables CREATE TABLE IF NOT EXISTS notifications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, message TEXT NOT NULL, notification_type VARCHAR(50), reference_id UUID, is_read BOOLEAN DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS reviews ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID NOT NULL REFERENCES user_role_profiles(id), reviewer_user_id UUID NOT NULL REFERENCES users(id), rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5), comment TEXT, status VARCHAR(50) DEFAULT 'VISIBLE', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS tracecoin_wallets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, balance BIGINT DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS tracecoin_ledger ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), wallet_id UUID NOT NULL REFERENCES tracecoin_wallets(id), transaction_type VARCHAR(50) NOT NULL, amount BIGINT NOT NULL, balance_after BIGINT NOT NULL, reference_type VARCHAR(50), reference_id UUID, description TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS services ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID REFERENCES user_role_profiles(id), service_name VARCHAR(255) NOT NULL, description TEXT, price INTEGER, price_type VARCHAR(50) DEFAULT 'FIXED', duration_minutes INTEGER, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS pricing_packages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID REFERENCES user_role_profiles(id), name VARCHAR(255) NOT NULL, description TEXT, price INTEGER NOT NULL, duration_days INTEGER, features JSONB, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS coupons ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), code VARCHAR(50) NOT NULL UNIQUE, discount_type VARCHAR(20) NOT NULL, discount_value INTEGER NOT NULL, min_order_amount INTEGER DEFAULT 0, max_uses INTEGER, used_count INTEGER DEFAULT 0, valid_from TIMESTAMPTZ, valid_until TIMESTAMPTZ, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS coupon_redemptions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), coupon_id UUID NOT NULL REFERENCES coupons(id), user_id UUID NOT NULL REFERENCES users(id), redeemed_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS discounts ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), package_id UUID NOT NULL REFERENCES pricing_packages(id), discount_type VARCHAR(20) NOT NULL, discount_value INTEGER NOT NULL, valid_from TIMESTAMPTZ, valid_until TIMESTAMPTZ, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS payments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id), amount INTEGER NOT NULL, currency VARCHAR(10) DEFAULT 'INR', payment_method VARCHAR(50), payment_status VARCHAR(50) DEFAULT 'PENDING', reference_id VARCHAR(255), transaction_id VARCHAR(255), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS invoices ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id), invoice_number VARCHAR(50) NOT NULL UNIQUE, amount INTEGER NOT NULL, status VARCHAR(50) DEFAULT 'DRAFT', issued_at TIMESTAMPTZ, due_at TIMESTAMPTZ, paid_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS portfolio_items ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID REFERENCES user_role_profiles(id), title VARCHAR(255) NOT NULL, description TEXT, media_url TEXT, media_type VARCHAR(50), display_order INTEGER DEFAULT 0, is_featured BOOLEAN DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS verification_requests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID REFERENCES user_role_profiles(id), verification_type VARCHAR(50) NOT NULL DEFAULT 'IDENTITY', status VARCHAR(50) NOT NULL DEFAULT 'PENDING', submitted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), reviewed_at TIMESTAMPTZ, reviewed_by_user_id UUID REFERENCES users(id), remarks TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS verification_documents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), verification_request_id UUID NOT NULL REFERENCES verification_requests(id) ON DELETE CASCADE, document_type VARCHAR(100) NOT NULL, file_url TEXT NOT NULL, file_name TEXT, mime_type TEXT, status VARCHAR(50) DEFAULT 'PENDING', uploaded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), reviewed_at TIMESTAMPTZ, reviewed_by_user_id UUID REFERENCES users(id), remarks TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS verification_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), verification_request_id UUID NOT NULL REFERENCES verification_requests(id), action VARCHAR(50) NOT NULL, old_status VARCHAR(50), new_status VARCHAR(50), acted_by_user_id UUID REFERENCES users(id), remarks TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS verifications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_role_profile_id UUID NOT NULL REFERENCES user_role_profiles(id), verification_type VARCHAR(50) NOT NULL, document_url TEXT, status VARCHAR(50) DEFAULT 'PENDING', verified_at TIMESTAMPTZ, verified_by UUID REFERENCES users(id), rejection_reason TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS user_settings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, theme VARCHAR(20) DEFAULT 'LIGHT', language VARCHAR(10) DEFAULT 'en', timezone VARCHAR(50) DEFAULT 'Asia/Kolkata', email_notifications BOOLEAN DEFAULT true, push_notifications BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS account_deletion_requests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, reason TEXT, scheduled_deletion_at TIMESTAMPTZ, status VARCHAR(50) DEFAULT 'PENDING', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS activity_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id), action VARCHAR(100) NOT NULL, entity_type VARCHAR(50), entity_id UUID, metadata JSONB, ip_address TEXT, user_agent TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS email_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id), email_type VARCHAR(50) NOT NULL, recipient_email VARCHAR(255) NOT NULL, subject VARCHAR(255), status VARCHAR(50) DEFAULT 'SENT', error_message TEXT, sent_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- KB tables CREATE TABLE IF NOT EXISTS kb_categories ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, slug VARCHAR(255) NOT NULL UNIQUE, description TEXT, display_order INTEGER DEFAULT 0, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS kb_articles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), category_id UUID REFERENCES kb_categories(id) ON DELETE SET NULL, title VARCHAR(255) NOT NULL, slug VARCHAR(255) NOT NULL UNIQUE, content TEXT, summary TEXT, tags TEXT[], views_count INTEGER DEFAULT 0, is_published BOOLEAN DEFAULT false, is_featured BOOLEAN DEFAULT false, published_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Support tables CREATE TABLE IF NOT EXISTS support_tickets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id), subject VARCHAR(255) NOT NULL, description TEXT, priority VARCHAR(20) DEFAULT 'MEDIUM', status VARCHAR(50) DEFAULT 'OPEN', assigned_to UUID REFERENCES users(id), resolved_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS support_ticket_messages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), ticket_id UUID NOT NULL REFERENCES support_tickets(id) ON DELETE CASCADE, sender_id UUID NOT NULL REFERENCES users(id), message TEXT NOT NULL, is_internal BOOLEAN DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Config tables CREATE TABLE IF NOT EXISTS runtime_configs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), config_key VARCHAR(100) NOT NULL UNIQUE, config_value JSONB NOT NULL, description TEXT, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS onboarding_configs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), role_key VARCHAR(50) NOT NULL, steps JSONB NOT NULL, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS dashboard_configs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), role_key VARCHAR(50) NOT NULL, audience VARCHAR(50) DEFAULT 'USER', widgets JSONB NOT NULL, is_active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Create indexes CREATE INDEX IF NOT EXISTS idx_user_roles_user_id ON user_roles(user_id); CREATE INDEX IF NOT EXISTS idx_user_roles_role_id ON user_roles(role_id); CREATE INDEX IF NOT EXISTS idx_user_roles_status ON user_roles(status); CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON notifications(user_id); CREATE INDEX IF NOT EXISTS idx_notifications_is_read ON notifications(is_read); CREATE INDEX IF NOT EXISTS idx_reviews_user_role_profile_id ON reviews(user_role_profile_id); CREATE INDEX IF NOT EXISTS idx_services_user_role_profile_id ON services(user_role_profile_id); CREATE INDEX IF NOT EXISTS idx_pricing_packages_user_role_profile_id ON pricing_packages(user_role_profile_id); CREATE INDEX IF NOT EXISTS idx_portfolio_items_user_role_profile_id ON portfolio_items(user_role_profile_id); CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status); CREATE INDEX IF NOT EXISTS idx_jobs_company_id ON jobs(company_id); CREATE INDEX IF NOT EXISTS idx_job_applications_job_id ON job_applications(job_id); CREATE INDEX IF NOT EXISTS idx_job_applications_applicant ON job_applications(applicant_user_id); CREATE INDEX IF NOT EXISTS idx_leads_status ON leads(status); CREATE INDEX IF NOT EXISTS idx_leads_user_role_profile_id ON leads(user_role_profile_id); CREATE INDEX IF NOT EXISTS idx_tracecoin_ledger_wallet_id ON tracecoin_ledger(wallet_id); CREATE INDEX IF NOT EXISTS idx_coupons_code ON coupons(code); CREATE INDEX IF NOT EXISTS idx_support_tickets_user_id ON support_tickets(user_id); CREATE INDEX IF NOT EXISTS idx_support_tickets_status ON support_tickets(status); CREATE INDEX IF NOT EXISTS idx_activity_logs_user_id ON activity_logs(user_id); CREATE INDEX IF NOT EXISTS idx_activity_logs_created_at ON activity_logs(created_at); CREATE INDEX IF NOT EXISTS idx_email_logs_user_id ON email_logs(user_id); CREATE INDEX IF NOT EXISTS idx_email_logs_sent_at ON email_logs(sent_at); CREATE INDEX IF NOT EXISTS idx_kb_articles_category_id ON kb_articles(category_id); CREATE INDEX IF NOT EXISTS idx_kb_articles_slug ON kb_articles(slug); CREATE INDEX IF NOT EXISTS idx_verification_requests_user_role_profile_id ON verification_requests(user_role_profile_id); CREATE INDEX IF NOT EXISTS idx_verifications_user_role_profile_id ON verifications(user_role_profile_id); CREATE INDEX IF NOT EXISTS idx_user_settings_user_id ON user_settings(user_id); -- Insert default roles INSERT INTO roles (id, name, code, description, audience, is_active) VALUES ('00000000-0000-0000-0000-000000000001', 'Super Admin', 'SUPER_ADMIN', 'Full system access', 'ADMIN', true), ('00000000-0000-0000-0000-000000000002', 'Admin', 'ADMIN', 'Administrative access', 'ADMIN', true), ('00000000-0000-0000-0000-000000000003', 'User', 'USER', 'Regular user', 'USER', true), ('00000000-0000-0000-0000-000000000004', 'Company', 'COMPANY', 'Company account', 'BUSINESS', true), ('00000000-0000-0000-0000-000000000005', 'Customer', 'CUSTOMER', 'Customer account', 'USER', true) ON CONFLICT (code) DO NOTHING; COMMIT;