-- Contexta — Features Migration (Phase 1, 2, 3) -- Run this in your Supabase SQL Editor -- ══════════════════════════════════════════════════════════════ -- PHASE 1 — Live Chat Inbox + Lead CRM -- ══════════════════════════════════════════════════════════════ -- Add status to conversations (open → agent_handling → resolved) ALTER TABLE conversations ADD COLUMN IF NOT EXISTS status VARCHAR(20) DEFAULT 'open', ADD COLUMN IF NOT EXISTS last_agent_reply_at TIMESTAMPTZ; -- Add CRM fields to leads ALTER TABLE leads ADD COLUMN IF NOT EXISTS status VARCHAR(20) DEFAULT 'new', ADD COLUMN IF NOT EXISTS notes TEXT; -- ══════════════════════════════════════════════════════════════ -- PHASE 2a — Appointment Booking -- ══════════════════════════════════════════════════════════════ -- Add booking toggle to chatbots ALTER TABLE chatbots ADD COLUMN IF NOT EXISTS booking_enabled BOOLEAN DEFAULT FALSE; -- Business hours per chatbot (one row per weekday) CREATE TABLE IF NOT EXISTS business_hours ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), chatbot_id UUID NOT NULL REFERENCES chatbots(id) ON DELETE CASCADE, day_of_week INTEGER NOT NULL CHECK (day_of_week BETWEEN 0 AND 6), -- 0=Mon, 6=Sun is_open BOOLEAN DEFAULT TRUE, open_time TIME NOT NULL DEFAULT '09:00', close_time TIME NOT NULL DEFAULT '17:00', slot_duration_minutes INTEGER NOT NULL DEFAULT 60, UNIQUE(chatbot_id, day_of_week) ); CREATE INDEX IF NOT EXISTS idx_business_hours_chatbot ON business_hours(chatbot_id); ALTER TABLE business_hours ENABLE ROW LEVEL SECURITY; CREATE POLICY "business_hours_owner" ON business_hours FOR ALL USING ( chatbot_id IN ( SELECT c.id FROM chatbots c JOIN companies co ON c.company_id = co.id WHERE co.owner_id = auth.uid() ) ); -- Appointments table CREATE TABLE IF NOT EXISTS appointments ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), chatbot_id UUID NOT NULL REFERENCES chatbots(id) ON DELETE CASCADE, conversation_id UUID REFERENCES conversations(id) ON DELETE SET NULL, customer_name TEXT NOT NULL, customer_contact TEXT NOT NULL, -- email or phone service TEXT, slot_start TIMESTAMPTZ NOT NULL, slot_end TIMESTAMPTZ NOT NULL, status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending','confirmed','cancelled','completed')), notes TEXT, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_appointments_chatbot ON appointments(chatbot_id); CREATE INDEX IF NOT EXISTS idx_appointments_slot ON appointments(chatbot_id, slot_start); ALTER TABLE appointments ENABLE ROW LEVEL SECURITY; CREATE POLICY "appointments_owner" ON appointments FOR ALL USING ( chatbot_id IN ( SELECT c.id FROM chatbots c JOIN companies co ON c.company_id = co.id WHERE co.owner_id = auth.uid() ) ); -- Allow anonymous inserts (customers booking without auth) CREATE POLICY "appointments_insert_public" ON appointments FOR INSERT WITH CHECK (true); -- ══════════════════════════════════════════════════════════════ -- PHASE 2b — Telegram Campaigns -- ══════════════════════════════════════════════════════════════ CREATE TABLE IF NOT EXISTS campaigns ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), chatbot_id UUID NOT NULL REFERENCES chatbots(id) ON DELETE CASCADE, title TEXT NOT NULL, message TEXT NOT NULL, status VARCHAR(20) DEFAULT 'draft' CHECK (status IN ('draft','sending','sent','failed')), recipients_count INTEGER DEFAULT 0, sent_count INTEGER DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW(), sent_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS idx_campaigns_chatbot ON campaigns(chatbot_id); ALTER TABLE campaigns ENABLE ROW LEVEL SECURITY; CREATE POLICY "campaigns_owner" ON campaigns FOR ALL USING ( chatbot_id IN ( SELECT c.id FROM chatbots c JOIN companies co ON c.company_id = co.id WHERE co.owner_id = auth.uid() ) );