@studious-lms/server 1.7.0 → 1.9.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 (212) hide show
  1. package/dist/middleware/security.d.ts.map +1 -1
  2. package/dist/middleware/security.js +3 -3
  3. package/dist/middleware/security.js.map +1 -1
  4. package/dist/models/access.d.ts +21 -66
  5. package/dist/models/access.d.ts.map +1 -1
  6. package/dist/models/access.js +10 -26
  7. package/dist/models/access.js.map +1 -1
  8. package/dist/models/agenda.d.ts +4 -2
  9. package/dist/models/agenda.d.ts.map +1 -1
  10. package/dist/models/announcement.d.ts +4 -3
  11. package/dist/models/announcement.d.ts.map +1 -1
  12. package/dist/models/announcement.js +2 -3
  13. package/dist/models/announcement.js.map +1 -1
  14. package/dist/models/assignment.d.ts +40 -33
  15. package/dist/models/assignment.d.ts.map +1 -1
  16. package/dist/models/auth.d.ts +2 -4
  17. package/dist/models/auth.d.ts.map +1 -1
  18. package/dist/models/auth.js +2 -3
  19. package/dist/models/auth.js.map +1 -1
  20. package/dist/models/class.d.ts +34 -6
  21. package/dist/models/class.d.ts.map +1 -1
  22. package/dist/models/class.js +15 -2
  23. package/dist/models/class.js.map +1 -1
  24. package/dist/models/cloudStorage.d.ts +153 -0
  25. package/dist/models/cloudStorage.d.ts.map +1 -0
  26. package/dist/models/cloudStorage.js +295 -0
  27. package/dist/models/cloudStorage.js.map +1 -0
  28. package/dist/models/comment.d.ts +0 -24
  29. package/dist/models/comment.d.ts.map +1 -1
  30. package/dist/models/comment.js +2 -6
  31. package/dist/models/comment.js.map +1 -1
  32. package/dist/models/conversation.d.ts +22 -22
  33. package/dist/models/department.d.ts +154 -0
  34. package/dist/models/department.d.ts.map +1 -0
  35. package/dist/models/department.js +135 -0
  36. package/dist/models/department.js.map +1 -0
  37. package/dist/models/event.d.ts +10 -4
  38. package/dist/models/event.d.ts.map +1 -1
  39. package/dist/models/event.js +2 -5
  40. package/dist/models/event.js.map +1 -1
  41. package/dist/models/file.d.ts +52 -36
  42. package/dist/models/file.d.ts.map +1 -1
  43. package/dist/models/file.js +4 -42
  44. package/dist/models/file.js.map +1 -1
  45. package/dist/models/folder.d.ts +47 -0
  46. package/dist/models/folder.d.ts.map +1 -1
  47. package/dist/models/labChat.d.ts +11 -9
  48. package/dist/models/labChat.d.ts.map +1 -1
  49. package/dist/models/message.d.ts +46 -12
  50. package/dist/models/message.d.ts.map +1 -1
  51. package/dist/models/message.js +19 -10
  52. package/dist/models/message.js.map +1 -1
  53. package/dist/models/newtonChat.d.ts +2 -1
  54. package/dist/models/newtonChat.d.ts.map +1 -1
  55. package/dist/models/school.d.ts +45 -12
  56. package/dist/models/school.d.ts.map +1 -1
  57. package/dist/models/school.js +19 -2
  58. package/dist/models/school.js.map +1 -1
  59. package/dist/models/section.d.ts +2 -1
  60. package/dist/models/section.d.ts.map +1 -1
  61. package/dist/models/tag.d.ts +117 -0
  62. package/dist/models/tag.d.ts.map +1 -0
  63. package/dist/models/tag.js +113 -0
  64. package/dist/models/tag.js.map +1 -0
  65. package/dist/models/worksheet.d.ts +3 -0
  66. package/dist/models/worksheet.d.ts.map +1 -1
  67. package/dist/pipelines/aiLabChatContract.d.ts +8 -8
  68. package/dist/routers/_app.d.ts +6704 -5222
  69. package/dist/routers/_app.d.ts.map +1 -1
  70. package/dist/routers/_app.js +8 -2
  71. package/dist/routers/_app.js.map +1 -1
  72. package/dist/routers/agenda.d.ts +4 -2
  73. package/dist/routers/agenda.d.ts.map +1 -1
  74. package/dist/routers/announcement.d.ts.map +1 -1
  75. package/dist/routers/announcement.js +3 -5
  76. package/dist/routers/announcement.js.map +1 -1
  77. package/dist/routers/assignment.d.ts +49 -40
  78. package/dist/routers/assignment.d.ts.map +1 -1
  79. package/dist/routers/assignment.js +2 -3
  80. package/dist/routers/assignment.js.map +1 -1
  81. package/dist/routers/class.d.ts +92 -19
  82. package/dist/routers/class.d.ts.map +1 -1
  83. package/dist/routers/class.js +5 -2
  84. package/dist/routers/class.js.map +1 -1
  85. package/dist/routers/conversation.d.ts +5 -5
  86. package/dist/routers/department.d.ts +293 -0
  87. package/dist/routers/department.d.ts.map +1 -0
  88. package/dist/routers/department.js +93 -0
  89. package/dist/routers/department.js.map +1 -0
  90. package/dist/routers/event.d.ts +4 -3
  91. package/dist/routers/event.d.ts.map +1 -1
  92. package/dist/routers/file.d.ts +10 -8
  93. package/dist/routers/file.d.ts.map +1 -1
  94. package/dist/routers/file.js +26 -17
  95. package/dist/routers/file.js.map +1 -1
  96. package/dist/routers/folder.d.ts +163 -186
  97. package/dist/routers/folder.d.ts.map +1 -1
  98. package/dist/routers/folder.js +102 -88
  99. package/dist/routers/folder.js.map +1 -1
  100. package/dist/routers/labChat.d.ts +13 -4
  101. package/dist/routers/labChat.d.ts.map +1 -1
  102. package/dist/routers/message.d.ts +20 -2
  103. package/dist/routers/message.d.ts.map +1 -1
  104. package/dist/routers/newtonChat.d.ts +10 -1
  105. package/dist/routers/newtonChat.d.ts.map +1 -1
  106. package/dist/routers/permissions.d.ts +120 -0
  107. package/dist/routers/permissions.d.ts.map +1 -0
  108. package/dist/routers/permissions.js +50 -0
  109. package/dist/routers/permissions.js.map +1 -0
  110. package/dist/routers/school.d.ts +160 -17
  111. package/dist/routers/school.d.ts.map +1 -1
  112. package/dist/routers/school.js +46 -3
  113. package/dist/routers/school.js.map +1 -1
  114. package/dist/routers/tag.d.ts +119 -0
  115. package/dist/routers/tag.d.ts.map +1 -0
  116. package/dist/routers/tag.js +52 -0
  117. package/dist/routers/tag.js.map +1 -0
  118. package/dist/routers/worksheet.d.ts +1 -0
  119. package/dist/routers/worksheet.d.ts.map +1 -1
  120. package/dist/seedDatabase.d.ts +0 -1
  121. package/dist/seedDatabase.d.ts.map +1 -1
  122. package/dist/services/agenda.d.ts +4 -2
  123. package/dist/services/agenda.d.ts.map +1 -1
  124. package/dist/services/assignment.d.ts +49 -40
  125. package/dist/services/assignment.d.ts.map +1 -1
  126. package/dist/services/class.d.ts +92 -19
  127. package/dist/services/class.d.ts.map +1 -1
  128. package/dist/services/class.js +92 -5
  129. package/dist/services/class.js.map +1 -1
  130. package/dist/services/conversation.d.ts +5 -5
  131. package/dist/services/department.d.ts +200 -0
  132. package/dist/services/department.d.ts.map +1 -0
  133. package/dist/services/department.js +368 -0
  134. package/dist/services/department.js.map +1 -0
  135. package/dist/services/event.d.ts +4 -3
  136. package/dist/services/event.d.ts.map +1 -1
  137. package/dist/services/file.d.ts +105 -3
  138. package/dist/services/file.d.ts.map +1 -1
  139. package/dist/services/file.js +167 -41
  140. package/dist/services/file.js.map +1 -1
  141. package/dist/services/folder.d.ts +220 -149
  142. package/dist/services/folder.d.ts.map +1 -1
  143. package/dist/services/folder.js +326 -196
  144. package/dist/services/folder.js.map +1 -1
  145. package/dist/services/labChat.d.ts +13 -4
  146. package/dist/services/labChat.d.ts.map +1 -1
  147. package/dist/services/labChat.js +4 -3
  148. package/dist/services/labChat.js.map +1 -1
  149. package/dist/services/message.d.ts +20 -2
  150. package/dist/services/message.d.ts.map +1 -1
  151. package/dist/services/message.js +7 -23
  152. package/dist/services/message.js.map +1 -1
  153. package/dist/services/newtonChat.d.ts +9 -0
  154. package/dist/services/newtonChat.d.ts.map +1 -1
  155. package/dist/services/newtonChat.js +4 -3
  156. package/dist/services/newtonChat.js.map +1 -1
  157. package/dist/services/permissions.d.ts +188 -0
  158. package/dist/services/permissions.d.ts.map +1 -0
  159. package/dist/services/permissions.js +661 -0
  160. package/dist/services/permissions.js.map +1 -0
  161. package/dist/services/school.d.ts +142 -15
  162. package/dist/services/school.d.ts.map +1 -1
  163. package/dist/services/school.js +308 -54
  164. package/dist/services/school.js.map +1 -1
  165. package/dist/services/tag.d.ts +71 -0
  166. package/dist/services/tag.d.ts.map +1 -0
  167. package/dist/services/tag.js +178 -0
  168. package/dist/services/tag.js.map +1 -0
  169. package/dist/services/worksheet.d.ts +1 -0
  170. package/dist/services/worksheet.d.ts.map +1 -1
  171. package/dist/utils/aiUser.d.ts.map +1 -1
  172. package/dist/utils/aiUser.js +2 -3
  173. package/dist/utils/aiUser.js.map +1 -1
  174. package/package.json +1 -1
  175. package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +184 -0
  176. package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +93 -0
  177. package/prisma/schema.prisma +193 -35
  178. package/src/middleware/security.ts +1 -1
  179. package/src/models/access.ts +8 -24
  180. package/src/models/announcement.ts +0 -1
  181. package/src/models/auth.ts +0 -1
  182. package/src/models/class.ts +13 -0
  183. package/src/models/cloudStorage.ts +327 -0
  184. package/src/models/comment.ts +0 -4
  185. package/src/models/department.ts +159 -0
  186. package/src/models/event.ts +0 -3
  187. package/src/models/file.ts +2 -40
  188. package/src/models/message.ts +19 -5
  189. package/src/models/school.ts +26 -0
  190. package/src/models/tag.ts +140 -0
  191. package/src/routers/_app.ts +6 -0
  192. package/src/routers/announcement.ts +1 -3
  193. package/src/routers/assignment.ts +0 -1
  194. package/src/routers/class.ts +3 -0
  195. package/src/routers/department.ts +174 -0
  196. package/src/routers/file.ts +29 -26
  197. package/src/routers/folder.ts +127 -118
  198. package/src/routers/permissions.ts +71 -0
  199. package/src/routers/school.ts +83 -0
  200. package/src/routers/tag.ts +78 -0
  201. package/src/services/class.ts +109 -4
  202. package/src/services/department.ts +478 -0
  203. package/src/services/file.ts +172 -43
  204. package/src/services/folder.ts +399 -237
  205. package/src/services/labChat.ts +2 -1
  206. package/src/services/message.ts +5 -21
  207. package/src/services/newtonChat.ts +2 -1
  208. package/src/services/permissions.ts +778 -0
  209. package/src/services/school.ts +369 -57
  210. package/src/services/tag.ts +229 -0
  211. package/src/utils/aiUser.ts +0 -1
  212. package/tests/unit/services/permissions.test.ts +463 -0
@@ -20,8 +20,8 @@ export declare function listConversations(userId: string): Promise<{
20
20
  };
21
21
  } & {
22
22
  id: string;
23
- role: import(".prisma/client").$Enums.ConversationRole;
24
23
  userId: string;
24
+ role: import(".prisma/client").$Enums.ConversationRole;
25
25
  conversationId: string;
26
26
  joinedAt: Date;
27
27
  hiddenAt: Date | null;
@@ -81,8 +81,8 @@ export declare function createConversationRecord(userId: string, type: "DM" | "G
81
81
  };
82
82
  } & {
83
83
  id: string;
84
- role: import(".prisma/client").$Enums.ConversationRole;
85
84
  userId: string;
85
+ role: import(".prisma/client").$Enums.ConversationRole;
86
86
  conversationId: string;
87
87
  joinedAt: Date;
88
88
  hiddenAt: Date | null;
@@ -109,8 +109,8 @@ export declare function getConversation(userId: string, conversationId: string):
109
109
  };
110
110
  } & {
111
111
  id: string;
112
- role: import(".prisma/client").$Enums.ConversationRole;
113
112
  userId: string;
113
+ role: import(".prisma/client").$Enums.ConversationRole;
114
114
  conversationId: string;
115
115
  joinedAt: Date;
116
116
  hiddenAt: Date | null;
@@ -137,8 +137,8 @@ export declare function addMemberToConversation(userId: string, conversationId:
137
137
  };
138
138
  } & {
139
139
  id: string;
140
- role: import(".prisma/client").$Enums.ConversationRole;
141
140
  userId: string;
141
+ role: import(".prisma/client").$Enums.ConversationRole;
142
142
  conversationId: string;
143
143
  joinedAt: Date;
144
144
  hiddenAt: Date | null;
@@ -165,8 +165,8 @@ export declare function removeMemberFromConversation(userId: string, conversatio
165
165
  };
166
166
  } & {
167
167
  id: string;
168
- role: import(".prisma/client").$Enums.ConversationRole;
169
168
  userId: string;
169
+ role: import(".prisma/client").$Enums.ConversationRole;
170
170
  conversationId: string;
171
171
  joinedAt: Date;
172
172
  hiddenAt: Date | null;
@@ -0,0 +1,200 @@
1
+ export declare function listDepartments(userId: string, schoolId: string): Promise<{
2
+ name: string;
3
+ id: string;
4
+ description: string | null;
5
+ createdAt: Date;
6
+ updatedAt: Date;
7
+ schoolId: string;
8
+ color: string | null;
9
+ _count: {
10
+ tags: number;
11
+ classes: number;
12
+ members: number;
13
+ rubricTemplates: number;
14
+ boundaryTemplates: number;
15
+ };
16
+ }[]>;
17
+ export declare function listMyDepartments(userId: string, schoolId: string): Promise<{
18
+ name: string;
19
+ id: string;
20
+ description: string | null;
21
+ createdAt: Date;
22
+ updatedAt: Date;
23
+ schoolId: string;
24
+ color: string | null;
25
+ }[]>;
26
+ export declare function getDepartmentDetails(userId: string, departmentId: string): Promise<{
27
+ name: string;
28
+ id: string;
29
+ description: string | null;
30
+ createdAt: Date;
31
+ updatedAt: Date;
32
+ schoolId: string;
33
+ color: string | null;
34
+ tags: {
35
+ name: string;
36
+ id: string;
37
+ color: string;
38
+ }[];
39
+ classes: {
40
+ name: string;
41
+ id: string;
42
+ subject: string;
43
+ color: string | null;
44
+ section: string;
45
+ }[];
46
+ members: {
47
+ id: string;
48
+ username: string;
49
+ email: string;
50
+ profile: {
51
+ displayName: string | null;
52
+ profilePicture: string | null;
53
+ profilePictureThumbnail: string | null;
54
+ } | null;
55
+ }[];
56
+ rubricTemplates: {
57
+ name: string | null;
58
+ id: string;
59
+ structured: string;
60
+ }[];
61
+ boundaryTemplates: {
62
+ name: string | null;
63
+ id: string;
64
+ structured: string;
65
+ }[];
66
+ }>;
67
+ export declare function createDepartmentRecord(userId: string, input: {
68
+ schoolId: string;
69
+ name: string;
70
+ description?: string;
71
+ color?: string;
72
+ }): Promise<{
73
+ name: string;
74
+ id: string;
75
+ description: string | null;
76
+ createdAt: Date;
77
+ updatedAt: Date;
78
+ schoolId: string;
79
+ color: string | null;
80
+ }>;
81
+ export declare function updateDepartmentRecord(userId: string, input: {
82
+ departmentId: string;
83
+ name?: string;
84
+ description?: string | null;
85
+ color?: string;
86
+ }): Promise<{
87
+ name: string;
88
+ id: string;
89
+ description: string | null;
90
+ createdAt: Date;
91
+ updatedAt: Date;
92
+ schoolId: string;
93
+ color: string | null;
94
+ }>;
95
+ export declare function deleteDepartmentRecord(userId: string, departmentId: string): Promise<{
96
+ success: boolean;
97
+ }>;
98
+ export declare function addMembersToDepartment(userId: string, input: {
99
+ departmentId: string;
100
+ userIds: string[];
101
+ }): Promise<{
102
+ id: string;
103
+ }>;
104
+ export declare function removeMemberFromDepartment(userId: string, input: {
105
+ departmentId: string;
106
+ memberId: string;
107
+ }): Promise<{
108
+ id: string;
109
+ }>;
110
+ /** Department template authoring (rubrics + boundaries). */
111
+ export declare function createRubricTemplate(userId: string, input: {
112
+ departmentId: string;
113
+ name: string;
114
+ structured: string;
115
+ }): Promise<{
116
+ name: string | null;
117
+ id: string;
118
+ departmentId: string | null;
119
+ structured: string;
120
+ }>;
121
+ export declare function updateRubricTemplate(userId: string, input: {
122
+ templateId: string;
123
+ name?: string;
124
+ structured?: string;
125
+ }): Promise<{
126
+ name: string | null;
127
+ id: string;
128
+ departmentId: string | null;
129
+ classId: string | null;
130
+ structured: string;
131
+ }>;
132
+ export declare function deleteRubricTemplate(userId: string, templateId: string): Promise<{
133
+ name: string | null;
134
+ id: string;
135
+ departmentId: string | null;
136
+ classId: string | null;
137
+ structured: string;
138
+ }>;
139
+ export declare function createBoundaryTemplate(userId: string, input: {
140
+ departmentId: string;
141
+ name: string;
142
+ structured: string;
143
+ }): Promise<{
144
+ name: string | null;
145
+ id: string;
146
+ departmentId: string | null;
147
+ structured: string;
148
+ }>;
149
+ export declare function updateBoundaryTemplate(userId: string, input: {
150
+ templateId: string;
151
+ name?: string;
152
+ structured?: string;
153
+ }): Promise<{
154
+ name: string | null;
155
+ id: string;
156
+ departmentId: string | null;
157
+ classId: string | null;
158
+ structured: string;
159
+ }>;
160
+ export declare function deleteBoundaryTemplate(userId: string, templateId: string): Promise<{
161
+ name: string | null;
162
+ id: string;
163
+ departmentId: string | null;
164
+ classId: string | null;
165
+ structured: string;
166
+ }>;
167
+ /**
168
+ * Apply a department template to a class by *copying* the structured payload
169
+ * into a class-scoped record. Teacher-only (the class teacher).
170
+ */
171
+ export declare function applyRubricTemplate(userId: string, input: {
172
+ classId: string;
173
+ templateId: string;
174
+ }): Promise<{
175
+ name: string | null;
176
+ id: string;
177
+ departmentId: string | null;
178
+ classId: string | null;
179
+ structured: string;
180
+ }>;
181
+ export declare function applyBoundaryTemplate(userId: string, input: {
182
+ classId: string;
183
+ templateId: string;
184
+ }): Promise<{
185
+ name: string | null;
186
+ id: string;
187
+ departmentId: string | null;
188
+ classId: string | null;
189
+ structured: string;
190
+ }>;
191
+ /** Helper used by the auto-tag flow on class creation. */
192
+ export declare function setClassDepartment(userId: string, input: {
193
+ classId: string;
194
+ departmentId: string | null;
195
+ }): Promise<{
196
+ id: string;
197
+ departmentId: string | null;
198
+ }>;
199
+ export declare function checkDepartmentMember(userId: string, departmentId: string): Promise<boolean>;
200
+ //# sourceMappingURL=department.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"department.d.ts","sourceRoot":"/","sources":["services/department.ts"],"names":[],"mappings":"AA0CA,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;KAIjB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM;;;;;;;;KAIjB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAWrB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;GAIF;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;GAeF;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM;;GAYrB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE;;GA8BnD;AAED,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE;;GAWlD;AAED,4DAA4D;AAC5D,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;;;;;GAkBlE;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;;;;;;GAsBF;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM;;;;;;GAcnB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;;;;;GAkBlE;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;;;;;;GAsBF;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM;;;;;;GAcnB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;;;;;;GAkD/C;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;;;;;;GAkD/C;AAED,0DAA0D;AAC1D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;;;GAuCxD;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,oBAGrB"}
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Department service — admin CRUD, members, and template management for
3
+ * department-level rubrics and grading boundaries.
4
+ */
5
+
6
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a61f9d68-eb30-571c-908d-8c1fb445f85c")}catch(e){}}();
7
+ import { TRPCError } from "@trpc/server";
8
+ import { prisma } from "../lib/prisma.js";
9
+ import { addDepartmentMembers, createDepartment, deleteDepartment, findDepartmentMembership, getDepartment, listDepartmentsForSchool, listDepartmentsForUser, removeDepartmentMember, updateDepartment, } from "../models/department.js";
10
+ import { findActiveSchoolAdminMembership, findSchoolMembership, } from "../models/school.js";
11
+ async function requireAdmin(schoolId, userId) {
12
+ const membership = await findActiveSchoolAdminMembership(schoolId, userId);
13
+ if (!membership) {
14
+ throw new TRPCError({
15
+ code: "FORBIDDEN",
16
+ message: "Only school admins can manage departments",
17
+ });
18
+ }
19
+ }
20
+ async function requireMember(schoolId, userId) {
21
+ const membership = await findSchoolMembership(schoolId, userId);
22
+ if (!membership || membership.status !== "ACTIVE") {
23
+ throw new TRPCError({
24
+ code: "FORBIDDEN",
25
+ message: "You aren't a member of this institution",
26
+ });
27
+ }
28
+ }
29
+ export async function listDepartments(userId, schoolId) {
30
+ await requireMember(schoolId, userId);
31
+ return listDepartmentsForSchool(schoolId);
32
+ }
33
+ export async function listMyDepartments(userId, schoolId) {
34
+ await requireMember(schoolId, userId);
35
+ return listDepartmentsForUser(userId, schoolId);
36
+ }
37
+ export async function getDepartmentDetails(userId, departmentId) {
38
+ const department = await getDepartment(departmentId);
39
+ if (!department) {
40
+ throw new TRPCError({
41
+ code: "NOT_FOUND",
42
+ message: "Department not found",
43
+ });
44
+ }
45
+ await requireMember(department.schoolId, userId);
46
+ return department;
47
+ }
48
+ export async function createDepartmentRecord(userId, input) {
49
+ await requireAdmin(input.schoolId, userId);
50
+ return createDepartment(input);
51
+ }
52
+ export async function updateDepartmentRecord(userId, input) {
53
+ const department = await getDepartment(input.departmentId);
54
+ if (!department) {
55
+ throw new TRPCError({
56
+ code: "NOT_FOUND",
57
+ message: "Department not found",
58
+ });
59
+ }
60
+ await requireAdmin(department.schoolId, userId);
61
+ return updateDepartment(input.departmentId, {
62
+ name: input.name,
63
+ description: input.description,
64
+ color: input.color,
65
+ });
66
+ }
67
+ export async function deleteDepartmentRecord(userId, departmentId) {
68
+ const department = await getDepartment(departmentId);
69
+ if (!department) {
70
+ throw new TRPCError({
71
+ code: "NOT_FOUND",
72
+ message: "Department not found",
73
+ });
74
+ }
75
+ await requireAdmin(department.schoolId, userId);
76
+ await deleteDepartment(departmentId);
77
+ return { success: true };
78
+ }
79
+ export async function addMembersToDepartment(userId, input) {
80
+ const department = await getDepartment(input.departmentId);
81
+ if (!department) {
82
+ throw new TRPCError({
83
+ code: "NOT_FOUND",
84
+ message: "Department not found",
85
+ });
86
+ }
87
+ await requireAdmin(department.schoolId, userId);
88
+ // Members must already be in the institution.
89
+ const memberships = await prisma.schoolMembership.findMany({
90
+ where: {
91
+ schoolId: department.schoolId,
92
+ userId: { in: input.userIds },
93
+ status: "ACTIVE",
94
+ },
95
+ select: { userId: true },
96
+ });
97
+ const validIds = new Set(memberships.map((m) => m.userId));
98
+ const validUserIds = input.userIds.filter((id) => validIds.has(id));
99
+ if (validUserIds.length === 0) {
100
+ throw new TRPCError({
101
+ code: "BAD_REQUEST",
102
+ message: "None of the supplied users are institution members",
103
+ });
104
+ }
105
+ return addDepartmentMembers(input.departmentId, validUserIds);
106
+ }
107
+ export async function removeMemberFromDepartment(userId, input) {
108
+ const department = await getDepartment(input.departmentId);
109
+ if (!department) {
110
+ throw new TRPCError({
111
+ code: "NOT_FOUND",
112
+ message: "Department not found",
113
+ });
114
+ }
115
+ await requireAdmin(department.schoolId, userId);
116
+ return removeDepartmentMember(input.departmentId, input.memberId);
117
+ }
118
+ /** Department template authoring (rubrics + boundaries). */
119
+ export async function createRubricTemplate(userId, input) {
120
+ const department = await getDepartment(input.departmentId);
121
+ if (!department) {
122
+ throw new TRPCError({
123
+ code: "NOT_FOUND",
124
+ message: "Department not found",
125
+ });
126
+ }
127
+ await requireAdmin(department.schoolId, userId);
128
+ return prisma.markScheme.create({
129
+ data: {
130
+ name: input.name,
131
+ structured: input.structured.replace(/\\n/g, "\n"),
132
+ department: { connect: { id: input.departmentId } },
133
+ },
134
+ select: { id: true, name: true, structured: true, departmentId: true },
135
+ });
136
+ }
137
+ export async function updateRubricTemplate(userId, input) {
138
+ const template = await prisma.markScheme.findUnique({
139
+ where: { id: input.templateId },
140
+ select: { departmentId: true, department: { select: { schoolId: true } } },
141
+ });
142
+ if (!template?.departmentId || !template.department) {
143
+ throw new TRPCError({
144
+ code: "NOT_FOUND",
145
+ message: "Template not found",
146
+ });
147
+ }
148
+ await requireAdmin(template.department.schoolId, userId);
149
+ return prisma.markScheme.update({
150
+ where: { id: input.templateId },
151
+ data: {
152
+ ...(input.name !== undefined ? { name: input.name } : {}),
153
+ ...(input.structured !== undefined
154
+ ? { structured: input.structured.replace(/\\n/g, "\n") }
155
+ : {}),
156
+ },
157
+ });
158
+ }
159
+ export async function deleteRubricTemplate(userId, templateId) {
160
+ const template = await prisma.markScheme.findUnique({
161
+ where: { id: templateId },
162
+ select: { departmentId: true, department: { select: { schoolId: true } } },
163
+ });
164
+ if (!template?.departmentId || !template.department) {
165
+ throw new TRPCError({
166
+ code: "NOT_FOUND",
167
+ message: "Template not found",
168
+ });
169
+ }
170
+ await requireAdmin(template.department.schoolId, userId);
171
+ return prisma.markScheme.delete({ where: { id: templateId } });
172
+ }
173
+ export async function createBoundaryTemplate(userId, input) {
174
+ const department = await getDepartment(input.departmentId);
175
+ if (!department) {
176
+ throw new TRPCError({
177
+ code: "NOT_FOUND",
178
+ message: "Department not found",
179
+ });
180
+ }
181
+ await requireAdmin(department.schoolId, userId);
182
+ return prisma.gradingBoundary.create({
183
+ data: {
184
+ name: input.name,
185
+ structured: input.structured.replace(/\\n/g, "\n"),
186
+ department: { connect: { id: input.departmentId } },
187
+ },
188
+ select: { id: true, name: true, structured: true, departmentId: true },
189
+ });
190
+ }
191
+ export async function updateBoundaryTemplate(userId, input) {
192
+ const template = await prisma.gradingBoundary.findUnique({
193
+ where: { id: input.templateId },
194
+ select: { departmentId: true, department: { select: { schoolId: true } } },
195
+ });
196
+ if (!template?.departmentId || !template.department) {
197
+ throw new TRPCError({
198
+ code: "NOT_FOUND",
199
+ message: "Template not found",
200
+ });
201
+ }
202
+ await requireAdmin(template.department.schoolId, userId);
203
+ return prisma.gradingBoundary.update({
204
+ where: { id: input.templateId },
205
+ data: {
206
+ ...(input.name !== undefined ? { name: input.name } : {}),
207
+ ...(input.structured !== undefined
208
+ ? { structured: input.structured.replace(/\\n/g, "\n") }
209
+ : {}),
210
+ },
211
+ });
212
+ }
213
+ export async function deleteBoundaryTemplate(userId, templateId) {
214
+ const template = await prisma.gradingBoundary.findUnique({
215
+ where: { id: templateId },
216
+ select: { departmentId: true, department: { select: { schoolId: true } } },
217
+ });
218
+ if (!template?.departmentId || !template.department) {
219
+ throw new TRPCError({
220
+ code: "NOT_FOUND",
221
+ message: "Template not found",
222
+ });
223
+ }
224
+ await requireAdmin(template.department.schoolId, userId);
225
+ return prisma.gradingBoundary.delete({ where: { id: templateId } });
226
+ }
227
+ /**
228
+ * Apply a department template to a class by *copying* the structured payload
229
+ * into a class-scoped record. Teacher-only (the class teacher).
230
+ */
231
+ export async function applyRubricTemplate(userId, input) {
232
+ const cls = await prisma.class.findFirst({
233
+ where: {
234
+ id: input.classId,
235
+ OR: [
236
+ { teachers: { some: { id: userId } } },
237
+ {
238
+ school: {
239
+ memberships: {
240
+ some: { userId, role: "ADMIN", status: "ACTIVE" },
241
+ },
242
+ },
243
+ },
244
+ ],
245
+ },
246
+ select: { id: true, departmentId: true },
247
+ });
248
+ if (!cls) {
249
+ throw new TRPCError({
250
+ code: "FORBIDDEN",
251
+ message: "You don't have permission to apply templates to this class",
252
+ });
253
+ }
254
+ const template = await prisma.markScheme.findUnique({
255
+ where: { id: input.templateId },
256
+ select: { id: true, structured: true, departmentId: true, name: true },
257
+ });
258
+ if (!template?.departmentId) {
259
+ throw new TRPCError({
260
+ code: "NOT_FOUND",
261
+ message: "Template not found",
262
+ });
263
+ }
264
+ if (cls.departmentId && cls.departmentId !== template.departmentId) {
265
+ throw new TRPCError({
266
+ code: "FORBIDDEN",
267
+ message: "This template belongs to a different department than the class",
268
+ });
269
+ }
270
+ return prisma.markScheme.create({
271
+ data: {
272
+ class: { connect: { id: input.classId } },
273
+ structured: template.structured,
274
+ name: template.name,
275
+ },
276
+ });
277
+ }
278
+ export async function applyBoundaryTemplate(userId, input) {
279
+ const cls = await prisma.class.findFirst({
280
+ where: {
281
+ id: input.classId,
282
+ OR: [
283
+ { teachers: { some: { id: userId } } },
284
+ {
285
+ school: {
286
+ memberships: {
287
+ some: { userId, role: "ADMIN", status: "ACTIVE" },
288
+ },
289
+ },
290
+ },
291
+ ],
292
+ },
293
+ select: { id: true, departmentId: true },
294
+ });
295
+ if (!cls) {
296
+ throw new TRPCError({
297
+ code: "FORBIDDEN",
298
+ message: "You don't have permission to apply templates to this class",
299
+ });
300
+ }
301
+ const template = await prisma.gradingBoundary.findUnique({
302
+ where: { id: input.templateId },
303
+ select: { id: true, structured: true, departmentId: true, name: true },
304
+ });
305
+ if (!template?.departmentId) {
306
+ throw new TRPCError({
307
+ code: "NOT_FOUND",
308
+ message: "Template not found",
309
+ });
310
+ }
311
+ if (cls.departmentId && cls.departmentId !== template.departmentId) {
312
+ throw new TRPCError({
313
+ code: "FORBIDDEN",
314
+ message: "This template belongs to a different department than the class",
315
+ });
316
+ }
317
+ return prisma.gradingBoundary.create({
318
+ data: {
319
+ class: { connect: { id: input.classId } },
320
+ structured: template.structured,
321
+ name: template.name,
322
+ },
323
+ });
324
+ }
325
+ /** Helper used by the auto-tag flow on class creation. */
326
+ export async function setClassDepartment(userId, input) {
327
+ const cls = await prisma.class.findFirst({
328
+ where: {
329
+ id: input.classId,
330
+ OR: [
331
+ { teachers: { some: { id: userId } } },
332
+ {
333
+ school: {
334
+ memberships: {
335
+ some: { userId, role: "ADMIN", status: "ACTIVE" },
336
+ },
337
+ },
338
+ },
339
+ ],
340
+ },
341
+ select: { id: true, schoolId: true },
342
+ });
343
+ if (!cls?.schoolId) {
344
+ throw new TRPCError({
345
+ code: "BAD_REQUEST",
346
+ message: "Class is not affiliated with an institution",
347
+ });
348
+ }
349
+ if (input.departmentId) {
350
+ const dept = await getDepartment(input.departmentId);
351
+ if (!dept || dept.schoolId !== cls.schoolId) {
352
+ throw new TRPCError({
353
+ code: "BAD_REQUEST",
354
+ message: "Department does not belong to this institution",
355
+ });
356
+ }
357
+ }
358
+ return prisma.class.update({
359
+ where: { id: input.classId },
360
+ data: { departmentId: input.departmentId },
361
+ select: { id: true, departmentId: true },
362
+ });
363
+ }
364
+ export async function checkDepartmentMember(userId, departmentId) {
365
+ return Boolean(await findDepartmentMembership(departmentId, userId));
366
+ }
367
+ //# sourceMappingURL=department.js.map
368
+ //# debugId=a61f9d68-eb30-571c-908d-8c1fb445f85c
@@ -0,0 +1 @@
1
+ {"version":3,"file":"department.js","sources":["services/department.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Department service — admin CRUD, members, and template management for\n * department-level rubrics and grading boundaries.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport { prisma } from \"../lib/prisma.js\";\nimport {\n addDepartmentMembers,\n createDepartment,\n deleteDepartment,\n findDepartmentMembership,\n getDepartment,\n listDepartmentsForSchool,\n listDepartmentsForUser,\n removeDepartmentMember,\n updateDepartment,\n} from \"../models/department.js\";\nimport {\n findActiveSchoolAdminMembership,\n findSchoolMembership,\n} from \"../models/school.js\";\n\nasync function requireAdmin(schoolId: string, userId: string) {\n const membership = await findActiveSchoolAdminMembership(schoolId, userId);\n if (!membership) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can manage departments\",\n });\n }\n}\n\nasync function requireMember(schoolId: string, userId: string) {\n const membership = await findSchoolMembership(schoolId, userId);\n if (!membership || membership.status !== \"ACTIVE\") {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You aren't a member of this institution\",\n });\n }\n}\n\nexport async function listDepartments(\n userId: string,\n schoolId: string\n) {\n await requireMember(schoolId, userId);\n return listDepartmentsForSchool(schoolId);\n}\n\nexport async function listMyDepartments(\n userId: string,\n schoolId: string\n) {\n await requireMember(schoolId, userId);\n return listDepartmentsForUser(userId, schoolId);\n}\n\nexport async function getDepartmentDetails(\n userId: string,\n departmentId: string\n) {\n const department = await getDepartment(departmentId);\n if (!department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Department not found\",\n });\n }\n await requireMember(department.schoolId, userId);\n return department;\n}\n\nexport async function createDepartmentRecord(\n userId: string,\n input: {\n schoolId: string;\n name: string;\n description?: string;\n color?: string;\n }\n) {\n await requireAdmin(input.schoolId, userId);\n return createDepartment(input);\n}\n\nexport async function updateDepartmentRecord(\n userId: string,\n input: {\n departmentId: string;\n name?: string;\n description?: string | null;\n color?: string;\n }\n) {\n const department = await getDepartment(input.departmentId);\n if (!department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Department not found\",\n });\n }\n await requireAdmin(department.schoolId, userId);\n return updateDepartment(input.departmentId, {\n name: input.name,\n description: input.description,\n color: input.color,\n });\n}\n\nexport async function deleteDepartmentRecord(\n userId: string,\n departmentId: string\n) {\n const department = await getDepartment(departmentId);\n if (!department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Department not found\",\n });\n }\n await requireAdmin(department.schoolId, userId);\n await deleteDepartment(departmentId);\n return { success: true };\n}\n\nexport async function addMembersToDepartment(\n userId: string,\n input: { departmentId: string; userIds: string[] }\n) {\n const department = await getDepartment(input.departmentId);\n if (!department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Department not found\",\n });\n }\n await requireAdmin(department.schoolId, userId);\n\n // Members must already be in the institution.\n const memberships = await prisma.schoolMembership.findMany({\n where: {\n schoolId: department.schoolId,\n userId: { in: input.userIds },\n status: \"ACTIVE\",\n },\n select: { userId: true },\n });\n const validIds = new Set(memberships.map((m) => m.userId));\n const validUserIds = input.userIds.filter((id) => validIds.has(id));\n\n if (validUserIds.length === 0) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"None of the supplied users are institution members\",\n });\n }\n return addDepartmentMembers(input.departmentId, validUserIds);\n}\n\nexport async function removeMemberFromDepartment(\n userId: string,\n input: { departmentId: string; memberId: string }\n) {\n const department = await getDepartment(input.departmentId);\n if (!department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Department not found\",\n });\n }\n await requireAdmin(department.schoolId, userId);\n return removeDepartmentMember(input.departmentId, input.memberId);\n}\n\n/** Department template authoring (rubrics + boundaries). */\nexport async function createRubricTemplate(\n userId: string,\n input: { departmentId: string; name: string; structured: string }\n) {\n const department = await getDepartment(input.departmentId);\n if (!department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Department not found\",\n });\n }\n await requireAdmin(department.schoolId, userId);\n return prisma.markScheme.create({\n data: {\n name: input.name,\n structured: input.structured.replace(/\\\\n/g, \"\\n\"),\n department: { connect: { id: input.departmentId } },\n },\n select: { id: true, name: true, structured: true, departmentId: true },\n });\n}\n\nexport async function updateRubricTemplate(\n userId: string,\n input: {\n templateId: string;\n name?: string;\n structured?: string;\n }\n) {\n const template = await prisma.markScheme.findUnique({\n where: { id: input.templateId },\n select: { departmentId: true, department: { select: { schoolId: true } } },\n });\n if (!template?.departmentId || !template.department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Template not found\",\n });\n }\n await requireAdmin(template.department.schoolId, userId);\n return prisma.markScheme.update({\n where: { id: input.templateId },\n data: {\n ...(input.name !== undefined ? { name: input.name } : {}),\n ...(input.structured !== undefined\n ? { structured: input.structured.replace(/\\\\n/g, \"\\n\") }\n : {}),\n },\n });\n}\n\nexport async function deleteRubricTemplate(\n userId: string,\n templateId: string\n) {\n const template = await prisma.markScheme.findUnique({\n where: { id: templateId },\n select: { departmentId: true, department: { select: { schoolId: true } } },\n });\n if (!template?.departmentId || !template.department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Template not found\",\n });\n }\n await requireAdmin(template.department.schoolId, userId);\n return prisma.markScheme.delete({ where: { id: templateId } });\n}\n\nexport async function createBoundaryTemplate(\n userId: string,\n input: { departmentId: string; name: string; structured: string }\n) {\n const department = await getDepartment(input.departmentId);\n if (!department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Department not found\",\n });\n }\n await requireAdmin(department.schoolId, userId);\n return prisma.gradingBoundary.create({\n data: {\n name: input.name,\n structured: input.structured.replace(/\\\\n/g, \"\\n\"),\n department: { connect: { id: input.departmentId } },\n },\n select: { id: true, name: true, structured: true, departmentId: true },\n });\n}\n\nexport async function updateBoundaryTemplate(\n userId: string,\n input: {\n templateId: string;\n name?: string;\n structured?: string;\n }\n) {\n const template = await prisma.gradingBoundary.findUnique({\n where: { id: input.templateId },\n select: { departmentId: true, department: { select: { schoolId: true } } },\n });\n if (!template?.departmentId || !template.department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Template not found\",\n });\n }\n await requireAdmin(template.department.schoolId, userId);\n return prisma.gradingBoundary.update({\n where: { id: input.templateId },\n data: {\n ...(input.name !== undefined ? { name: input.name } : {}),\n ...(input.structured !== undefined\n ? { structured: input.structured.replace(/\\\\n/g, \"\\n\") }\n : {}),\n },\n });\n}\n\nexport async function deleteBoundaryTemplate(\n userId: string,\n templateId: string\n) {\n const template = await prisma.gradingBoundary.findUnique({\n where: { id: templateId },\n select: { departmentId: true, department: { select: { schoolId: true } } },\n });\n if (!template?.departmentId || !template.department) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Template not found\",\n });\n }\n await requireAdmin(template.department.schoolId, userId);\n return prisma.gradingBoundary.delete({ where: { id: templateId } });\n}\n\n/**\n * Apply a department template to a class by *copying* the structured payload\n * into a class-scoped record. Teacher-only (the class teacher).\n */\nexport async function applyRubricTemplate(\n userId: string,\n input: { classId: string; templateId: string }\n) {\n const cls = await prisma.class.findFirst({\n where: {\n id: input.classId,\n OR: [\n { teachers: { some: { id: userId } } },\n {\n school: {\n memberships: {\n some: { userId, role: \"ADMIN\", status: \"ACTIVE\" },\n },\n },\n },\n ],\n },\n select: { id: true, departmentId: true },\n });\n if (!cls) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to apply templates to this class\",\n });\n }\n\n const template = await prisma.markScheme.findUnique({\n where: { id: input.templateId },\n select: { id: true, structured: true, departmentId: true, name: true },\n });\n if (!template?.departmentId) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Template not found\",\n });\n }\n if (cls.departmentId && cls.departmentId !== template.departmentId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message:\n \"This template belongs to a different department than the class\",\n });\n }\n\n return prisma.markScheme.create({\n data: {\n class: { connect: { id: input.classId } },\n structured: template.structured,\n name: template.name,\n },\n });\n}\n\nexport async function applyBoundaryTemplate(\n userId: string,\n input: { classId: string; templateId: string }\n) {\n const cls = await prisma.class.findFirst({\n where: {\n id: input.classId,\n OR: [\n { teachers: { some: { id: userId } } },\n {\n school: {\n memberships: {\n some: { userId, role: \"ADMIN\", status: \"ACTIVE\" },\n },\n },\n },\n ],\n },\n select: { id: true, departmentId: true },\n });\n if (!cls) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to apply templates to this class\",\n });\n }\n\n const template = await prisma.gradingBoundary.findUnique({\n where: { id: input.templateId },\n select: { id: true, structured: true, departmentId: true, name: true },\n });\n if (!template?.departmentId) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Template not found\",\n });\n }\n if (cls.departmentId && cls.departmentId !== template.departmentId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message:\n \"This template belongs to a different department than the class\",\n });\n }\n\n return prisma.gradingBoundary.create({\n data: {\n class: { connect: { id: input.classId } },\n structured: template.structured,\n name: template.name,\n },\n });\n}\n\n/** Helper used by the auto-tag flow on class creation. */\nexport async function setClassDepartment(\n userId: string,\n input: { classId: string; departmentId: string | null }\n) {\n const cls = await prisma.class.findFirst({\n where: {\n id: input.classId,\n OR: [\n { teachers: { some: { id: userId } } },\n {\n school: {\n memberships: {\n some: { userId, role: \"ADMIN\", status: \"ACTIVE\" },\n },\n },\n },\n ],\n },\n select: { id: true, schoolId: true },\n });\n if (!cls?.schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Class is not affiliated with an institution\",\n });\n }\n\n if (input.departmentId) {\n const dept = await getDepartment(input.departmentId);\n if (!dept || dept.schoolId !== cls.schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Department does not belong to this institution\",\n });\n }\n }\n return prisma.class.update({\n where: { id: input.classId },\n data: { departmentId: input.departmentId },\n select: { id: true, departmentId: true },\n });\n}\n\nexport async function checkDepartmentMember(\n userId: string,\n departmentId: string\n) {\n return Boolean(await findDepartmentMembership(departmentId, userId));\n}\n"],"names":[],"mappings":"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","debug_id":"a61f9d68-eb30-571c-908d-8c1fb445f85c"}