CREATE TABLE IF NOT EXISTS referral_codes ( id BIGSERIAL PRIMARY KEY, code VARCHAR(12) NOT NULL UNIQUE, referrer_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, is_active BOOLEAN NOT NULL DEFAULT TRUE, max_uses INT, current_uses INT NOT NULL DEFAULT 0, incentive_type TEXT NOT NULL CHECK ( incentive_type IN ( 'course_access', 'discount', 'certificate_unlock', 'feature_unlock' ) ), incentive_value TEXT, -- e.g. course_id, percentage, feature_key created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_referral_codes_referrer_id ON referral_codes (referrer_id); CREATE INDEX idx_referral_codes_code ON referral_codes (code); CREATE TABLE IF NOT EXISTS user_referrals ( id BIGSERIAL PRIMARY KEY, referrer_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, referred_user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, referral_code_id BIGINT NOT NULL REFERENCES referral_codes(id) ON DELETE CASCADE, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE (referred_user_id), UNIQUE (referrer_id, referred_user_id) );