medical-platform / database /Old /schema.sql
Dhiman-07-cyber's picture
Complete database schema consolidation + UI enhancements
caf6eb8
-- 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;