File size: 11,442 Bytes
3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 09ab9b3 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 09ab9b3 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 2f230ab 3a338e5 |
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 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
-- =====================================================
-- Supabase μ΄κΈ° μ€μ ν΅ν© μ€ν¬λ¦½νΈ (μμ μ΄κΈ°ν λ²μ )
-- κ°νΈ μΈμμΈκ³ κ΅μ‘ νλ«νΌ
-- μ€ν μμ: μ΄ νμΌμ Supabase SQL Editorμμ ν λ²λ§ μ€ννμΈμ
-- =====================================================
-- =====================================================
-- 1. κΈ°λ³Έ ν
μ΄λΈ μμ± (μμ‘΄μ± μμλλ‘)
-- =====================================================
-- 1.1 patients ν
μ΄λΈ (νμ κΈ°λ³Έ μ 보)
CREATE TABLE patients (
id VARCHAR(50) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age INTEGER NOT NULL,
gender VARCHAR(10) NOT NULL,
weight INTEGER,
height INTEGER,
diagnosis VARCHAR(200) NOT NULL,
admission_date DATE NOT NULL,
attending_physician VARCHAR(100),
allergies VARCHAR(200),
comorbidities TEXT,
room_number VARCHAR(20),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE patients IS 'νμ κΈ°λ³Έ μ 보';
-- 1.2 scenarios ν
μ΄λΈ (μΈμμΈκ³ μλ리μ€)
CREATE TABLE scenarios (
id VARCHAR(50) PRIMARY KEY,
patient_id VARCHAR(50) NOT NULL,
title VARCHAR(200) NOT NULL,
day INTEGER NOT NULL,
handoff_situation VARCHAR(200),
vitals JSONB,
labs JSONB,
orders JSONB,
nursing_notes JSONB,
physical_exam JSONB,
imaging JSONB,
surgery_info JSONB,
discharge_education JSONB,
hospital_day INTEGER,
status_badge VARCHAR(20),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CONSTRAINT scenarios_patient_fkey
FOREIGN KEY (patient_id)
REFERENCES patients(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
COMMENT ON TABLE scenarios IS 'μΈμμΈκ³ μλ리μ€';
-- 1.3 sessions ν
μ΄λΈ (μΈμ
κ΄λ¦¬) - session_idλ₯Ό PKλ‘
CREATE TABLE sessions (
session_id VARCHAR(100) PRIMARY KEY,
student_id VARCHAR(100) NOT NULL,
scenario_id VARCHAR(50) NOT NULL,
status VARCHAR(20) DEFAULT 'active',
started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
ended_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CONSTRAINT sessions_scenario_fkey
FOREIGN KEY (scenario_id)
REFERENCES scenarios(id)
ON DELETE RESTRICT
ON UPDATE CASCADE
);
COMMENT ON TABLE sessions IS 'TSID κΈ°λ° μ±ν
μΈμ
κ΄λ¦¬ ν
μ΄λΈ';
COMMENT ON COLUMN sessions.session_id IS 'TSID κΈ°λ° μΈμ
μλ³μ (PRIMARY KEY)';
-- 1.4 chat_history ν
μ΄λΈ (νμκ³Ό AI κ°μ μ±ν
κΈ°λ‘)
CREATE TABLE chat_history (
id SERIAL PRIMARY KEY,
session_id VARCHAR(100) NOT NULL,
student_id VARCHAR(100) NOT NULL,
scenario_id VARCHAR(50) NOT NULL,
role VARCHAR(20) NOT NULL CHECK (role IN ('user', 'assistant')),
message TEXT NOT NULL,
timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CONSTRAINT chat_history_session_fkey
FOREIGN KEY (session_id)
REFERENCES sessions(session_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
COMMENT ON TABLE chat_history IS 'νμκ³Ό AI κ°μ μ±ν
κΈ°λ‘';
-- 1.5 handoff_records ν
μ΄λΈ (μΈμμΈκ³ κΈ°λ‘ λ° νκ°)
CREATE TABLE handoff_records (
id SERIAL PRIMARY KEY,
session_id VARCHAR(100),
student_id VARCHAR(100) NOT NULL,
scenario_id VARCHAR(50) NOT NULL,
submitted_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
situation TEXT,
background TEXT,
assessment TEXT,
recommendation TEXT,
total_score FLOAT,
category_scores JSONB,
strengths JSONB,
improvements JSONB,
detailed_feedback TEXT,
missing_critical_info JSONB,
safety_concerns JSONB,
CONSTRAINT handoff_records_scenario_fkey
FOREIGN KEY (scenario_id)
REFERENCES scenarios(id)
ON DELETE RESTRICT
ON UPDATE CASCADE,
CONSTRAINT handoff_records_session_fkey
FOREIGN KEY (session_id)
REFERENCES sessions(session_id)
ON DELETE SET NULL
ON UPDATE CASCADE
);
COMMENT ON TABLE handoff_records IS 'νμμ μΈμμΈκ³ κΈ°λ‘ λ° AI νκ° κ²°κ³Ό';
COMMENT ON COLUMN handoff_records.session_id IS 'μ±ν
μΈμ
ID (nullable)';
-- 1.6 sbar_drafts ν
μ΄λΈ (μμ± μ€μΈ SBAR μμ μ μ₯)
CREATE TABLE sbar_drafts (
id SERIAL PRIMARY KEY,
session_id VARCHAR(100) NOT NULL UNIQUE,
student_id VARCHAR(100) NOT NULL,
scenario_id VARCHAR(50) NOT NULL,
situation TEXT DEFAULT '',
background TEXT DEFAULT '',
assessment TEXT DEFAULT '',
recommendation TEXT DEFAULT '',
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CONSTRAINT sbar_drafts_session_fkey
FOREIGN KEY (session_id)
REFERENCES sessions(session_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
COMMENT ON TABLE sbar_drafts IS 'μμ± μ€μΈ SBAR μμ μ μ₯';
-- =====================================================
-- 2. μΈλ±μ€ μμ± (μ±λ₯ μ΅μ ν)
-- =====================================================
-- patients
CREATE INDEX idx_patients_name ON patients(name);
-- scenarios
CREATE INDEX idx_scenarios_patient ON scenarios(patient_id);
CREATE INDEX idx_scenarios_day ON scenarios(day);
-- sessions
CREATE INDEX idx_sessions_student ON sessions(student_id);
CREATE INDEX idx_sessions_scenario ON sessions(scenario_id);
CREATE INDEX idx_sessions_status ON sessions(status);
CREATE INDEX idx_sessions_started ON sessions(started_at DESC);
-- chat_history
CREATE INDEX idx_chat_history_session ON chat_history(session_id);
CREATE INDEX idx_chat_history_student ON chat_history(student_id);
CREATE INDEX idx_chat_history_timestamp ON chat_history(timestamp);
-- handoff_records
CREATE INDEX idx_handoff_student ON handoff_records(student_id);
CREATE INDEX idx_handoff_scenario ON handoff_records(scenario_id);
CREATE INDEX idx_handoff_session ON handoff_records(session_id);
CREATE INDEX idx_handoff_submitted ON handoff_records(submitted_at DESC);
-- sbar_drafts
CREATE INDEX idx_sbar_session ON sbar_drafts(session_id);
CREATE INDEX idx_sbar_student ON sbar_drafts(student_id);
-- =====================================================
-- 3. νΈλ¦¬κ±° ν¨μ λ° νΈλ¦¬κ±° μμ±
-- =====================================================
-- updated_at μλ μ
λ°μ΄νΈ ν¨μ
CREATE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- μΈμ
μ’
λ£ μ ended_at μλ μ
λ°μ΄νΈ ν¨μ
CREATE FUNCTION update_session_ended_at()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.status = 'completed' OR NEW.status = 'archived' THEN
IF NEW.ended_at IS NULL THEN
NEW.ended_at = NOW();
END IF;
END IF;
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- μλ μΈμ
μμ± ν¨μ (chat_history insert μ)
CREATE FUNCTION auto_create_session()
RETURNS TRIGGER AS $$
BEGIN
-- session_idκ° sessionsμ μμΌλ©΄ μλ μμ±
IF NOT EXISTS (SELECT 1 FROM sessions WHERE session_id = NEW.session_id) THEN
INSERT INTO sessions (session_id, student_id, scenario_id, status)
VALUES (NEW.session_id, NEW.student_id, NEW.scenario_id, 'active')
ON CONFLICT (session_id) DO NOTHING;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- νΈλ¦¬κ±° μμ±
CREATE TRIGGER update_patients_updated_at
BEFORE UPDATE ON patients
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_scenarios_updated_at
BEFORE UPDATE ON scenarios
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_sessions_updated_at
BEFORE UPDATE ON sessions
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_session_on_status_change
BEFORE UPDATE ON sessions
FOR EACH ROW
WHEN (OLD.status IS DISTINCT FROM NEW.status)
EXECUTE FUNCTION update_session_ended_at();
CREATE TRIGGER update_sbar_drafts_updated_at
BEFORE UPDATE ON sbar_drafts
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- chat_history insert μ sessions μλ μμ±
CREATE TRIGGER auto_create_session_trigger
BEFORE INSERT ON chat_history
FOR EACH ROW
EXECUTE FUNCTION auto_create_session();
-- =====================================================
-- 4. Row Level Security (RLS) μ€μ
-- =====================================================
-- RLS νμ±ν
ALTER TABLE patients ENABLE ROW LEVEL SECURITY;
ALTER TABLE scenarios ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE chat_history ENABLE ROW LEVEL SECURITY;
ALTER TABLE handoff_records ENABLE ROW LEVEL SECURITY;
ALTER TABLE sbar_drafts ENABLE ROW LEVEL SECURITY;
-- μ μ±
μμ± (λͺ¨λ μ¬μ©μ μ κ·Ό νμ©)
CREATE POLICY "patients_all_access" ON patients
FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "scenarios_all_access" ON scenarios
FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "sessions_all_access" ON sessions
FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "chat_history_all_access" ON chat_history
FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "handoff_records_all_access" ON handoff_records
FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "sbar_drafts_all_access" ON sbar_drafts
FOR ALL USING (true) WITH CHECK (true);
-- =====================================================
-- μλ£ λ©μμ§
-- =====================================================
DO $$
BEGIN
RAISE NOTICE '';
RAISE NOTICE 'ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ';
RAISE NOTICE 'β β
Supabase μμ μ΄κΈ°ν μλ£! β';
RAISE NOTICE 'ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ';
RAISE NOTICE '';
RAISE NOTICE 'π μμ±λ ν
μ΄λΈ:';
RAISE NOTICE ' 1. patients (νμ μ 보)';
RAISE NOTICE ' 2. scenarios (μλ리μ€)';
RAISE NOTICE ' 3. sessions (μΈμ
κ΄λ¦¬ - session_idκ° PK)';
RAISE NOTICE ' 4. chat_history (μ±ν
κΈ°λ‘)';
RAISE NOTICE ' 5. handoff_records (μΈμμΈκ³ κΈ°λ‘)';
RAISE NOTICE ' 6. sbar_drafts (SBAR μ΄μ)';
RAISE NOTICE '';
RAISE NOTICE 'π μΈλ ν€:';
RAISE NOTICE ' - scenarios β patients';
RAISE NOTICE ' - sessions β scenarios';
RAISE NOTICE ' - chat_history β sessions (μλ μμ± νΈλ¦¬κ±°)';
RAISE NOTICE ' - handoff_records β sessions, scenarios';
RAISE NOTICE ' - sbar_drafts β sessions';
RAISE NOTICE '';
RAISE NOTICE 'β‘ μλ κΈ°λ₯:';
RAISE NOTICE ' - chat_history insert μ sessions μλ μμ±';
RAISE NOTICE ' - μΈμ
μλ£ μ ended_at μλ μ€μ ';
RAISE NOTICE ' - updated_at μλ κ°±μ ';
RAISE NOTICE '';
RAISE NOTICE 'π λ€μ λ¨κ³:';
RAISE NOTICE ' uv run python init_db.py - μλλ¦¬μ€ λ°μ΄ν° λ‘λ';
RAISE NOTICE '';
END $$;
|