@studious-lms/server 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/.dockerignore +28 -0
  2. package/.env.example +5 -0
  3. package/.github/workflows/deploy.yml +123 -0
  4. package/Dockerfile +54 -0
  5. package/dist/index.js +5 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/lib/config/cors.d.ts.map +1 -1
  8. package/dist/lib/config/cors.js +31 -11
  9. package/dist/lib/config/cors.js.map +1 -1
  10. package/dist/lib/config/env.d.ts +17 -0
  11. package/dist/lib/config/env.d.ts.map +1 -1
  12. package/dist/lib/config/env.js +8 -2
  13. package/dist/lib/config/env.js.map +1 -1
  14. package/dist/lib/googleCloudStorage.d.ts +10 -0
  15. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  16. package/dist/lib/googleCloudStorage.js +22 -2
  17. package/dist/lib/googleCloudStorage.js.map +1 -1
  18. package/dist/lib/prisma.d.ts +104 -5
  19. package/dist/lib/prisma.d.ts.map +1 -1
  20. package/dist/lib/prisma.js +33 -2
  21. package/dist/lib/prisma.js.map +1 -1
  22. package/dist/models/agenda.d.ts +20 -20
  23. package/dist/models/announcement.d.ts +177 -69
  24. package/dist/models/announcement.d.ts.map +1 -1
  25. package/dist/models/assignment.d.ts +551 -353
  26. package/dist/models/assignment.d.ts.map +1 -1
  27. package/dist/models/attendance.d.ts +197 -71
  28. package/dist/models/attendance.d.ts.map +1 -1
  29. package/dist/models/auth.d.ts +348 -114
  30. package/dist/models/auth.d.ts.map +1 -1
  31. package/dist/models/class.d.ts +324 -198
  32. package/dist/models/class.d.ts.map +1 -1
  33. package/dist/models/class.js +2 -2
  34. package/dist/models/class.js.map +1 -1
  35. package/dist/models/cloudStorage.d.ts +146 -56
  36. package/dist/models/cloudStorage.d.ts.map +1 -1
  37. package/dist/models/comment.d.ts +267 -115
  38. package/dist/models/comment.d.ts.map +1 -1
  39. package/dist/models/conversation.d.ts +199 -73
  40. package/dist/models/conversation.d.ts.map +1 -1
  41. package/dist/models/department.d.ts +196 -70
  42. package/dist/models/department.d.ts.map +1 -1
  43. package/dist/models/event.d.ts +287 -125
  44. package/dist/models/event.d.ts.map +1 -1
  45. package/dist/models/file.d.ts +389 -263
  46. package/dist/models/file.d.ts.map +1 -1
  47. package/dist/models/folder.d.ts +433 -181
  48. package/dist/models/folder.d.ts.map +1 -1
  49. package/dist/models/labChat.d.ts +209 -83
  50. package/dist/models/labChat.d.ts.map +1 -1
  51. package/dist/models/marketing.d.ts +80 -26
  52. package/dist/models/marketing.d.ts.map +1 -1
  53. package/dist/models/message.d.ts +95 -41
  54. package/dist/models/message.d.ts.map +1 -1
  55. package/dist/models/newtonChat.d.ts +83 -29
  56. package/dist/models/newtonChat.d.ts.map +1 -1
  57. package/dist/models/notification.d.ts +61 -25
  58. package/dist/models/notification.d.ts.map +1 -1
  59. package/dist/models/school.d.ts +349 -133
  60. package/dist/models/school.d.ts.map +1 -1
  61. package/dist/models/section.d.ts +216 -72
  62. package/dist/models/section.d.ts.map +1 -1
  63. package/dist/models/tag.d.ts +156 -48
  64. package/dist/models/tag.d.ts.map +1 -1
  65. package/dist/models/user.d.ts +82 -28
  66. package/dist/models/user.d.ts.map +1 -1
  67. package/dist/models/worksheet.d.ts +1020 -411
  68. package/dist/models/worksheet.d.ts.map +1 -1
  69. package/dist/models/worksheet.js +8 -2
  70. package/dist/models/worksheet.js.map +1 -1
  71. package/dist/pipelines/aiLabChat.d.ts +0 -8
  72. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  73. package/dist/pipelines/aiLabChat.js +50 -67
  74. package/dist/pipelines/aiLabChat.js.map +1 -1
  75. package/dist/pipelines/aiLabChatContract.d.ts +393 -388
  76. package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
  77. package/dist/pipelines/aiLabChatContract.js +63 -69
  78. package/dist/pipelines/aiLabChatContract.js.map +1 -1
  79. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
  80. package/dist/pipelines/aiNewtonChat.js +41 -41
  81. package/dist/pipelines/aiNewtonChat.js.map +1 -1
  82. package/dist/pipelines/gradeWorksheet.d.ts +8 -8
  83. package/dist/pipelines/labChatPrompt.d.ts +10 -8
  84. package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
  85. package/dist/pipelines/labChatPrompt.js +47 -67
  86. package/dist/pipelines/labChatPrompt.js.map +1 -1
  87. package/dist/pipelines/pdfToWorksheet.d.ts +2 -2
  88. package/dist/routers/_app.d.ts +2203 -1957
  89. package/dist/routers/_app.d.ts.map +1 -1
  90. package/dist/routers/_app.js +4 -2
  91. package/dist/routers/_app.js.map +1 -1
  92. package/dist/routers/admin.d.ts +13 -13
  93. package/dist/routers/agenda.d.ts +18 -18
  94. package/dist/routers/announcement.d.ts +32 -32
  95. package/dist/routers/assignment.d.ts +335 -335
  96. package/dist/routers/attendance.d.ts +10 -10
  97. package/dist/routers/auth.d.ts +2 -2
  98. package/dist/routers/class.d.ts +147 -147
  99. package/dist/routers/comment.d.ts +22 -22
  100. package/dist/routers/conversation.d.ts +17 -17
  101. package/dist/routers/department.d.ts +34 -34
  102. package/dist/routers/discussion.d.ts +65 -53
  103. package/dist/routers/discussion.d.ts.map +1 -1
  104. package/dist/routers/discussion.js +6 -2
  105. package/dist/routers/discussion.js.map +1 -1
  106. package/dist/routers/embedding.d.ts +69 -0
  107. package/dist/routers/embedding.d.ts.map +1 -0
  108. package/dist/routers/embedding.js +143 -0
  109. package/dist/routers/embedding.js.map +1 -0
  110. package/dist/routers/event.d.ts +39 -39
  111. package/dist/routers/file.d.ts +12 -12
  112. package/dist/routers/folder.d.ts +38 -38
  113. package/dist/routers/labChat.d.ts +19 -19
  114. package/dist/routers/marketing.d.ts +2 -2
  115. package/dist/routers/message.d.ts +13 -13
  116. package/dist/routers/newtonChat.d.ts +4 -4
  117. package/dist/routers/notifications.d.ts +9 -9
  118. package/dist/routers/permissions.d.ts +14 -14
  119. package/dist/routers/school.d.ts +55 -55
  120. package/dist/routers/search.d.ts +22 -1
  121. package/dist/routers/search.d.ts.map +1 -1
  122. package/dist/routers/search.js +9 -3
  123. package/dist/routers/search.js.map +1 -1
  124. package/dist/routers/section.d.ts +4 -4
  125. package/dist/routers/studentProgress.d.ts +1 -1
  126. package/dist/routers/tag.d.ts +7 -7
  127. package/dist/routers/user.d.ts +10 -10
  128. package/dist/routers/worksheet.d.ts +95 -57
  129. package/dist/routers/worksheet.d.ts.map +1 -1
  130. package/dist/routers/worksheet.js +26 -2
  131. package/dist/routers/worksheet.js.map +1 -1
  132. package/dist/routes/aiStream.d.ts +2 -0
  133. package/dist/routes/aiStream.d.ts.map +1 -0
  134. package/dist/routes/aiStream.js +696 -0
  135. package/dist/routes/aiStream.js.map +1 -0
  136. package/dist/seedDatabase.d.ts +2 -2
  137. package/dist/seedDatabase.js +6 -6
  138. package/dist/seedDatabase.js.map +1 -1
  139. package/dist/services/adminInstitution.d.ts +8 -8
  140. package/dist/services/adminRunJob.d.ts +4 -4
  141. package/dist/services/agenda.d.ts +18 -18
  142. package/dist/services/aiChatStream.d.ts +68 -0
  143. package/dist/services/aiChatStream.d.ts.map +1 -0
  144. package/dist/services/aiChatStream.js +157 -0
  145. package/dist/services/aiChatStream.js.map +1 -0
  146. package/dist/services/aiModifierTools.d.ts +32 -0
  147. package/dist/services/aiModifierTools.d.ts.map +1 -0
  148. package/dist/services/aiModifierTools.js +165 -0
  149. package/dist/services/aiModifierTools.js.map +1 -0
  150. package/dist/services/aiProposalTools.d.ts +32 -0
  151. package/dist/services/aiProposalTools.d.ts.map +1 -0
  152. package/dist/services/aiProposalTools.js +207 -0
  153. package/dist/services/aiProposalTools.js.map +1 -0
  154. package/dist/services/aiStream.d.ts +22 -0
  155. package/dist/services/aiStream.d.ts.map +1 -0
  156. package/dist/services/aiStream.js +142 -0
  157. package/dist/services/aiStream.js.map +1 -0
  158. package/dist/services/aiTools.d.ts +16 -0
  159. package/dist/services/aiTools.d.ts.map +1 -0
  160. package/dist/services/aiTools.js +271 -0
  161. package/dist/services/aiTools.js.map +1 -0
  162. package/dist/services/announcement.d.ts +12 -12
  163. package/dist/services/announcement.d.ts.map +1 -1
  164. package/dist/services/announcement.js +7 -2
  165. package/dist/services/announcement.js.map +1 -1
  166. package/dist/services/assignment.d.ts +293 -293
  167. package/dist/services/assignment.d.ts.map +1 -1
  168. package/dist/services/assignment.js +28 -9
  169. package/dist/services/assignment.js.map +1 -1
  170. package/dist/services/attendance.d.ts +10 -10
  171. package/dist/services/auth.d.ts +2 -2
  172. package/dist/services/class.d.ts +138 -138
  173. package/dist/services/class.d.ts.map +1 -1
  174. package/dist/services/class.js +19 -3
  175. package/dist/services/class.js.map +1 -1
  176. package/dist/services/comment.d.ts +22 -22
  177. package/dist/services/conversation.d.ts +17 -17
  178. package/dist/services/department.d.ts +33 -33
  179. package/dist/services/discussion.d.ts +58 -58
  180. package/dist/services/discussion.d.ts.map +1 -1
  181. package/dist/services/discussion.js +8 -8
  182. package/dist/services/discussion.js.map +1 -1
  183. package/dist/services/discussionSummary.d.ts +21 -0
  184. package/dist/services/discussionSummary.d.ts.map +1 -0
  185. package/dist/services/discussionSummary.js +179 -0
  186. package/dist/services/discussionSummary.js.map +1 -0
  187. package/dist/services/embedding.d.ts +67 -0
  188. package/dist/services/embedding.d.ts.map +1 -0
  189. package/dist/services/embedding.js +226 -0
  190. package/dist/services/embedding.js.map +1 -0
  191. package/dist/services/event.d.ts +37 -37
  192. package/dist/services/file.d.ts +24 -24
  193. package/dist/services/folder.d.ts +36 -36
  194. package/dist/services/labChat.d.ts +19 -19
  195. package/dist/services/marketing.d.ts +2 -2
  196. package/dist/services/message.d.ts +11 -11
  197. package/dist/services/message.d.ts.map +1 -1
  198. package/dist/services/message.js +2 -2
  199. package/dist/services/message.js.map +1 -1
  200. package/dist/services/newtonChat.d.ts +4 -4
  201. package/dist/services/notification.d.ts +9 -9
  202. package/dist/services/notification.d.ts.map +1 -1
  203. package/dist/services/permissions.d.ts +14 -14
  204. package/dist/services/school.d.ts +50 -50
  205. package/dist/services/search.d.ts +12 -0
  206. package/dist/services/search.d.ts.map +1 -1
  207. package/dist/services/search.js +120 -2
  208. package/dist/services/search.js.map +1 -1
  209. package/dist/services/section.d.ts +3 -3
  210. package/dist/services/tag.d.ts +4 -4
  211. package/dist/services/user.d.ts +4 -4
  212. package/dist/services/user.d.ts.map +1 -1
  213. package/dist/services/user.js +10 -15
  214. package/dist/services/user.js.map +1 -1
  215. package/dist/services/worksheet.d.ts +60 -48
  216. package/dist/services/worksheet.d.ts.map +1 -1
  217. package/dist/services/worksheet.js +11 -4
  218. package/dist/services/worksheet.js.map +1 -1
  219. package/dist/utils/streamBroadcast.d.ts +11 -0
  220. package/dist/utils/streamBroadcast.d.ts.map +1 -0
  221. package/dist/utils/streamBroadcast.js +32 -0
  222. package/dist/utils/streamBroadcast.js.map +1 -0
  223. package/dist/workers/connection.d.ts +15 -0
  224. package/dist/workers/connection.d.ts.map +1 -1
  225. package/dist/workers/connection.js +20 -2
  226. package/dist/workers/connection.js.map +1 -1
  227. package/dist/workers/index.js +4 -2
  228. package/dist/workers/index.js.map +1 -1
  229. package/dist/workers/processors/createRunJobWorker.d.ts.map +1 -1
  230. package/dist/workers/processors/createRunJobWorker.js +31 -8
  231. package/dist/workers/processors/createRunJobWorker.js.map +1 -1
  232. package/dist/workers/processors/embedContent.d.ts +8 -0
  233. package/dist/workers/processors/embedContent.d.ts.map +1 -0
  234. package/dist/workers/processors/embedContent.js +76 -0
  235. package/dist/workers/processors/embedContent.js.map +1 -0
  236. package/dist/workers/queues.d.ts +6 -0
  237. package/dist/workers/queues.d.ts.map +1 -1
  238. package/dist/workers/queues.js +5 -3
  239. package/dist/workers/queues.js.map +1 -1
  240. package/package.json +5 -1
  241. package/prisma/migrations/20260609215135_init/migration.sql +1412 -0
  242. package/prisma/migrations/20260610130000_add_worksheet_tags/migration.sql +13 -0
  243. package/prisma/schema.prisma +38 -7
  244. package/src/index.ts +4 -0
  245. package/src/lib/config/cors.ts +32 -9
  246. package/src/lib/config/env.ts +6 -0
  247. package/src/lib/googleCloudStorage.ts +21 -0
  248. package/src/lib/prisma.ts +40 -1
  249. package/src/models/class.ts +3 -2
  250. package/src/models/worksheet.ts +5 -2
  251. package/src/pipelines/aiLabChat.ts +54 -79
  252. package/src/pipelines/aiLabChatContract.ts +69 -69
  253. package/src/pipelines/aiNewtonChat.ts +46 -43
  254. package/src/pipelines/labChatPrompt.ts +63 -88
  255. package/src/routers/_app.ts +2 -0
  256. package/src/routers/discussion.ts +7 -0
  257. package/src/routers/embedding.ts +159 -0
  258. package/src/routers/search.ts +10 -1
  259. package/src/routers/worksheet.ts +27 -0
  260. package/src/routes/aiStream.ts +789 -0
  261. package/src/seedDatabase.ts +4 -4
  262. package/src/services/aiChatStream.ts +219 -0
  263. package/src/services/aiModifierTools.ts +188 -0
  264. package/src/services/aiProposalTools.ts +272 -0
  265. package/src/services/aiStream.ts +175 -0
  266. package/src/services/aiTools.ts +290 -0
  267. package/src/services/announcement.ts +7 -0
  268. package/src/services/assignment.ts +28 -7
  269. package/src/services/class.ts +20 -1
  270. package/src/services/discussion.ts +9 -8
  271. package/src/services/discussionSummary.ts +226 -0
  272. package/src/services/embedding.ts +285 -0
  273. package/src/services/message.ts +2 -2
  274. package/src/services/search.ts +138 -0
  275. package/src/services/user.ts +9 -17
  276. package/src/services/worksheet.ts +9 -2
  277. package/src/utils/streamBroadcast.ts +48 -0
  278. package/src/workers/connection.ts +19 -0
  279. package/src/workers/index.ts +2 -0
  280. package/src/workers/processors/createRunJobWorker.ts +32 -6
  281. package/src/workers/processors/embedContent.ts +90 -0
  282. package/src/workers/queues.ts +5 -1
  283. package/tests/unit/pipelines/aiLabChatContract.test.ts +38 -21
  284. package/tests/unit/pipelines/labChatPrompt.test.ts +23 -36
  285. package/prisma/migrations/20250807062924_init/migration.sql +0 -436
  286. package/prisma/migrations/20250919063704_init2/migration.sql +0 -24
  287. package/prisma/migrations/20250920143543_add_profile_fields/migration.sql +0 -15
  288. package/prisma/migrations/20250922165147_add_chat_models/migration.sql +0 -68
  289. package/prisma/migrations/20250922165314_add_chat_roles/migration.sql +0 -5
  290. package/prisma/migrations/20250922171242_refactor_notification_system/migration.sql +0 -20
  291. package/prisma/migrations/20250922172208_add_mentions_system/migration.sql +0 -21
  292. package/prisma/migrations/20250925072732_add_lab_chat_system/migration.sql +0 -25
  293. package/prisma/migrations/20251020151505_add_upload_tracking_fields/migration.sql +0 -57
  294. package/prisma/migrations/20251109122857_annuoncements_comments/migration.sql +0 -30
  295. package/prisma/migrations/20251109135555_reactions_announcements_comments/migration.sql +0 -35
  296. package/prisma/migrations/20260410124000_add_submission_recommendation_state/migration.sql +0 -14
  297. package/prisma/migrations/20260415103500_add_session_type/migration.sql +0 -33
  298. package/prisma/migrations/20260415133000_add_ai_usage_logs/migration.sql +0 -19
  299. package/prisma/migrations/20260417083000_add_conversation_member_hidden_at/migration.sql +0 -2
  300. package/prisma/migrations/20260502230500_assignment_submission_comments/migration.sql +0 -60
  301. package/prisma/migrations/20260504071500_school_memberships/migration.sql +0 -81
  302. package/prisma/migrations/20260506162500_consolidate_run_job_and_unify_job_status/migration.sql +0 -166
  303. package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +0 -184
  304. package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +0 -93
  305. package/prisma/migrations/20260510183000_add_discussions/migration.sql +0 -151
  306. /package/.github/workflows/{npm.yml → npm-publish.yml} +0 -0
@@ -1,30 +0,0 @@
1
- -- AlterTable
2
- ALTER TABLE "public"."Announcement" ADD COLUMN "modifiedAt" TIMESTAMP(3);
3
-
4
- -- AlterTable
5
- ALTER TABLE "public"."File" ADD COLUMN "announcementId" TEXT;
6
-
7
- -- CreateTable
8
- CREATE TABLE "public"."AnnouncementComment" (
9
- "id" TEXT NOT NULL,
10
- "content" TEXT NOT NULL,
11
- "authorId" TEXT NOT NULL,
12
- "announcementId" TEXT NOT NULL,
13
- "parentCommentId" TEXT,
14
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
15
- "modifiedAt" TIMESTAMP(3),
16
-
17
- CONSTRAINT "AnnouncementComment_pkey" PRIMARY KEY ("id")
18
- );
19
-
20
- -- AddForeignKey
21
- ALTER TABLE "public"."File" ADD CONSTRAINT "File_announcementId_fkey" FOREIGN KEY ("announcementId") REFERENCES "public"."Announcement"("id") ON DELETE CASCADE ON UPDATE CASCADE;
22
-
23
- -- AddForeignKey
24
- ALTER TABLE "public"."AnnouncementComment" ADD CONSTRAINT "AnnouncementComment_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
25
-
26
- -- AddForeignKey
27
- ALTER TABLE "public"."AnnouncementComment" ADD CONSTRAINT "AnnouncementComment_announcementId_fkey" FOREIGN KEY ("announcementId") REFERENCES "public"."Announcement"("id") ON DELETE CASCADE ON UPDATE CASCADE;
28
-
29
- -- AddForeignKey
30
- ALTER TABLE "public"."AnnouncementComment" ADD CONSTRAINT "AnnouncementComment_parentCommentId_fkey" FOREIGN KEY ("parentCommentId") REFERENCES "public"."AnnouncementComment"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -1,35 +0,0 @@
1
- -- CreateEnum
2
- CREATE TYPE "public"."ReactionType" AS ENUM ('THUMBSUP', 'CELEBRATE', 'CARE', 'HEART', 'IDEA', 'HAPPY');
3
-
4
- -- CreateTable
5
- CREATE TABLE "public"."Reaction" (
6
- "id" TEXT NOT NULL,
7
- "type" "public"."ReactionType" NOT NULL,
8
- "userId" TEXT NOT NULL,
9
- "announcementId" TEXT,
10
- "commentId" TEXT,
11
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
12
-
13
- CONSTRAINT "Reaction_pkey" PRIMARY KEY ("id")
14
- );
15
-
16
- -- CreateIndex
17
- CREATE INDEX "Reaction_announcementId_idx" ON "public"."Reaction"("announcementId");
18
-
19
- -- CreateIndex
20
- CREATE INDEX "Reaction_commentId_idx" ON "public"."Reaction"("commentId");
21
-
22
- -- CreateIndex
23
- CREATE UNIQUE INDEX "Reaction_userId_announcementId_key" ON "public"."Reaction"("userId", "announcementId");
24
-
25
- -- CreateIndex
26
- CREATE UNIQUE INDEX "Reaction_userId_commentId_key" ON "public"."Reaction"("userId", "commentId");
27
-
28
- -- AddForeignKey
29
- ALTER TABLE "public"."Reaction" ADD CONSTRAINT "Reaction_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
30
-
31
- -- AddForeignKey
32
- ALTER TABLE "public"."Reaction" ADD CONSTRAINT "Reaction_announcementId_fkey" FOREIGN KEY ("announcementId") REFERENCES "public"."Announcement"("id") ON DELETE CASCADE ON UPDATE CASCADE;
33
-
34
- -- AddForeignKey
35
- ALTER TABLE "public"."Reaction" ADD CONSTRAINT "Reaction_commentId_fkey" FOREIGN KEY ("commentId") REFERENCES "public"."AnnouncementComment"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -1,14 +0,0 @@
1
- -- CreateEnum
2
- CREATE TYPE "SubmissionRecommendationState" AS ENUM ('NONE', 'OPEN', 'ASSIGNED', 'DISMISSED');
3
-
4
- -- AlterTable
5
- ALTER TABLE "Submission"
6
- ADD COLUMN "recommendationState" "SubmissionRecommendationState" NOT NULL DEFAULT 'NONE',
7
- ADD COLUMN "recommendationUpdatedAt" TIMESTAMP(3),
8
- ADD COLUMN "targetedAssignmentId" TEXT;
9
-
10
- -- CreateIndex
11
- CREATE INDEX "Submission_studentId_recommendationState_idx" ON "Submission"("studentId", "recommendationState");
12
-
13
- -- AddForeignKey
14
- ALTER TABLE "Submission" ADD CONSTRAINT "Submission_targetedAssignmentId_fkey" FOREIGN KEY ("targetedAssignmentId") REFERENCES "Assignment"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -1,33 +0,0 @@
1
- -- CreateEnum
2
- CREATE TYPE "SessionType" AS ENUM ('AUTH', 'EMAIL_VERIFICATION', 'PASSWORD_RESET', 'CLASS_INVITE');
3
-
4
- -- AlterTable
5
- ALTER TABLE "Session"
6
- ADD COLUMN "type" "SessionType" NOT NULL DEFAULT 'AUTH';
7
-
8
- -- Backfill existing non-auth session records when they can be inferred safely.
9
- UPDATE "Session"
10
- SET "type" = 'CLASS_INVITE'
11
- WHERE "classId" IS NOT NULL;
12
-
13
- -- This Session.type backfill uses the expiresAt <= NOW() + INTERVAL '2 hours'
14
- -- heuristic to identify password reset tokens. It may misclassify rare short-lived
15
- -- AUTH sessions, but this one-time migration safely fails those sessions until users re-login.
16
- UPDATE "Session"
17
- SET "type" = 'PASSWORD_RESET'
18
- WHERE "userId" IS NOT NULL
19
- AND "classId" IS NULL
20
- AND "expiresAt" IS NOT NULL
21
- AND "expiresAt" <= NOW() + INTERVAL '2 hours';
22
-
23
- UPDATE "Session"
24
- SET "type" = 'EMAIL_VERIFICATION'
25
- WHERE "userId" IS NOT NULL
26
- AND "classId" IS NULL
27
- AND "type" = 'AUTH'
28
- AND EXISTS (
29
- SELECT 1
30
- FROM "User"
31
- WHERE "User"."id" = "Session"."userId"
32
- AND "User"."verified" = false
33
- );
@@ -1,19 +0,0 @@
1
- CREATE TABLE "AiUsageLog" (
2
- "id" TEXT NOT NULL,
3
- "reason" TEXT NOT NULL,
4
- "provider" TEXT NOT NULL DEFAULT 'openai',
5
- "model" TEXT NOT NULL,
6
- "operation" TEXT NOT NULL,
7
- "success" BOOLEAN NOT NULL DEFAULT true,
8
- "promptTokens" INTEGER,
9
- "completionTokens" INTEGER,
10
- "totalTokens" INTEGER,
11
- "estimatedInputTokens" INTEGER,
12
- "metadata" JSONB DEFAULT '{}'::jsonb,
13
- "error" TEXT,
14
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
15
-
16
- CONSTRAINT "AiUsageLog_pkey" PRIMARY KEY ("id")
17
- );
18
-
19
- CREATE INDEX "AiUsageLog_reason_createdAt_idx" ON "AiUsageLog"("reason", "createdAt");
@@ -1,2 +0,0 @@
1
- ALTER TABLE "ConversationMember"
2
- ADD COLUMN "hiddenAt" TIMESTAMP(3);
@@ -1,60 +0,0 @@
1
- ALTER TABLE "public"."Comment" ADD COLUMN "assignmentId" TEXT;
2
- ALTER TABLE "public"."Comment" ADD COLUMN "submissionId" TEXT;
3
-
4
- CREATE INDEX "Comment_assignmentId_idx" ON "public"."Comment"("assignmentId");
5
- CREATE INDEX "Comment_submissionId_idx" ON "public"."Comment"("submissionId");
6
-
7
- ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_assignmentId_fkey" FOREIGN KEY ("assignmentId") REFERENCES "public"."Assignment"("id") ON DELETE CASCADE ON UPDATE CASCADE;
8
- ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_submissionId_fkey" FOREIGN KEY ("submissionId") REFERENCES "public"."Submission"("id") ON DELETE CASCADE ON UPDATE CASCADE;
9
-
10
- WITH RECURSIVE "CommentOwnerContext" AS (
11
- SELECT
12
- "id",
13
- "parentCommentId",
14
- "announcementId",
15
- "assignmentId",
16
- "submissionId",
17
- "studentQuestionProgressId"
18
- FROM "public"."Comment"
19
- WHERE "parentCommentId" IS NULL
20
-
21
- UNION ALL
22
-
23
- SELECT
24
- child."id",
25
- child."parentCommentId",
26
- COALESCE(child."announcementId", parent."announcementId"),
27
- COALESCE(child."assignmentId", parent."assignmentId"),
28
- COALESCE(child."submissionId", parent."submissionId"),
29
- COALESCE(child."studentQuestionProgressId", parent."studentQuestionProgressId")
30
- FROM "public"."Comment" child
31
- INNER JOIN "CommentOwnerContext" parent ON child."parentCommentId" = parent."id"
32
- )
33
- UPDATE "public"."Comment" c
34
- SET
35
- "announcementId" = owner."announcementId",
36
- "assignmentId" = owner."assignmentId",
37
- "submissionId" = owner."submissionId",
38
- "studentQuestionProgressId" = owner."studentQuestionProgressId"
39
- FROM "CommentOwnerContext" owner
40
- WHERE c."id" = owner."id"
41
- AND c."parentCommentId" IS NOT NULL
42
- AND (
43
- (CASE WHEN c."assignmentId" IS NOT NULL THEN 1 ELSE 0 END) +
44
- (CASE WHEN c."submissionId" IS NOT NULL THEN 1 ELSE 0 END) +
45
- (CASE WHEN c."announcementId" IS NOT NULL THEN 1 ELSE 0 END) +
46
- (CASE WHEN c."studentQuestionProgressId" IS NOT NULL THEN 1 ELSE 0 END)
47
- ) = 0
48
- AND (
49
- (CASE WHEN owner."assignmentId" IS NOT NULL THEN 1 ELSE 0 END) +
50
- (CASE WHEN owner."submissionId" IS NOT NULL THEN 1 ELSE 0 END) +
51
- (CASE WHEN owner."announcementId" IS NOT NULL THEN 1 ELSE 0 END) +
52
- (CASE WHEN owner."studentQuestionProgressId" IS NOT NULL THEN 1 ELSE 0 END)
53
- ) = 1;
54
-
55
- ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_single_owner_check" CHECK (
56
- (CASE WHEN "assignmentId" IS NOT NULL THEN 1 ELSE 0 END) +
57
- (CASE WHEN "submissionId" IS NOT NULL THEN 1 ELSE 0 END) +
58
- (CASE WHEN "announcementId" IS NOT NULL THEN 1 ELSE 0 END) +
59
- (CASE WHEN "studentQuestionProgressId" IS NOT NULL THEN 1 ELSE 0 END) = 1
60
- );
@@ -1,81 +0,0 @@
1
- -- Add durable multi-school membership and invite support.
2
-
3
- CREATE TYPE "SchoolMembershipRole" AS ENUM ('ADMIN', 'TEACHER', 'STUDENT');
4
- CREATE TYPE "SchoolMembershipStatus" AS ENUM ('ACTIVE', 'INVITED', 'SUSPENDED');
5
- CREATE TYPE "SchoolInviteStatus" AS ENUM ('PENDING', 'ACCEPTED', 'REVOKED', 'EXPIRED');
6
-
7
- ALTER TABLE "School"
8
- ALTER COLUMN "logoId" DROP NOT NULL,
9
- ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
10
- ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
11
-
12
- CREATE TABLE "SchoolMembership" (
13
- "id" TEXT NOT NULL,
14
- "schoolId" TEXT NOT NULL,
15
- "userId" TEXT NOT NULL,
16
- "role" "SchoolMembershipRole" NOT NULL,
17
- "status" "SchoolMembershipStatus" NOT NULL DEFAULT 'ACTIVE',
18
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
19
- "updatedAt" TIMESTAMP(3) NOT NULL,
20
-
21
- CONSTRAINT "SchoolMembership_pkey" PRIMARY KEY ("id")
22
- );
23
-
24
- CREATE TABLE "SchoolInvite" (
25
- "id" TEXT NOT NULL,
26
- "token" TEXT NOT NULL,
27
- "email" TEXT NOT NULL,
28
- "role" "SchoolMembershipRole" NOT NULL,
29
- "status" "SchoolInviteStatus" NOT NULL DEFAULT 'PENDING',
30
- "expiresAt" TIMESTAMP(3) NOT NULL,
31
- "acceptedAt" TIMESTAMP(3),
32
- "revokedAt" TIMESTAMP(3),
33
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
34
- "updatedAt" TIMESTAMP(3) NOT NULL,
35
- "schoolId" TEXT NOT NULL,
36
- "invitedById" TEXT NOT NULL,
37
-
38
- CONSTRAINT "SchoolInvite_pkey" PRIMARY KEY ("id")
39
- );
40
-
41
- INSERT INTO "SchoolMembership" ("id", "schoolId", "userId", "role", "status", "createdAt", "updatedAt")
42
- SELECT
43
- gen_random_uuid()::text,
44
- "schoolId",
45
- "id",
46
- CASE
47
- WHEN "role" = 'ADMIN' THEN 'ADMIN'::"SchoolMembershipRole"
48
- WHEN "role" = 'TEACHER' THEN 'TEACHER'::"SchoolMembershipRole"
49
- ELSE 'STUDENT'::"SchoolMembershipRole"
50
- END,
51
- 'ACTIVE'::"SchoolMembershipStatus",
52
- CURRENT_TIMESTAMP,
53
- CURRENT_TIMESTAMP
54
- FROM "User"
55
- WHERE "schoolId" IS NOT NULL
56
- ON CONFLICT DO NOTHING;
57
-
58
- CREATE UNIQUE INDEX "SchoolMembership_schoolId_userId_key" ON "SchoolMembership"("schoolId", "userId");
59
- CREATE INDEX "SchoolMembership_userId_idx" ON "SchoolMembership"("userId");
60
- CREATE INDEX "SchoolMembership_schoolId_role_idx" ON "SchoolMembership"("schoolId", "role");
61
- CREATE INDEX "SchoolMembership_schoolId_status_idx" ON "SchoolMembership"("schoolId", "status");
62
-
63
- CREATE UNIQUE INDEX "SchoolInvite_token_key" ON "SchoolInvite"("token");
64
- CREATE INDEX "SchoolInvite_schoolId_status_idx" ON "SchoolInvite"("schoolId", "status");
65
- CREATE INDEX "SchoolInvite_email_idx" ON "SchoolInvite"("email");
66
-
67
- ALTER TABLE "SchoolMembership"
68
- ADD CONSTRAINT "SchoolMembership_schoolId_fkey"
69
- FOREIGN KEY ("schoolId") REFERENCES "School"("id") ON DELETE CASCADE ON UPDATE CASCADE;
70
-
71
- ALTER TABLE "SchoolMembership"
72
- ADD CONSTRAINT "SchoolMembership_userId_fkey"
73
- FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
74
-
75
- ALTER TABLE "SchoolInvite"
76
- ADD CONSTRAINT "SchoolInvite_schoolId_fkey"
77
- FOREIGN KEY ("schoolId") REFERENCES "School"("id") ON DELETE CASCADE ON UPDATE CASCADE;
78
-
79
- ALTER TABLE "SchoolInvite"
80
- ADD CONSTRAINT "SchoolInvite_invitedById_fkey"
81
- FOREIGN KEY ("invitedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -1,166 +0,0 @@
1
- -- Consolidate background-job tracking onto RunJob and unify domain status.
2
- --
3
- -- 1. Replace the bare-bones RunJob table with a fully-typed audit row that
4
- -- carries job type, status, input/result, error, attempts, timestamps.
5
- -- 2. Replace the catch-all GenerationStatus enum with a single shared
6
- -- JobStatus enum used by every domain row that has a user-observable
7
- -- async lifecycle (Message, StudentQuestionProgress).
8
- -- 3. Add a nullable runJobId FK on Message and StudentQuestionProgress so we
9
- -- can trace a domain row back to the job that produced it. Operational
10
- -- state (retries, errors, attempts) lives on RunJob, not on the row.
11
- -- 4. Drop the unused Comment.status column.
12
-
13
- -- ---------------------------------------------------------------------------
14
- -- 1. New enum types
15
- -- ---------------------------------------------------------------------------
16
-
17
- CREATE TYPE "RunJobType" AS ENUM (
18
- 'PDF_TO_WORKSHEET',
19
- 'GRADE_WORKSHEET',
20
- 'AI_LAB_CHAT',
21
- 'AI_NEWTON_CHAT',
22
- 'STUDENT_PROGRESS_CHAT'
23
- );
24
-
25
- -- Queue-internal lifecycle. Distinct from JobStatus because PENDING (queued
26
- -- but not picked up) vs RUNNING (worker actively executing) is a real
27
- -- operational distinction we want when debugging.
28
- CREATE TYPE "RunJobStatus" AS ENUM (
29
- 'PENDING',
30
- 'RUNNING',
31
- 'SUCCEEDED',
32
- 'FAILED',
33
- 'CANCELLED'
34
- );
35
-
36
- -- Shared UI-shaped status for domain rows. Not every row uses every value
37
- -- (e.g. Message never gets NOT_STARTED) but we keep one enum to avoid an
38
- -- explosion of near-duplicate types.
39
- CREATE TYPE "JobStatus" AS ENUM (
40
- 'NOT_STARTED',
41
- 'PENDING',
42
- 'COMPLETED',
43
- 'FAILED',
44
- 'CANCELLED'
45
- );
46
-
47
- -- ---------------------------------------------------------------------------
48
- -- 2. Replace the legacy RunJob table.
49
- --
50
- -- The previous schema only had `id` and `createdAt`, and was applied via
51
- -- `prisma db push` (no migration history) — so any rows in it are throwaway.
52
- -- We DROP IF EXISTS to handle both fresh production DBs and dev DBs that have
53
- -- the old shape.
54
- -- ---------------------------------------------------------------------------
55
-
56
- DROP TABLE IF EXISTS "RunJob" CASCADE;
57
-
58
- CREATE TABLE "RunJob" (
59
- "id" TEXT NOT NULL,
60
- "type" "RunJobType" NOT NULL,
61
- "status" "RunJobStatus" NOT NULL DEFAULT 'PENDING',
62
- "classId" TEXT,
63
- "userId" TEXT,
64
- "bullJobId" TEXT,
65
- "input" JSONB NOT NULL,
66
- "result" JSONB,
67
- "error" TEXT,
68
- "attempts" INTEGER NOT NULL DEFAULT 0,
69
- "startedAt" TIMESTAMP(3),
70
- "finishedAt" TIMESTAMP(3),
71
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
72
- "updatedAt" TIMESTAMP(3) NOT NULL,
73
-
74
- CONSTRAINT "RunJob_pkey" PRIMARY KEY ("id")
75
- );
76
-
77
- CREATE INDEX "RunJob_userId_type_status_idx" ON "RunJob"("userId", "type", "status");
78
- CREATE INDEX "RunJob_classId_status_idx" ON "RunJob"("classId", "status");
79
- CREATE INDEX "RunJob_status_createdAt_idx" ON "RunJob"("status", "createdAt");
80
-
81
- -- ---------------------------------------------------------------------------
82
- -- 2b. Track PDF source URLs on worksheets for idempotent PDF conversion.
83
- -- ---------------------------------------------------------------------------
84
-
85
- ALTER TABLE "Worksheet" ADD COLUMN "sourceUrl" TEXT;
86
-
87
- CREATE UNIQUE INDEX "Worksheet_classId_sourceUrl_key"
88
- ON "Worksheet"("classId", "sourceUrl");
89
-
90
- -- ---------------------------------------------------------------------------
91
- -- 3. Message.status: GenerationStatus -> JobStatus.
92
- --
93
- -- Old enum had NOT_STARTED / PENDING / GENERATING / COMPLETED / FAILED /
94
- -- CANCELLED. New JobStatus drops GENERATING (never written). The old default
95
- -- of NOT_STARTED is dropped: a row without an AI lifecycle now has NULL.
96
- -- GENERATING is mapped to PENDING defensively in case any row carries it.
97
- -- ---------------------------------------------------------------------------
98
-
99
- ALTER TABLE "Message" ALTER COLUMN "status" DROP DEFAULT;
100
-
101
- ALTER TABLE "Message"
102
- ALTER COLUMN "status" TYPE "JobStatus"
103
- USING (
104
- CASE "status"::text
105
- WHEN 'NOT_STARTED' THEN NULL
106
- WHEN 'GENERATING' THEN 'PENDING'::"JobStatus"
107
- WHEN 'PENDING' THEN 'PENDING'::"JobStatus"
108
- WHEN 'COMPLETED' THEN 'COMPLETED'::"JobStatus"
109
- WHEN 'FAILED' THEN 'FAILED'::"JobStatus"
110
- WHEN 'CANCELLED' THEN 'CANCELLED'::"JobStatus"
111
- ELSE NULL
112
- END
113
- );
114
-
115
- -- ---------------------------------------------------------------------------
116
- -- 4. StudentQuestionProgress.status: GenerationStatus -> JobStatus.
117
- --
118
- -- Default kept at NOT_STARTED. GENERATING -> PENDING defensively.
119
- -- ---------------------------------------------------------------------------
120
-
121
- ALTER TABLE "StudentQuestionProgress" ALTER COLUMN "status" DROP DEFAULT;
122
-
123
- ALTER TABLE "StudentQuestionProgress"
124
- ALTER COLUMN "status" TYPE "JobStatus"
125
- USING (
126
- CASE "status"::text
127
- WHEN 'NOT_STARTED' THEN 'NOT_STARTED'::"JobStatus"
128
- WHEN 'PENDING' THEN 'PENDING'::"JobStatus"
129
- WHEN 'GENERATING' THEN 'PENDING'::"JobStatus"
130
- WHEN 'COMPLETED' THEN 'COMPLETED'::"JobStatus"
131
- WHEN 'FAILED' THEN 'FAILED'::"JobStatus"
132
- WHEN 'CANCELLED' THEN 'CANCELLED'::"JobStatus"
133
- ELSE NULL
134
- END
135
- );
136
-
137
- ALTER TABLE "StudentQuestionProgress"
138
- ALTER COLUMN "status" SET DEFAULT 'NOT_STARTED';
139
-
140
- -- ---------------------------------------------------------------------------
141
- -- 5. Drop the unused Comment.status column and the legacy enum.
142
- -- ---------------------------------------------------------------------------
143
-
144
- ALTER TABLE "Comment" DROP COLUMN "status";
145
-
146
- DROP TYPE "GenerationStatus";
147
-
148
- -- ---------------------------------------------------------------------------
149
- -- 6. Add runJobId FKs and supporting indexes.
150
- -- ---------------------------------------------------------------------------
151
-
152
- ALTER TABLE "Message"
153
- ADD COLUMN "runJobId" TEXT,
154
- ADD CONSTRAINT "Message_runJobId_fkey"
155
- FOREIGN KEY ("runJobId") REFERENCES "RunJob"("id")
156
- ON DELETE SET NULL ON UPDATE CASCADE;
157
-
158
- CREATE INDEX "Message_runJobId_idx" ON "Message"("runJobId");
159
-
160
- ALTER TABLE "StudentQuestionProgress"
161
- ADD COLUMN "runJobId" TEXT,
162
- ADD CONSTRAINT "StudentQuestionProgress_runJobId_fkey"
163
- FOREIGN KEY ("runJobId") REFERENCES "RunJob"("id")
164
- ON DELETE SET NULL ON UPDATE CASCADE;
165
-
166
- CREATE INDEX "StudentQuestionProgress_runJobId_idx" ON "StudentQuestionProgress"("runJobId");
@@ -1,184 +0,0 @@
1
- -- Institution overhaul: departments, tags, cloud storage, class affiliation,
2
- -- and template grading artefacts.
3
-
4
- CREATE TYPE "TagTarget" AS ENUM ('USER', 'CLASS', 'RUBRIC', 'BOUNDARY');
5
- CREATE TYPE "FolderScope" AS ENUM ('CLASS', 'SCHOOL_STORAGE', 'PERSONAL', 'GENERIC');
6
-
7
- -- School: optional description.
8
- ALTER TABLE "School"
9
- ADD COLUMN "description" TEXT;
10
-
11
- -- Folder: extend with scope + alternate root owners (school, personal user).
12
- ALTER TABLE "Folder"
13
- ADD COLUMN "scope" "FolderScope" NOT NULL DEFAULT 'GENERIC',
14
- ADD COLUMN "schoolStorageId" TEXT,
15
- ADD COLUMN "personalOwnerId" TEXT;
16
-
17
- -- Backfill existing class root folders to CLASS scope so the data layer can
18
- -- distinguish roots from generic subfolders.
19
- UPDATE "Folder"
20
- SET "scope" = 'CLASS'
21
- WHERE "classId" IS NOT NULL AND "parentFolderId" IS NULL;
22
-
23
- CREATE UNIQUE INDEX "Folder_schoolStorageId_key" ON "Folder"("schoolStorageId");
24
- CREATE UNIQUE INDEX "Folder_personalOwnerId_key" ON "Folder"("personalOwnerId");
25
-
26
- ALTER TABLE "Folder"
27
- ADD CONSTRAINT "Folder_schoolStorageId_fkey"
28
- FOREIGN KEY ("schoolStorageId") REFERENCES "School"("id")
29
- ON DELETE SET NULL ON UPDATE CASCADE,
30
- ADD CONSTRAINT "Folder_personalOwnerId_fkey"
31
- FOREIGN KEY ("personalOwnerId") REFERENCES "User"("id")
32
- ON DELETE CASCADE ON UPDATE CASCADE;
33
-
34
- -- Department.
35
- CREATE TABLE "Department" (
36
- "id" TEXT NOT NULL,
37
- "schoolId" TEXT NOT NULL,
38
- "name" TEXT NOT NULL,
39
- "description" TEXT,
40
- "color" TEXT DEFAULT '#3B82F6',
41
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
42
- "updatedAt" TIMESTAMP(3) NOT NULL,
43
-
44
- CONSTRAINT "Department_pkey" PRIMARY KEY ("id")
45
- );
46
-
47
- CREATE UNIQUE INDEX "Department_schoolId_name_key" ON "Department"("schoolId", "name");
48
- CREATE INDEX "Department_schoolId_idx" ON "Department"("schoolId");
49
-
50
- ALTER TABLE "Department"
51
- ADD CONSTRAINT "Department_schoolId_fkey"
52
- FOREIGN KEY ("schoolId") REFERENCES "School"("id")
53
- ON DELETE CASCADE ON UPDATE CASCADE;
54
-
55
- -- User <-> Department (M:N).
56
- CREATE TABLE "_UserDepartments" (
57
- "A" TEXT NOT NULL,
58
- "B" TEXT NOT NULL
59
- );
60
- CREATE UNIQUE INDEX "_UserDepartments_AB_unique" ON "_UserDepartments"("A", "B");
61
- CREATE INDEX "_UserDepartments_B_index" ON "_UserDepartments"("B");
62
- ALTER TABLE "_UserDepartments"
63
- ADD CONSTRAINT "_UserDepartments_A_fkey"
64
- FOREIGN KEY ("A") REFERENCES "Department"("id") ON DELETE CASCADE ON UPDATE CASCADE,
65
- ADD CONSTRAINT "_UserDepartments_B_fkey"
66
- FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
67
-
68
- -- Tag.
69
- CREATE TABLE "Tag" (
70
- "id" TEXT NOT NULL,
71
- "schoolId" TEXT NOT NULL,
72
- "departmentId" TEXT,
73
- "name" TEXT NOT NULL,
74
- "color" TEXT NOT NULL DEFAULT '#3B82F6',
75
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
76
- "updatedAt" TIMESTAMP(3) NOT NULL,
77
-
78
- CONSTRAINT "Tag_pkey" PRIMARY KEY ("id")
79
- );
80
-
81
- CREATE UNIQUE INDEX "Tag_schoolId_name_key" ON "Tag"("schoolId", "name");
82
- CREATE INDEX "Tag_schoolId_idx" ON "Tag"("schoolId");
83
- CREATE INDEX "Tag_departmentId_idx" ON "Tag"("departmentId");
84
-
85
- ALTER TABLE "Tag"
86
- ADD CONSTRAINT "Tag_schoolId_fkey"
87
- FOREIGN KEY ("schoolId") REFERENCES "School"("id")
88
- ON DELETE CASCADE ON UPDATE CASCADE,
89
- ADD CONSTRAINT "Tag_departmentId_fkey"
90
- FOREIGN KEY ("departmentId") REFERENCES "Department"("id")
91
- ON DELETE SET NULL ON UPDATE CASCADE;
92
-
93
- -- Tag join tables.
94
- CREATE TABLE "_UserTags" (
95
- "A" TEXT NOT NULL,
96
- "B" TEXT NOT NULL
97
- );
98
- CREATE UNIQUE INDEX "_UserTags_AB_unique" ON "_UserTags"("A", "B");
99
- CREATE INDEX "_UserTags_B_index" ON "_UserTags"("B");
100
- ALTER TABLE "_UserTags"
101
- ADD CONSTRAINT "_UserTags_A_fkey" FOREIGN KEY ("A") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE,
102
- ADD CONSTRAINT "_UserTags_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
103
-
104
- CREATE TABLE "_ClassTags" (
105
- "A" TEXT NOT NULL,
106
- "B" TEXT NOT NULL
107
- );
108
- CREATE UNIQUE INDEX "_ClassTags_AB_unique" ON "_ClassTags"("A", "B");
109
- CREATE INDEX "_ClassTags_B_index" ON "_ClassTags"("B");
110
- ALTER TABLE "_ClassTags"
111
- ADD CONSTRAINT "_ClassTags_A_fkey" FOREIGN KEY ("A") REFERENCES "Class"("id") ON DELETE CASCADE ON UPDATE CASCADE,
112
- ADD CONSTRAINT "_ClassTags_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
113
-
114
- CREATE TABLE "_MarkSchemeTags" (
115
- "A" TEXT NOT NULL,
116
- "B" TEXT NOT NULL
117
- );
118
- CREATE UNIQUE INDEX "_MarkSchemeTags_AB_unique" ON "_MarkSchemeTags"("A", "B");
119
- CREATE INDEX "_MarkSchemeTags_B_index" ON "_MarkSchemeTags"("B");
120
- ALTER TABLE "_MarkSchemeTags"
121
- ADD CONSTRAINT "_MarkSchemeTags_A_fkey" FOREIGN KEY ("A") REFERENCES "MarkScheme"("id") ON DELETE CASCADE ON UPDATE CASCADE,
122
- ADD CONSTRAINT "_MarkSchemeTags_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
123
-
124
- CREATE TABLE "_GradingBoundaryTags" (
125
- "A" TEXT NOT NULL,
126
- "B" TEXT NOT NULL
127
- );
128
- CREATE UNIQUE INDEX "_GradingBoundaryTags_AB_unique" ON "_GradingBoundaryTags"("A", "B");
129
- CREATE INDEX "_GradingBoundaryTags_B_index" ON "_GradingBoundaryTags"("B");
130
- ALTER TABLE "_GradingBoundaryTags"
131
- ADD CONSTRAINT "_GradingBoundaryTags_A_fkey" FOREIGN KEY ("A") REFERENCES "GradingBoundary"("id") ON DELETE CASCADE ON UPDATE CASCADE,
132
- ADD CONSTRAINT "_GradingBoundaryTags_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
133
-
134
- -- Class: department + tags relations (tags are via _ClassTags above).
135
- ALTER TABLE "Class"
136
- ADD COLUMN "departmentId" TEXT;
137
-
138
- CREATE INDEX "Class_schoolId_idx" ON "Class"("schoolId");
139
- CREATE INDEX "Class_departmentId_idx" ON "Class"("departmentId");
140
-
141
- ALTER TABLE "Class"
142
- ADD CONSTRAINT "Class_departmentId_fkey"
143
- FOREIGN KEY ("departmentId") REFERENCES "Department"("id")
144
- ON DELETE SET NULL ON UPDATE CASCADE;
145
-
146
- -- MarkScheme: optional class, departmentId, name.
147
- ALTER TABLE "MarkScheme"
148
- DROP CONSTRAINT IF EXISTS "MarkScheme_classId_fkey";
149
-
150
- ALTER TABLE "MarkScheme"
151
- ALTER COLUMN "classId" DROP NOT NULL,
152
- ADD COLUMN "departmentId" TEXT,
153
- ADD COLUMN "name" TEXT;
154
-
155
- ALTER TABLE "MarkScheme"
156
- ADD CONSTRAINT "MarkScheme_classId_fkey"
157
- FOREIGN KEY ("classId") REFERENCES "Class"("id")
158
- ON DELETE CASCADE ON UPDATE CASCADE,
159
- ADD CONSTRAINT "MarkScheme_departmentId_fkey"
160
- FOREIGN KEY ("departmentId") REFERENCES "Department"("id")
161
- ON DELETE CASCADE ON UPDATE CASCADE;
162
-
163
- CREATE INDEX "MarkScheme_classId_idx" ON "MarkScheme"("classId");
164
- CREATE INDEX "MarkScheme_departmentId_idx" ON "MarkScheme"("departmentId");
165
-
166
- -- GradingBoundary: optional class, departmentId, name.
167
- ALTER TABLE "GradingBoundary"
168
- DROP CONSTRAINT IF EXISTS "GradingBoundary_classId_fkey";
169
-
170
- ALTER TABLE "GradingBoundary"
171
- ALTER COLUMN "classId" DROP NOT NULL,
172
- ADD COLUMN "departmentId" TEXT,
173
- ADD COLUMN "name" TEXT;
174
-
175
- ALTER TABLE "GradingBoundary"
176
- ADD CONSTRAINT "GradingBoundary_classId_fkey"
177
- FOREIGN KEY ("classId") REFERENCES "Class"("id")
178
- ON DELETE CASCADE ON UPDATE CASCADE,
179
- ADD CONSTRAINT "GradingBoundary_departmentId_fkey"
180
- FOREIGN KEY ("departmentId") REFERENCES "Department"("id")
181
- ON DELETE CASCADE ON UPDATE CASCADE;
182
-
183
- CREATE INDEX "GradingBoundary_classId_idx" ON "GradingBoundary"("classId");
184
- CREATE INDEX "GradingBoundary_departmentId_idx" ON "GradingBoundary"("departmentId");