Aarogyan_Project / supabase_schema.sql
Sahil
First Commit
9bd4388
-- ============================================================
-- Aarogyan β€” Supabase Database Schema
-- Run this in your Supabase SQL Editor (in order)
-- ============================================================
-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- ────────────────────────────────────────────────────────────
-- 1. USERS
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
full_name TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users (email);
-- ────────────────────────────────────────────────────────────
-- 2. PROFILES
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID UNIQUE NOT NULL REFERENCES users(id) ON DELETE CASCADE,
-- Section 1: Personal
full_name TEXT,
date_of_birth DATE,
biological_sex TEXT CHECK (biological_sex IN ('Male', 'Female', 'Intersex')),
height_cm NUMERIC(5,1),
weight_kg NUMERIC(5,1),
blood_group TEXT,
city TEXT,
region_state TEXT,
preferred_language TEXT DEFAULT 'English',
emergency_contact_name TEXT,
emergency_contact_phone TEXT,
-- Sections 2–9: stored as JSONB arrays/objects
existing_conditions JSONB DEFAULT '[]'::JSONB,
allergies JSONB DEFAULT '[]'::JSONB,
current_medications JSONB DEFAULT '[]'::JSONB,
supplements JSONB DEFAULT '[]'::JSONB,
past_medical_history JSONB DEFAULT '[]'::JSONB,
family_medical_history JSONB DEFAULT '[]'::JSONB,
lifestyle JSONB DEFAULT '{}'::JSONB,
mental_health JSONB DEFAULT '{}'::JSONB,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_profiles_user_id ON profiles (user_id);
-- ────────────────────────────────────────────────────────────
-- 3. CONSULTATIONS
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS consultations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
start_date DATE,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_consultations_user_id ON consultations (user_id);
-- ────────────────────────────────────────────────────────────
-- 4. SESSIONS
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
consultation_id UUID NOT NULL REFERENCES consultations(id) ON DELETE CASCADE,
visit_date DATE NOT NULL,
symptoms TEXT,
diagnosis TEXT,
medications TEXT,
doctor_notes TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_sessions_consultation_id ON sessions (consultation_id);
-- ────────────────────────────────────────────────────────────
-- 5. SESSION DOCUMENTS
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS session_documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
file_name TEXT NOT NULL,
storage_path TEXT NOT NULL,
public_url TEXT,
content_type TEXT,
ocr_text TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_session_documents_session_id ON session_documents (session_id);
-- ────────────────────────────────────────────────────────────
-- 6. CONVERSATIONS (Medical Assistant)
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS conversations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
title TEXT DEFAULT 'New Conversation',
preview TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_conversations_user_id ON conversations (user_id);
-- ────────────────────────────────────────────────────────────
-- 7. MESSAGES
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
role TEXT NOT NULL CHECK (role IN ('user', 'assistant')),
content TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_messages_conversation_id ON messages (conversation_id);
-- ────────────────────────────────────────────────────────────
-- 8. EMOTIONAL SESSIONS (Orbz / Buddy)
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS emotional_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
user_text TEXT,
buddy_text TEXT,
mood_score SMALLINT CHECK (mood_score BETWEEN 1 AND 10),
emotion TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_emotional_sessions_user_id ON emotional_sessions (user_id);
CREATE INDEX idx_emotional_sessions_created_at ON emotional_sessions (created_at);
-- ────────────────────────────────────────────────────────────
-- 9. STORAGE BUCKETS (run separately or via Supabase dashboard)
-- ────────────────────────────────────────────────────────────
-- Create a storage bucket called "documents" with:
-- Public: false (files accessed via signed URLs or backend proxy)
-- Max file size: 2097152 (2 MB)
-- Allowed MIME types: image/jpeg, image/png, application/pdf
--
-- Run this if the Supabase storage API supports SQL:
-- INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
-- VALUES (
-- 'documents',
-- 'documents',
-- true,
-- 2097152,
-- ARRAY['image/jpeg', 'image/png', 'application/pdf']
-- )
-- ON CONFLICT (id) DO NOTHING;
-- ────────────────────────────────────────────────────────────
-- 10. UPDATED_AT TRIGGERS
-- ────────────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_users_updated_at
BEFORE UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER trg_profiles_updated_at
BEFORE UPDATE ON profiles
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER trg_consultations_updated_at
BEFORE UPDATE ON consultations
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER trg_sessions_updated_at
BEFORE UPDATE ON sessions
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER trg_conversations_updated_at
BEFORE UPDATE ON conversations
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ────────────────────────────────────────────────────────────
-- 11. ROW LEVEL SECURITY (RLS) β€” Disable for service role key
-- ────────────────────────────────────────────────────────────
-- Since the backend uses the SERVICE ROLE key (bypasses RLS),
-- RLS is disabled. Enable RLS policies only if you switch to
-- the ANON key on the backend.
ALTER TABLE users DISABLE ROW LEVEL SECURITY;
ALTER TABLE profiles DISABLE ROW LEVEL SECURITY;
ALTER TABLE consultations DISABLE ROW LEVEL SECURITY;
ALTER TABLE sessions DISABLE ROW LEVEL SECURITY;
ALTER TABLE session_documents DISABLE ROW LEVEL SECURITY;
ALTER TABLE conversations DISABLE ROW LEVEL SECURITY;
ALTER TABLE messages DISABLE ROW LEVEL SECURITY;
ALTER TABLE emotional_sessions DISABLE ROW LEVEL SECURITY;