-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathschema.sql
More file actions
375 lines (331 loc) · 15 KB
/
Copy pathschema.sql
File metadata and controls
375 lines (331 loc) · 15 KB
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
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
-- Enable standard uuid extension if needed (PostgreSQL 13+ has gen_random_uuid() built-in)
-- CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- =========================================================================
-- 1. BASE MULTI-TENANCY
-- =========================================================================
CREATE TABLE tenant (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL UNIQUE,
code TEXT NOT NULL UNIQUE,
created_by TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
meta JSONB
);
-- =========================================================================
-- 2. METADATA REFERENCES
-- =========================================================================
CREATE TABLE leader_category (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
description TEXT,
tenant_code TEXT NOT NULL REFERENCES tenant(code) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE programs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
leaders_id UUID NOT NULL REFERENCES leader_category(id) ON DELETE CASCADE,
name TEXT NOT NULL,
description TEXT,
tenant_code TEXT NOT NULL REFERENCES tenant(code) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- =========================================================================
-- 3. PROMPT MANAGEMENT SYSTEM (Generic & Shared)
-- =========================================================================
CREATE TABLE prompts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL UNIQUE,
analysis_type TEXT NOT NULL, -- 'pii', 'theme', 'environment', etc.
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE prompt_version (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
prompt_id UUID NOT NULL REFERENCES prompts(id) ON DELETE CASCADE,
version INT NOT NULL,
system_prompt TEXT NOT NULL,
user_prompt TEXT NOT NULL, -- Template containing {{variables}}
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_by TEXT,
change_note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT unique_prompt_version UNIQUE (prompt_id, version)
);
-- =========================================================================
-- 4. CENTRAL INGESTION TRACKING
-- =========================================================================
CREATE TABLE submissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id TEXT UNIQUE, -- 32-character random alphanumeric string
submission_id TEXT NOT NULL,
tenant_code TEXT NOT NULL REFERENCES tenant(code) ON DELETE CASCADE,
submission_type TEXT NOT NULL, -- 'discussion', 'story', etc.
user_id TEXT, -- Future login integration
user_name TEXT,
role TEXT,
state TEXT,
district TEXT,
organization TEXT,
submission_date TIMESTAMPTZ,
process_status JSONB,
status TEXT NOT NULL DEFAULT 'pending', -- 'pending', 'processing', 'success', 'failed'
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
program_id UUID REFERENCES programs(id) ON DELETE SET NULL,
leader_id UUID REFERENCES leader_category(id) ON DELETE SET NULL,
CONSTRAINT unique_submission_tenant UNIQUE (submission_id, tenant_code)
);
-- =========================================================================
-- 5. SOURCE PAYLOADS (Raw CSV / Kafka Output)
-- =========================================================================
CREATE TABLE discussion_submissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
submission_id TEXT NOT NULL,
tenant_code TEXT NOT NULL,
title TEXT,
challenges TEXT[], -- one array element per discrete statement (see operations.py's _normalize_statement_list)
solutions TEXT[], -- same format as challenges
author TEXT,
language TEXT,
image_urls TEXT[] DEFAULT '{}',
blur_image_urls TEXT[] DEFAULT '{}',
pdf_urls TEXT[] DEFAULT '{}',
masked_pdf_urls TEXT[] DEFAULT '{}',
transcript_link TEXT,
pii_masked BOOLEAN NOT NULL DEFAULT FALSE,
pii_masked_at TEXT[] DEFAULT '{}',
abusive_masked_at TEXT[] DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
meta_data JSONB,
FOREIGN KEY (submission_id, tenant_code)
REFERENCES submissions(submission_id, tenant_code) ON DELETE CASCADE
);
CREATE TABLE story_submissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
submission_id TEXT NOT NULL,
tenant_code TEXT NOT NULL,
title TEXT,
objective TEXT,
challenge TEXT,
action_steps TEXT,
impact TEXT,
duration TEXT,
blurb TEXT,
content TEXT,
image_urls TEXT[] DEFAULT '{}',
blur_image_urls TEXT[] DEFAULT '{}',
pdf_urls TEXT[] DEFAULT '{}',
masked_pdf_urls TEXT[] DEFAULT '{}',
transcript_link TEXT,
pii_masked BOOLEAN NOT NULL DEFAULT FALSE,
pii_masked_at TEXT[] DEFAULT '{}',
abusive_masked_at TEXT[] DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
meta_data JSONB,
FOREIGN KEY (submission_id, tenant_code)
REFERENCES submissions(submission_id, tenant_code) ON DELETE CASCADE
);
-- =========================================================================
-- 6. EXECUTION & AUDIT LOGGING
-- =========================================================================
CREATE TABLE llm_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
submission_id TEXT NOT NULL,
tenant_code TEXT NOT NULL,
model_name TEXT NOT NULL,
model_version TEXT,
analysis_type TEXT NOT NULL,
prompt_version_id UUID NOT NULL REFERENCES prompt_version(id),
prompt_tokens INT NOT NULL DEFAULT 0,
completion_tokens INT NOT NULL DEFAULT 0,
total_tokens INT GENERATED ALWAYS AS (prompt_tokens + completion_tokens) STORED,
status TEXT NOT NULL, -- 'success', 'failed', 'timeout', 'retried'
error_message TEXT,
called_at TIMESTAMPTZ NOT NULL DEFAULT now(),
meta_data JSONB,
FOREIGN KEY (submission_id, tenant_code)
REFERENCES submissions(submission_id, tenant_code) ON DELETE CASCADE
);
-- =========================================================================
-- 7. TAXONOMY (Global)
-- =========================================================================
CREATE TABLE themes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL UNIQUE,
definitions TEXT,
keywords TEXT,
examples TEXT,
status TEXT -- 'Approved', 'Rejected', 'Merged', 'Draft'
-- total_objective_count INTEGER DEFAULT 0, --newly added can be removed
-- original_statement_text TEXT[] DEFAULT '{}' --newly added can be removed
);
-- =========================================================================
-- 8. THEMATIC & ENVIRONMENTAL EXTRACTION OUTPUTS
-- =========================================================================
CREATE TABLE analysis_results (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
submission_id TEXT NOT NULL,
tenant_code TEXT NOT NULL,
theme_id UUID REFERENCES themes(id) ON DELETE SET NULL, -- Nullable for environmental analysis
analysis_type TEXT NOT NULL, -- 'theme', 'environment'
statements TEXT,
statement_type TEXT, -- Column/context identifier (e.g. 'challenges', 'solutions', 'objective')
improvement_environment TEXT,
similarity_score FLOAT, -- Cosine similarity from local embedding match
confidence_score FLOAT, -- Confidence score from local embedding match
justification TEXT,
multi_theme_mapped BOOLEAN NOT NULL DEFAULT FALSE,
category_type TEXT, -- 'Standard', 'Others', 'Unknown/Unclear', 'Flagged'
meta_data JSONB,
FOREIGN KEY (submission_id, tenant_code)
REFERENCES submissions(submission_id, tenant_code) ON DELETE CASCADE
);
-- =========================================================================
-- 9. QUALITATIVE SCORING & SUMMARIES
-- =========================================================================
CREATE TABLE ranking (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
submission_id TEXT NOT NULL,
tenant_code TEXT NOT NULL,
criteria_data JSONB NOT NULL, -- Rich criteria-specific scores & justifications
composite_score FLOAT NOT NULL,
tier TEXT, -- 'Tier 1', 'Tier 2', etc.
overall_summary TEXT, -- Concise LLM qualitative report summary
meta_data JSONB,
FOREIGN KEY (submission_id, tenant_code)
REFERENCES submissions(submission_id, tenant_code) ON DELETE CASCADE
);
-- =========================================================================
-- 10. DYNAMIC KPI METRICS (EAV Model)
-- =========================================================================
CREATE TABLE metric_definitions (
code TEXT PRIMARY KEY, -- 'men', 'women', 'duration'
label TEXT NOT NULL,
value_type TEXT NOT NULL DEFAULT 'numeric' CHECK (value_type IN ('numeric', 'text')),
submission_type TEXT, -- Scoped payload type ('discussion', 'story')
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE submission_metrics (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
submission_id TEXT NOT NULL,
tenant_code TEXT NOT NULL,
metric_code TEXT NOT NULL REFERENCES metric_definitions(code) ON DELETE CASCADE,
numeric_value INT,
text_value TEXT,
CONSTRAINT one_value_required CHECK (numeric_value IS NOT NULL OR text_value IS NOT NULL),
CONSTRAINT unique_submission_metric UNIQUE (submission_id, tenant_code, metric_code),
FOREIGN KEY (submission_id, tenant_code)
REFERENCES submissions(submission_id, tenant_code) ON DELETE CASCADE
);
-- =========================================================================
-- INDEXES FOR HIGH-PERFORMANCE ANALYTICS
-- =========================================================================
-- Multi-tenancy isolation indexes
CREATE INDEX idx_submissions_tenant ON submissions (tenant_code);
CREATE INDEX idx_discussion_tenant ON discussion_submissions (tenant_code);
CREATE INDEX idx_story_tenant ON story_submissions (tenant_code);
CREATE INDEX idx_llm_logs_tenant ON llm_logs (tenant_code);
CREATE INDEX idx_analysis_results_tenant ON analysis_results (tenant_code);
CREATE INDEX idx_ranking_tenant ON ranking (tenant_code);
CREATE INDEX idx_submission_metrics_tenant ON submission_metrics (tenant_code);
-- Composite query mapping indexes (Foreign key performance optimization)
CREATE INDEX idx_discussion_submission_mapping ON discussion_submissions (submission_id, tenant_code);
CREATE INDEX idx_story_submission_mapping ON story_submissions (submission_id, tenant_code);
CREATE INDEX idx_llm_logs_submission_mapping ON llm_logs (submission_id, tenant_code);
CREATE INDEX idx_analysis_results_submission_mapping ON analysis_results (submission_id, tenant_code);
CREATE INDEX idx_ranking_submission_mapping ON ranking (submission_id, tenant_code);
CREATE INDEX idx_submission_metrics_mapping ON submission_metrics (submission_id, tenant_code);
-- Program & Leader category filtering
CREATE INDEX idx_submissions_program ON submissions (program_id);
CREATE INDEX idx_submissions_leader ON submissions (leader_id);
CREATE INDEX idx_programs_leader ON programs (leaders_id);
-- Theme-specific analytics
CREATE INDEX idx_analysis_results_theme ON analysis_results (theme_id) WHERE theme_id IS NOT NULL;
CREATE INDEX idx_analysis_results_type ON analysis_results (analysis_type);
-- Prompt version active check
CREATE INDEX idx_prompt_version_active ON prompt_version (prompt_id) WHERE is_active = TRUE;
-- LLM log analysis performance
CREATE INDEX idx_llm_logs_called ON llm_logs (called_at DESC);
CREATE INDEX idx_llm_logs_analysis_type ON llm_logs (analysis_type);
-- Dynamic metric filtering
CREATE INDEX idx_submission_metrics_code ON submission_metrics (metric_code);
-- -- =========================================================================
-- -- EXPANDED VIEWS (To bypass JOINs in BI tools like Metabase)
-- -- =========================================================================
-- CREATE OR REPLACE VIEW story_submissions_expanded AS
-- SELECT
-- s.id AS submission_uuid,
-- ss.id AS story_payload_uuid,
-- ss.submission_id,
-- ss.tenant_code,
-- s.session_id,
-- s.submission_type,
-- s.user_id,
-- s.user_name,
-- s.role,
-- s.state,
-- s.district,
-- s.organization,
-- s.submission_date,
-- s.status AS ingestion_status,
-- s.program_id,
-- s.leader_id,
-- ss.title,
-- ss.objective,
-- ss.challenge,
-- ss.action_steps,
-- ss.impact,
-- ss.duration,
-- ss.blurb,
-- ss.content,
-- ss.image_urls,
-- ss.blur_image_urls,
-- ss.pdf_urls,
-- ss.transcript_link,
-- ss.pii_masked,
-- ss.created_at,
-- ss.updated_at
-- FROM story_submissions ss
-- JOIN submissions s
-- ON ss.submission_id = s.submission_id
-- AND ss.tenant_code = s.tenant_code;
-- CREATE OR REPLACE VIEW discussion_submissions_expanded AS
-- SELECT
-- s.id AS submission_uuid,
-- ds.id AS discussion_payload_uuid,
-- ds.submission_id,
-- ds.tenant_code,
-- s.session_id,
-- s.submission_type,
-- s.user_id,
-- s.user_name,
-- s.role,
-- s.state,
-- s.district,
-- s.organization,
-- s.submission_date,
-- s.status AS ingestion_status,
-- s.program_id,
-- s.leader_id,
-- ds.title,
-- ds.challenges,
-- ds.solutions,
-- ds.author,
-- ds.language,
-- ds.image_urls,
-- ds.blur_image_urls,
-- ds.pdf_urls,
-- ds.transcript_link,
-- ds.pii_masked,
-- ds.created_at,
-- ds.updated_at
-- FROM discussion_submissions ds
-- JOIN submissions s
-- ON ds.submission_id = s.submission_id
-- AND ds.tenant_code = s.tenant_code;