-- v2.4 CRM Enhanced: activities, tags, loyalty -- Customer activity timeline (notes, calls, visits, emails, whatsapp) CREATE TABLE IF NOT EXISTS customer_activities ( id SERIAL PRIMARY KEY, customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE CASCADE, activity_type VARCHAR(50) NOT NULL, -- 'note', 'call', 'visit', 'email', 'whatsapp', 'sale', 'payment', 'claim' title VARCHAR(200), description TEXT, metadata JSONB, -- e.g. {"call_duration": 120, "email_subject": "..."} employee_id INTEGER REFERENCES employees(id), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_cust_act_customer ON customer_activities(customer_id, created_at DESC); CREATE INDEX IF NOT EXISTS idx_cust_act_type ON customer_activities(activity_type); -- Customer tags for segmentation CREATE TABLE IF NOT EXISTS customer_tags ( id SERIAL PRIMARY KEY, tenant_id INTEGER NOT NULL, name VARCHAR(100) NOT NULL, color VARCHAR(7) DEFAULT '#6B7280', -- hex color description TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(tenant_id, name) ); CREATE INDEX IF NOT EXISTS idx_cust_tags_tenant ON customer_tags(tenant_id); -- Many-to-many: customers <-> tags CREATE TABLE IF NOT EXISTS customer_tag_assignments ( customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE CASCADE, tag_id INTEGER NOT NULL REFERENCES customer_tags(id) ON DELETE CASCADE, assigned_at TIMESTAMPTZ DEFAULT NOW(), assigned_by INTEGER REFERENCES employees(id), PRIMARY KEY (customer_id, tag_id) ); -- Loyalty / rewards program CREATE TABLE IF NOT EXISTS loyalty_points ( id SERIAL PRIMARY KEY, customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE CASCADE, points INTEGER NOT NULL DEFAULT 0, points_type VARCHAR(20) NOT NULL DEFAULT 'earned', -- 'earned', 'redeemed', 'expired', 'bonus' source_type VARCHAR(50), -- 'sale', 'referral', 'promotion', 'manual', 'redemption' source_id INTEGER, -- sale_id or other reference description TEXT, expires_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_loyalty_customer ON loyalty_points(customer_id, created_at DESC); CREATE INDEX IF NOT EXISTS idx_loyalty_expires ON loyalty_points(expires_at) WHERE expires_at IS NOT NULL; -- Loyalty redemptions (rewards catalog) CREATE TABLE IF NOT EXISTS loyalty_rewards ( id SERIAL PRIMARY KEY, tenant_id INTEGER NOT NULL, name VARCHAR(200) NOT NULL, description TEXT, points_cost INTEGER NOT NULL, reward_type VARCHAR(50) DEFAULT 'discount', -- 'discount', 'free_product', 'service' reward_value NUMERIC(12,2), -- discount amount or product ID is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Loyalty redemption history CREATE TABLE IF NOT EXISTS loyalty_redemptions ( id SERIAL PRIMARY KEY, customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE CASCADE, reward_id INTEGER REFERENCES loyalty_rewards(id), points_used INTEGER NOT NULL, reward_value NUMERIC(12,2), description TEXT, employee_id INTEGER REFERENCES employees(id), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_loyalty_redem_customer ON loyalty_redemptions(customer_id); -- Add loyalty balance to customers (denormalized for quick lookup) ALTER TABLE customers ADD COLUMN IF NOT EXISTS loyalty_points_balance INTEGER DEFAULT 0; ALTER TABLE customers ADD COLUMN IF NOT EXISTS loyalty_tier VARCHAR(50) DEFAULT 'bronze';