it0/packages/shared/database/migrations/006-create-referral-tables.sql

77 lines
3.7 KiB
SQL

-- ============================================================
-- Migration 006: Referral System Tables
-- All tables in public schema (cross-tenant, like billing)
-- ============================================================
-- 1. Referral codes — one per tenant, auto-generated on registration
CREATE TABLE IF NOT EXISTS public.referral_codes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id VARCHAR(100) NOT NULL UNIQUE,
user_id VARCHAR(100) NOT NULL,
code VARCHAR(20) NOT NULL UNIQUE,
click_count INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_referral_codes_code ON public.referral_codes (code);
CREATE INDEX IF NOT EXISTS idx_referral_codes_tenant ON public.referral_codes (tenant_id);
-- 2. Referral relationships — tracks who referred whom (tenant level)
CREATE TABLE IF NOT EXISTS public.referral_relationships (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
referrer_tenant_id VARCHAR(100) NOT NULL,
referred_tenant_id VARCHAR(100) NOT NULL UNIQUE, -- one referrer per tenant
referral_code VARCHAR(20) NOT NULL,
level INT NOT NULL DEFAULT 1, -- 1=direct, 2=indirect
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
registered_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
activated_at TIMESTAMPTZ,
rewarded_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_referral_rel_referrer ON public.referral_relationships (referrer_tenant_id);
CREATE INDEX IF NOT EXISTS idx_referral_rel_status ON public.referral_relationships (status);
CREATE INDEX IF NOT EXISTS idx_referral_rel_referred ON public.referral_relationships (referred_tenant_id);
-- 3. Referral rewards — credit records for each tenant
CREATE TABLE IF NOT EXISTS public.referral_rewards (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
beneficiary_tenant_id VARCHAR(100) NOT NULL,
referral_relationship_id UUID NOT NULL REFERENCES public.referral_relationships(id),
reward_type VARCHAR(20) NOT NULL, -- CREDIT | PERCENTAGE
trigger_type VARCHAR(20) NOT NULL, -- FIRST_PAYMENT | RECURRING
amount_cents INT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
invoice_id VARCHAR(100),
source_invoice_id VARCHAR(100),
recurring_month INT,
expires_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
applied_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_referral_rewards_beneficiary ON public.referral_rewards (beneficiary_tenant_id, status);
CREATE INDEX IF NOT EXISTS idx_referral_rewards_relationship ON public.referral_rewards (referral_relationship_id);
-- 4. Referral stats — denormalized cache per tenant
CREATE TABLE IF NOT EXISTS public.referral_stats (
tenant_id VARCHAR(100) PRIMARY KEY,
direct_count INT NOT NULL DEFAULT 0,
active_count INT NOT NULL DEFAULT 0,
total_credit_earned INT NOT NULL DEFAULT 0,
total_credit_applied INT NOT NULL DEFAULT 0,
pending_credit INT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- 5. Processed events — idempotency for Redis Stream consumers
CREATE TABLE IF NOT EXISTS public.referral_processed_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
event_id VARCHAR(255) NOT NULL UNIQUE,
event_type VARCHAR(100) NOT NULL,
processed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_referral_processed_events_event_id ON public.referral_processed_events (event_id);