-- Portfolio items (for professionals) CREATE TABLE IF NOT EXISTS portfolio_items ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), professional_id UUID NOT NULL REFERENCES professionals(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, description TEXT, tags TEXT[] DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Portfolio images (multiple images per portfolio item) CREATE TABLE IF NOT EXISTS portfolio_images ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), portfolio_item_id UUID NOT NULL REFERENCES portfolio_items(id) ON DELETE CASCADE, file_url VARCHAR(500) NOT NULL, display_order INTEGER NOT NULL DEFAULT 0 ); -- Services (offered by professionals) CREATE TABLE IF NOT EXISTS services ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), professional_id UUID NOT NULL REFERENCES professionals(id) ON DELETE CASCADE, name VARCHAR(255) NOT NULL, description TEXT, price INTEGER NOT NULL DEFAULT 0, -- in paise duration_minutes INTEGER, is_active BOOLEAN NOT NULL DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Tracecoin wallets (one per user) 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 INTEGER NOT NULL DEFAULT 0, reserved INTEGER NOT NULL DEFAULT 0, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Tracecoin ledger (IMMUTABLE — never update or delete) CREATE TABLE IF NOT EXISTS tracecoin_ledger ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), wallet_id UUID NOT NULL REFERENCES tracecoin_wallets(id), type VARCHAR(20) NOT NULL, -- CREDIT, DEBIT, RESERVE, RELEASE amount INTEGER NOT NULL, reason VARCHAR(100) NOT NULL, -- LEAD_REQUEST, LEAD_ACCEPTED, PURCHASE, ADMIN_CREDIT, LEAD_EXPIRED reference_id UUID, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Pricing packages (Tracecoin bundles, job slots, contact views) CREATE TABLE IF NOT EXISTS pricing_packages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, role_key VARCHAR(50) NOT NULL, package_type VARCHAR(50) NOT NULL, -- JOB_POSTING, CONTACT_VIEWS, TRACECOIN_BUNDLE tracecoins_amount INTEGER NOT NULL DEFAULT 0, price_inr INTEGER NOT NULL, -- in paise description TEXT, is_active BOOLEAN NOT NULL DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Payments (Razorpay transactions) CREATE TABLE IF NOT EXISTS payments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id), package_id UUID NOT NULL REFERENCES pricing_packages(id), razorpay_order_id VARCHAR(100), razorpay_payment_id VARCHAR(100), amount_inr INTEGER NOT NULL, tracecoins_credited INTEGER NOT NULL DEFAULT 0, status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING, SUCCESS, FAILED verified_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Invoices (generated for every successful payment) CREATE TABLE IF NOT EXISTS invoices ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), payment_id UUID NOT NULL REFERENCES payments(id), user_id UUID NOT NULL REFERENCES users(id), invoice_number VARCHAR(50) NOT NULL UNIQUE, subtotal INTEGER NOT NULL, -- in paise gst_amount INTEGER NOT NULL, -- in paise total INTEGER NOT NULL, -- in paise status VARCHAR(20) NOT NULL DEFAULT 'ISSUED', -- ISSUED, PAID issued_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), file_url VARCHAR(500) ); CREATE INDEX IF NOT EXISTS idx_portfolio_items_professional_id ON portfolio_items(professional_id); CREATE INDEX IF NOT EXISTS idx_services_professional_id ON services(professional_id); CREATE INDEX IF NOT EXISTS idx_tracecoin_ledger_wallet_id ON tracecoin_ledger(wallet_id); CREATE INDEX IF NOT EXISTS idx_payments_user_id ON payments(user_id); CREATE INDEX IF NOT EXISTS idx_invoices_user_id ON invoices(user_id);