Includes: API (Express/TypeScript), Astro site, Python workers, document generators, FCC compliance tools, Canada CRTC formation, Ansible infrastructure, and deployment scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
105 lines
4.4 KiB
PL/PgSQL
105 lines
4.4 KiB
PL/PgSQL
-- 011_sales_agents.sql
|
|
-- Sales agent referral system with commission tracking.
|
|
-- Agents get auto-generated REF-XXXXX codes. Clients get 5% off service fee.
|
|
-- Commissions paid 14 days after order delivery.
|
|
|
|
BEGIN;
|
|
|
|
CREATE TABLE IF NOT EXISTS sales_agents (
|
|
id SERIAL PRIMARY KEY,
|
|
agent_code TEXT UNIQUE NOT NULL, -- REF-XXXXX (auto-generated)
|
|
discount_code_id INTEGER REFERENCES discount_codes(id),
|
|
|
|
-- Agent info
|
|
name TEXT NOT NULL,
|
|
email TEXT NOT NULL UNIQUE,
|
|
phone TEXT,
|
|
company TEXT,
|
|
|
|
-- ERPNext user link
|
|
erpnext_user TEXT, -- ERPNext username for portal login
|
|
|
|
-- Payout info (for Relay ACH)
|
|
bank_name TEXT,
|
|
bank_routing TEXT,
|
|
bank_account_last4 TEXT, -- last 4 only in plain text
|
|
bank_account_encrypted TEXT, -- full account in ERPNext Sensitive ID
|
|
payout_email TEXT, -- PayPal/e-transfer email alternative
|
|
|
|
-- Commission config (defaults, overridable per agent)
|
|
commission_type TEXT DEFAULT 'flat', -- 'flat' or 'percent'
|
|
commission_default_cents INTEGER DEFAULT 30000, -- $300 default for Canada CRTC
|
|
commission_pct INTEGER DEFAULT 10, -- 10% for compliance services
|
|
|
|
-- Per-service commission overrides (JSON)
|
|
-- e.g., {"canada-crtc": 30000, "formation-basic": 5000, "formation-complete": 5000, "bundle": 10000}
|
|
commission_overrides JSONB DEFAULT '{}',
|
|
|
|
-- Stats (denormalized for fast queries)
|
|
total_referrals INTEGER DEFAULT 0,
|
|
total_earned_cents INTEGER DEFAULT 0,
|
|
total_paid_cents INTEGER DEFAULT 0,
|
|
total_pending_cents INTEGER DEFAULT 0,
|
|
|
|
-- Status
|
|
active BOOLEAN DEFAULT TRUE,
|
|
onboarded_at TIMESTAMPTZ,
|
|
notes TEXT,
|
|
created_at TIMESTAMPTZ DEFAULT now(),
|
|
updated_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_agents_code ON sales_agents(agent_code);
|
|
CREATE INDEX IF NOT EXISTS idx_agents_email ON sales_agents(email);
|
|
CREATE INDEX IF NOT EXISTS idx_agents_active ON sales_agents(active);
|
|
|
|
-- Commission ledger — one row per earned commission
|
|
CREATE TABLE IF NOT EXISTS commission_ledger (
|
|
id SERIAL PRIMARY KEY,
|
|
agent_id INTEGER NOT NULL REFERENCES sales_agents(id),
|
|
agent_code TEXT NOT NULL,
|
|
|
|
-- What was sold
|
|
order_type TEXT NOT NULL, -- 'canada_crtc', 'formation', 'service', 'bundle'
|
|
order_id INTEGER,
|
|
order_number TEXT NOT NULL,
|
|
service_slug TEXT,
|
|
customer_name TEXT NOT NULL,
|
|
customer_email TEXT NOT NULL,
|
|
|
|
-- Money
|
|
order_amount_cents INTEGER NOT NULL, -- what the client paid (total)
|
|
discount_cents INTEGER DEFAULT 0, -- 5% discount given to client
|
|
commission_cents INTEGER NOT NULL, -- what the agent earns
|
|
|
|
-- Lifecycle
|
|
-- pending: order placed, not yet delivered
|
|
-- eligible: order delivered + 14 day holdback passed
|
|
-- approved: admin reviewed and approved for payout
|
|
-- processing: payout being sent via Relay
|
|
-- paid: money sent to agent
|
|
-- cancelled: order was cancelled/refunded, commission voided
|
|
status TEXT DEFAULT 'pending' CHECK (status IN (
|
|
'pending', 'eligible', 'approved', 'processing', 'paid', 'cancelled'
|
|
)),
|
|
|
|
-- Dates
|
|
order_delivered_at TIMESTAMPTZ,
|
|
eligible_at TIMESTAMPTZ, -- delivered_at + 14 days
|
|
approved_by INTEGER, -- admin_users.id
|
|
approved_at TIMESTAMPTZ,
|
|
paid_at TIMESTAMPTZ,
|
|
payment_method TEXT, -- 'relay_ach', 'paypal', 'check'
|
|
payment_reference TEXT, -- transaction ID or check number
|
|
|
|
notes TEXT,
|
|
created_at TIMESTAMPTZ DEFAULT now(),
|
|
updated_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_commission_agent ON commission_ledger(agent_id);
|
|
CREATE INDEX IF NOT EXISTS idx_commission_status ON commission_ledger(status);
|
|
CREATE INDEX IF NOT EXISTS idx_commission_eligible ON commission_ledger(eligible_at);
|
|
CREATE INDEX IF NOT EXISTS idx_commission_order ON commission_ledger(order_type, order_id);
|
|
|
|
COMMIT;
|