286 lines
11 KiB
MySQL
286 lines
11 KiB
MySQL
|
|
-- ============================================================================
|
||
|
|
-- MIGRATION: Complete Schema Updates for Pricing & Lead Requests
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
BEGIN;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 1. Update pricing_packages table with new columns
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
ALTER TABLE pricing_packages
|
||
|
|
DROP COLUMN IF EXISTS user_role_profile_id,
|
||
|
|
ADD COLUMN IF NOT EXISTS package_type VARCHAR(50) NOT NULL DEFAULT 'TRACECOIN_BUNDLE',
|
||
|
|
ADD COLUMN IF NOT EXISTS applicable_roles TEXT[] DEFAULT '{}',
|
||
|
|
ADD COLUMN IF NOT EXISTS tracecoins_amount INTEGER DEFAULT 0,
|
||
|
|
ADD COLUMN IF NOT EXISTS valid_from TIMESTAMPTZ,
|
||
|
|
ADD COLUMN IF NOT EXISTS valid_until TIMESTAMPTZ,
|
||
|
|
ADD COLUMN IF NOT EXISTS is_promotional BOOLEAN DEFAULT false;
|
||
|
|
|
||
|
|
-- Add index for package lookup
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_pricing_packages_type ON pricing_packages(package_type);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 2. Update payments table with new columns
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
ALTER TABLE payments
|
||
|
|
ADD COLUMN IF NOT EXISTS package_id UUID,
|
||
|
|
ADD COLUMN IF NOT EXISTS razorpay_order_id VARCHAR(255),
|
||
|
|
ADD COLUMN IF NOT EXISTS razorpay_payment_id VARCHAR(255),
|
||
|
|
ADD COLUMN IF NOT EXISTS tracecoins_credited INTEGER DEFAULT 0,
|
||
|
|
ADD COLUMN IF NOT EXISTS verified_at TIMESTAMPTZ;
|
||
|
|
|
||
|
|
-- Add foreign key if not exists
|
||
|
|
ALTER TABLE payments
|
||
|
|
ADD CONSTRAINT payments_package_id_fkey
|
||
|
|
FOREIGN KEY (package_id) REFERENCES pricing_packages(id) ON DELETE SET NULL;
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_payments_package_id ON payments(package_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_payments_razorpay_order_id ON payments(razorpay_order_id);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 3. Create lead_requests table
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS lead_requests (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
lead_id UUID NOT NULL REFERENCES leads(id) ON DELETE CASCADE,
|
||
|
|
user_role_profile_id UUID NOT NULL REFERENCES user_role_profiles(id) ON DELETE CASCADE,
|
||
|
|
customer_user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||
|
|
status VARCHAR(50) NOT NULL DEFAULT 'PENDING',
|
||
|
|
tracecoins_reserved INTEGER NOT NULL DEFAULT 25,
|
||
|
|
message TEXT,
|
||
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
||
|
|
accepted_at TIMESTAMPTZ,
|
||
|
|
rejected_at TIMESTAMPTZ,
|
||
|
|
rejected_reason TEXT,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_lead_requests_lead_id ON lead_requests(lead_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_lead_requests_user_role_profile_id ON lead_requests(user_role_profile_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_lead_requests_customer_user_id ON lead_requests(customer_user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_lead_requests_status ON lead_requests(status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_lead_requests_expires_at ON lead_requests(expires_at);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 4. Add display_code to company_profiles
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
ALTER TABLE company_profiles
|
||
|
|
ADD COLUMN IF NOT EXISTS display_code VARCHAR(20) UNIQUE;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 5. Add display_code to customer_profiles
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
ALTER TABLE customer_profiles
|
||
|
|
ADD COLUMN IF NOT EXISTS display_code VARCHAR(20) UNIQUE;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 6. Add display_code to job_seeker_profiles
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
ALTER TABLE job_seeker_profiles
|
||
|
|
ADD COLUMN IF NOT EXISTS display_code VARCHAR(20) UNIQUE;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 7. Add free_requirement_slots and purchased_requirement_slots to customer_profiles
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
ALTER TABLE customer_profiles
|
||
|
|
ADD COLUMN IF NOT EXISTS free_requirement_slots INTEGER DEFAULT 2,
|
||
|
|
ADD COLUMN IF NOT EXISTS purchased_requirement_slots INTEGER DEFAULT 0;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 8. Update leads table with new columns
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
ALTER TABLE leads
|
||
|
|
ADD COLUMN IF NOT EXISTS customer_user_id UUID REFERENCES users(id),
|
||
|
|
ADD COLUMN IF NOT EXISTS max_acceptances INTEGER DEFAULT 10,
|
||
|
|
ADD COLUMN IF NOT EXISTS current_acceptances INTEGER DEFAULT 0,
|
||
|
|
ADD COLUMN IF NOT EXISTS expires_at TIMESTAMPTZ,
|
||
|
|
ADD COLUMN IF NOT EXISTS cover_image_url TEXT;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 9. Add tracecoins_reserved column to lead_requests for proper tracking
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
-- Already added in step 3
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 10. Create function to auto-generate display codes
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE OR REPLACE FUNCTION generate_display_code(prefix VARCHAR(10))
|
||
|
|
RETURNS VARCHAR(20) AS $$
|
||
|
|
DECLARE
|
||
|
|
new_code VARCHAR(20);
|
||
|
|
seq_num INTEGER;
|
||
|
|
BEGIN
|
||
|
|
-- Get the next sequence number for this prefix
|
||
|
|
SELECT COALESCE(
|
||
|
|
(SELECT MAX(CAST(SUBSTRING(code FROM 4) AS INTEGER)) + 1
|
||
|
|
FROM (
|
||
|
|
SELECT display_code as code FROM company_profiles WHERE display_code LIKE prefix || '%'
|
||
|
|
UNION ALL
|
||
|
|
SELECT display_code as code FROM customer_profiles WHERE display_code LIKE prefix || '%'
|
||
|
|
UNION ALL
|
||
|
|
SELECT display_code as code FROM job_seeker_profiles WHERE display_code LIKE prefix || '%'
|
||
|
|
) all_codes
|
||
|
|
),
|
||
|
|
1
|
||
|
|
) INTO seq_num;
|
||
|
|
|
||
|
|
new_code := prefix || LPAD(seq_num::TEXT, 4, '0');
|
||
|
|
RETURN new_code;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 11. Create indexes for performance
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_leads_customer_user_id ON leads(customer_user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_leads_status_expires ON leads(status, expires_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_user_role_profiles_role_key ON user_role_profiles(role_key);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 12. Create tracecoin ledger entry types enum support
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
-- Add transaction_type values for ledger tracking
|
||
|
|
-- The ledger already has 'type' column, ensure we have proper entries
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 13. Add indexes for verification queries
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_verifications_user_role_profile_id ON verifications(user_role_profile_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_verifications_status ON verifications(status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_verification_requests_user_role_profile_id ON verification_requests(user_role_profile_id);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 14. Add tracecoin refund support to ledger
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
-- Reserve tracecoins for lead request
|
||
|
|
CREATE OR REPLACE FUNCTION reserve_tracecoins_for_lead_request(
|
||
|
|
p_user_id UUID,
|
||
|
|
p_amount INTEGER,
|
||
|
|
p_lead_request_id UUID
|
||
|
|
) RETURNS BOOLEAN AS $$
|
||
|
|
DECLARE
|
||
|
|
v_wallet_id UUID;
|
||
|
|
v_balance BIGINT;
|
||
|
|
BEGIN
|
||
|
|
-- Get wallet
|
||
|
|
SELECT id, balance INTO v_wallet_id, v_balance
|
||
|
|
FROM tracecoin_wallets
|
||
|
|
WHERE user_id = p_user_id
|
||
|
|
FOR UPDATE;
|
||
|
|
|
||
|
|
IF v_wallet_id IS NULL THEN
|
||
|
|
RETURN FALSE;
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
IF v_balance < p_amount THEN
|
||
|
|
RETURN FALSE;
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
-- Deduct from balance (reserved, not yet spent)
|
||
|
|
UPDATE tracecoin_wallets
|
||
|
|
SET balance = balance - p_amount,
|
||
|
|
reserved = COALESCE(reserved, 0) + p_amount,
|
||
|
|
updated_at = NOW()
|
||
|
|
WHERE id = v_wallet_id;
|
||
|
|
|
||
|
|
-- Add ledger entry
|
||
|
|
INSERT INTO tracecoin_ledger (wallet_id, type, amount, balance_after, reference_type, reference_id, reason)
|
||
|
|
VALUES (v_wallet_id, 'RESERVE', -p_amount, v_balance - p_amount, 'LEAD_REQUEST', p_lead_request_id, 'Lead request reservation');
|
||
|
|
|
||
|
|
RETURN TRUE;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
-- Confirm tracecoins (when customer accepts)
|
||
|
|
CREATE OR REPLACE FUNCTION confirm_tracecoins_for_lead(
|
||
|
|
p_user_id UUID,
|
||
|
|
p_amount INTEGER,
|
||
|
|
p_lead_request_id UUID
|
||
|
|
) RETURNS BOOLEAN AS $$
|
||
|
|
DECLARE
|
||
|
|
v_wallet_id UUID;
|
||
|
|
v_balance BIGINT;
|
||
|
|
BEGIN
|
||
|
|
-- Get wallet
|
||
|
|
SELECT id, balance, COALESCE(reserved, 0) INTO v_wallet_id, v_balance, v_balance
|
||
|
|
FROM tracecoin_wallets
|
||
|
|
WHERE user_id = p_user_id
|
||
|
|
FOR UPDATE;
|
||
|
|
|
||
|
|
IF v_wallet_id IS NULL THEN
|
||
|
|
RETURN FALSE;
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
-- Move from reserved to spent
|
||
|
|
UPDATE tracecoin_wallets
|
||
|
|
SET reserved = reserved - p_amount,
|
||
|
|
updated_at = NOW()
|
||
|
|
WHERE id = v_wallet_id;
|
||
|
|
|
||
|
|
-- Add ledger entry for confirmation
|
||
|
|
INSERT INTO tracecoin_ledger (wallet_id, type, amount, balance_after, reference_type, reference_id, reason)
|
||
|
|
VALUES (v_wallet_id, 'SPEND', -p_amount, v_balance, 'LEAD_REQUEST', p_lead_request_id, 'Lead request accepted');
|
||
|
|
|
||
|
|
RETURN TRUE;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
-- Release tracecoins (when customer rejects or request expires)
|
||
|
|
CREATE OR REPLACE FUNCTION release_tracecoins_for_lead(
|
||
|
|
p_user_id UUID,
|
||
|
|
p_amount INTEGER,
|
||
|
|
p_lead_request_id UUID
|
||
|
|
) RETURNS BOOLEAN AS $$
|
||
|
|
DECLARE
|
||
|
|
v_wallet_id UUID;
|
||
|
|
v_balance BIGINT;
|
||
|
|
BEGIN
|
||
|
|
-- Get wallet
|
||
|
|
SELECT id, balance INTO v_wallet_id, v_balance
|
||
|
|
FROM tracecoin_wallets
|
||
|
|
WHERE user_id = p_user_id
|
||
|
|
FOR UPDATE;
|
||
|
|
|
||
|
|
IF v_wallet_id IS NULL THEN
|
||
|
|
RETURN FALSE;
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
-- Return to available balance from reserved
|
||
|
|
UPDATE tracecoin_wallets
|
||
|
|
SET balance = balance + p_amount,
|
||
|
|
reserved = reserved - p_amount,
|
||
|
|
updated_at = NOW()
|
||
|
|
WHERE id = v_wallet_id;
|
||
|
|
|
||
|
|
-- Add ledger entry for release
|
||
|
|
INSERT INTO tracecoin_ledger (wallet_id, type, amount, balance_after, reference_type, reference_id, reason)
|
||
|
|
VALUES (v_wallet_id, 'RELEASE', p_amount, v_balance + p_amount, 'LEAD_REQUEST', p_lead_request_id, 'Lead request rejected/expired');
|
||
|
|
|
||
|
|
RETURN TRUE;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- 15. Update tracecoin_wallets to have reserved column
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
ALTER TABLE tracecoin_wallets
|
||
|
|
ADD COLUMN IF NOT EXISTS reserved BIGINT DEFAULT 0;
|
||
|
|
|
||
|
|
COMMIT;
|