Spaces:
Running
Running
File size: 8,466 Bytes
127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 564fcbc 40be868 564fcbc 40be868 564fcbc 40be868 564fcbc 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 127838b 40be868 564fcbc 127838b 40be868 127838b 40be868 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | -- Medical AI Platform Database Schema
-- This is the ONLY schema file you need to run
-- Run this in Supabase SQL Editor
-- ============================================================================
-- STEP 1: Enable required extensions
-- ============================================================================
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "vector";
-- ============================================================================
-- STEP 2: Create all tables
-- ============================================================================
-- Users table
CREATE TABLE IF NOT EXISTS public.users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
email TEXT UNIQUE NOT NULL,
name TEXT,
plan TEXT NOT NULL DEFAULT 'free' CHECK (plan IN ('free', 'student', 'pro', 'admin')),
role TEXT CHECK (role IN ('super_admin', 'admin', 'ops', 'support', 'viewer')),
personal_api_key TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
disabled BOOLEAN NOT NULL DEFAULT FALSE
);
-- Admin allowlist table
CREATE TABLE IF NOT EXISTS public.admin_allowlist (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
email TEXT UNIQUE NOT NULL,
role TEXT NOT NULL CHECK (role IN ('super_admin', 'admin', 'ops', 'support', 'viewer')),
added_by UUID REFERENCES public.users(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Usage counters table
CREATE TABLE IF NOT EXISTS public.usage_counters (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
date DATE NOT NULL DEFAULT CURRENT_DATE,
tokens_used INTEGER NOT NULL DEFAULT 0,
requests_count INTEGER NOT NULL DEFAULT 0,
pdf_uploads INTEGER NOT NULL DEFAULT 0,
mcqs_generated INTEGER NOT NULL DEFAULT 0,
images_used INTEGER NOT NULL DEFAULT 0,
flashcards_generated INTEGER NOT NULL DEFAULT 0,
UNIQUE(user_id, date)
);
-- API keys table
CREATE TABLE IF NOT EXISTS public.api_keys (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
provider TEXT NOT NULL,
feature TEXT NOT NULL,
key_value TEXT NOT NULL,
priority INTEGER NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'degraded', 'disabled')),
failure_count INTEGER NOT NULL DEFAULT 0,
last_used_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Provider health table
CREATE TABLE IF NOT EXISTS public.provider_health (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
api_key_id UUID NOT NULL REFERENCES public.api_keys(id) ON DELETE CASCADE,
checked_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
status TEXT NOT NULL CHECK (status IN ('healthy', 'degraded', 'failed')),
response_time_ms INTEGER,
error_message TEXT,
quota_remaining INTEGER
);
-- System flags table
CREATE TABLE IF NOT EXISTS public.system_flags (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
flag_name TEXT UNIQUE NOT NULL,
flag_value TEXT NOT NULL,
updated_by UUID REFERENCES public.users(id),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Documents table
CREATE TABLE IF NOT EXISTS public.documents (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
filename TEXT NOT NULL,
file_type TEXT NOT NULL CHECK (file_type IN ('pdf', 'image')),
file_size INTEGER NOT NULL,
storage_path TEXT NOT NULL,
processing_status TEXT NOT NULL DEFAULT 'pending' CHECK (processing_status IN ('pending', 'processing', 'completed', 'failed')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Embeddings table
CREATE TABLE IF NOT EXISTS public.embeddings (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
document_id UUID NOT NULL REFERENCES public.documents(id) ON DELETE CASCADE,
chunk_text TEXT NOT NULL,
chunk_index INTEGER NOT NULL,
embedding VECTOR(768),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Chat sessions table
CREATE TABLE IF NOT EXISTS public.chat_sessions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
title TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Messages table
CREATE TABLE IF NOT EXISTS public.messages (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
session_id UUID NOT NULL REFERENCES public.chat_sessions(id) ON DELETE CASCADE,
role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system')),
content TEXT NOT NULL,
tokens_used INTEGER,
citations JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Study sessions table
CREATE TABLE IF NOT EXISTS public.study_sessions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
topic TEXT NOT NULL,
duration INTEGER NOT NULL,
scheduled_date TIMESTAMPTZ,
notes TEXT,
status TEXT NOT NULL DEFAULT 'planned' CHECK (status IN ('planned', 'in_progress', 'completed', 'cancelled')),
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Subscriptions table
CREATE TABLE IF NOT EXISTS public.subscriptions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
plan TEXT NOT NULL CHECK (plan IN ('free', 'student', 'pro', 'admin')),
razorpay_subscription_id TEXT UNIQUE,
status TEXT NOT NULL CHECK (status IN ('active', 'cancelled', 'expired')),
current_period_start TIMESTAMPTZ,
current_period_end TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Payments table
CREATE TABLE IF NOT EXISTS public.payments (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
subscription_id UUID REFERENCES public.subscriptions(id),
razorpay_payment_id TEXT UNIQUE,
amount INTEGER NOT NULL,
currency TEXT NOT NULL DEFAULT 'INR',
status TEXT NOT NULL CHECK (status IN ('success', 'failed', 'pending')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Audit logs table
CREATE TABLE IF NOT EXISTS public.audit_logs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
admin_id UUID REFERENCES public.users(id),
action_type TEXT NOT NULL,
target_type TEXT,
target_id TEXT,
details JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- ============================================================================
-- STEP 3: Create indexes
-- ============================================================================
CREATE INDEX IF NOT EXISTS idx_users_email ON public.users(email);
CREATE INDEX IF NOT EXISTS idx_admin_allowlist_email ON public.admin_allowlist(email);
CREATE INDEX IF NOT EXISTS idx_usage_counters_user_date ON public.usage_counters(user_id, date);
CREATE INDEX IF NOT EXISTS idx_api_keys_provider_feature ON public.api_keys(provider, feature);
CREATE INDEX IF NOT EXISTS idx_chat_sessions_user_id ON public.chat_sessions(user_id);
CREATE INDEX IF NOT EXISTS idx_messages_session_created ON public.messages(session_id, created_at);
CREATE INDEX IF NOT EXISTS idx_documents_user_id ON public.documents(user_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_admin_created ON public.audit_logs(admin_id, created_at DESC);
-- ============================================================================
-- STEP 4: Create trigger for updated_at
-- ============================================================================
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS update_users_updated_at ON public.users;
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON public.users
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
DROP TRIGGER IF EXISTS update_chat_sessions_updated_at ON public.chat_sessions;
CREATE TRIGGER update_chat_sessions_updated_at BEFORE UPDATE ON public.chat_sessions
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================================
-- DONE!
-- ============================================================================
SELECT 'Schema created successfully!' as status;
|