@studious-lms/server 1.23.0 → 1.25.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 (298) hide show
  1. package/.env.example +0 -1
  2. package/data/curriculum/nepal-cdc-g4-g5/README.md +90 -0
  3. package/data/curriculum/nepal-cdc-g4-g5/manifest.json +97 -0
  4. package/data/curriculum/nepal-cdc-g4-g5/proficiency-scale.json +76 -0
  5. package/data/curriculum/nepal-cdc-g4-g5/subjects/english.json +6936 -0
  6. package/data/curriculum/nepal-cdc-g4-g5/subjects/health-physical-creative-arts.json +3401 -0
  7. package/data/curriculum/nepal-cdc-g4-g5/subjects/mathematics.json +1511 -0
  8. package/data/curriculum/nepal-cdc-g4-g5/subjects/nepali.json +7928 -0
  9. package/data/curriculum/nepal-cdc-g4-g5/subjects/science-technology.json +2420 -0
  10. package/data/curriculum/nepal-cdc-g4-g5/subjects/social-studies.json +2177 -0
  11. package/dist/lib/assignmentTypeDefaults.d.ts +41 -0
  12. package/dist/lib/assignmentTypeDefaults.d.ts.map +1 -0
  13. package/dist/lib/assignmentTypeDefaults.js +167 -0
  14. package/dist/lib/assignmentTypeDefaults.js.map +1 -0
  15. package/dist/lib/config/env.d.ts +0 -8
  16. package/dist/lib/config/env.d.ts.map +1 -1
  17. package/dist/lib/config/env.js +2 -5
  18. package/dist/lib/config/env.js.map +1 -1
  19. package/dist/lib/feePdf.d.ts +19 -0
  20. package/dist/lib/feePdf.d.ts.map +1 -0
  21. package/dist/lib/feePdf.js +167 -0
  22. package/dist/lib/feePdf.js.map +1 -0
  23. package/dist/lib/feePdfFormat.d.ts +4 -0
  24. package/dist/lib/feePdfFormat.d.ts.map +1 -0
  25. package/dist/lib/feePdfFormat.js +16 -0
  26. package/dist/lib/feePdfFormat.js.map +1 -0
  27. package/dist/lib/idCardPdf.d.ts +26 -0
  28. package/dist/lib/idCardPdf.d.ts.map +1 -0
  29. package/dist/lib/idCardPdf.js +272 -0
  30. package/dist/lib/idCardPdf.js.map +1 -0
  31. package/dist/lib/pdfLetterhead.d.ts +41 -0
  32. package/dist/lib/pdfLetterhead.d.ts.map +1 -0
  33. package/dist/lib/pdfLetterhead.js +86 -0
  34. package/dist/lib/pdfLetterhead.js.map +1 -0
  35. package/dist/lib/transcriptPdf.d.ts +55 -0
  36. package/dist/lib/transcriptPdf.d.ts.map +1 -0
  37. package/dist/lib/transcriptPdf.js +303 -0
  38. package/dist/lib/transcriptPdf.js.map +1 -0
  39. package/dist/models/academicCalendar.d.ts +198 -0
  40. package/dist/models/academicCalendar.d.ts.map +1 -0
  41. package/dist/models/academicCalendar.js +106 -0
  42. package/dist/models/academicCalendar.js.map +1 -0
  43. package/dist/models/agenda.d.ts +8 -0
  44. package/dist/models/agenda.d.ts.map +1 -1
  45. package/dist/models/announcement.d.ts +2 -0
  46. package/dist/models/announcement.d.ts.map +1 -1
  47. package/dist/models/assignment.d.ts +66 -0
  48. package/dist/models/assignment.d.ts.map +1 -1
  49. package/dist/models/attendance.d.ts +659 -21
  50. package/dist/models/attendance.d.ts.map +1 -1
  51. package/dist/models/attendance.js +547 -75
  52. package/dist/models/attendance.js.map +1 -1
  53. package/dist/models/auth.d.ts +2 -0
  54. package/dist/models/auth.d.ts.map +1 -1
  55. package/dist/models/class.d.ts +12 -0
  56. package/dist/models/class.d.ts.map +1 -1
  57. package/dist/models/class.js +3 -2
  58. package/dist/models/class.js.map +1 -1
  59. package/dist/models/event.d.ts +16 -0
  60. package/dist/models/event.d.ts.map +1 -1
  61. package/dist/models/fees.d.ts +554 -0
  62. package/dist/models/fees.d.ts.map +1 -0
  63. package/dist/models/fees.js +278 -0
  64. package/dist/models/fees.js.map +1 -0
  65. package/dist/models/file.d.ts +29 -0
  66. package/dist/models/file.d.ts.map +1 -1
  67. package/dist/models/folder.d.ts +2 -0
  68. package/dist/models/folder.d.ts.map +1 -1
  69. package/dist/models/labChat.d.ts +2 -0
  70. package/dist/models/labChat.d.ts.map +1 -1
  71. package/dist/models/marketplace.d.ts +180 -0
  72. package/dist/models/marketplace.d.ts.map +1 -0
  73. package/dist/models/marketplace.js +116 -0
  74. package/dist/models/marketplace.js.map +1 -0
  75. package/dist/models/moduleItem.d.ts +308 -0
  76. package/dist/models/moduleItem.d.ts.map +1 -0
  77. package/dist/models/moduleItem.js +93 -0
  78. package/dist/models/moduleItem.js.map +1 -0
  79. package/dist/models/newtonChat.d.ts +1 -0
  80. package/dist/models/newtonChat.d.ts.map +1 -1
  81. package/dist/models/school.d.ts +18 -0
  82. package/dist/models/school.d.ts.map +1 -1
  83. package/dist/models/school.js +7 -2
  84. package/dist/models/school.js.map +1 -1
  85. package/dist/models/section.d.ts +4 -0
  86. package/dist/models/section.d.ts.map +1 -1
  87. package/dist/models/worksheet.d.ts +19 -0
  88. package/dist/models/worksheet.d.ts.map +1 -1
  89. package/dist/models/worksheet.js +2 -2
  90. package/dist/models/worksheet.js.map +1 -1
  91. package/dist/routers/_app.d.ts +12024 -7778
  92. package/dist/routers/_app.d.ts.map +1 -1
  93. package/dist/routers/_app.js +12 -2
  94. package/dist/routers/_app.js.map +1 -1
  95. package/dist/routers/academicCalendar.d.ts +229 -0
  96. package/dist/routers/academicCalendar.d.ts.map +1 -0
  97. package/dist/routers/academicCalendar.js +75 -0
  98. package/dist/routers/academicCalendar.js.map +1 -0
  99. package/dist/routers/admin.d.ts +2 -0
  100. package/dist/routers/admin.d.ts.map +1 -1
  101. package/dist/routers/agenda.d.ts +8 -0
  102. package/dist/routers/agenda.d.ts.map +1 -1
  103. package/dist/routers/assignment.d.ts +75 -0
  104. package/dist/routers/assignment.d.ts.map +1 -1
  105. package/dist/routers/assignment.js +10 -2
  106. package/dist/routers/assignment.js.map +1 -1
  107. package/dist/routers/attendance.d.ts +103 -0
  108. package/dist/routers/attendance.d.ts.map +1 -1
  109. package/dist/routers/attendance.js +8 -5
  110. package/dist/routers/attendance.js.map +1 -1
  111. package/dist/routers/class.d.ts +27 -0
  112. package/dist/routers/class.d.ts.map +1 -1
  113. package/dist/routers/class.js +6 -2
  114. package/dist/routers/class.js.map +1 -1
  115. package/dist/routers/event.d.ts +8 -0
  116. package/dist/routers/event.d.ts.map +1 -1
  117. package/dist/routers/fees.d.ts +513 -0
  118. package/dist/routers/fees.d.ts.map +1 -0
  119. package/dist/routers/fees.js +88 -0
  120. package/dist/routers/fees.js.map +1 -0
  121. package/dist/routers/file.d.ts +2 -0
  122. package/dist/routers/file.d.ts.map +1 -1
  123. package/dist/routers/gradebook.d.ts +4 -1
  124. package/dist/routers/gradebook.d.ts.map +1 -1
  125. package/dist/routers/marketplace.d.ts +371 -0
  126. package/dist/routers/marketplace.d.ts.map +1 -0
  127. package/dist/routers/marketplace.js +87 -0
  128. package/dist/routers/marketplace.js.map +1 -0
  129. package/dist/routers/moduleItem.d.ts +263 -0
  130. package/dist/routers/moduleItem.d.ts.map +1 -0
  131. package/dist/routers/moduleItem.js +61 -0
  132. package/dist/routers/moduleItem.js.map +1 -0
  133. package/dist/routers/parent.d.ts +170 -0
  134. package/dist/routers/parent.d.ts.map +1 -0
  135. package/dist/routers/parent.js +49 -0
  136. package/dist/routers/parent.js.map +1 -0
  137. package/dist/routers/school.d.ts +363 -7
  138. package/dist/routers/school.d.ts.map +1 -1
  139. package/dist/routers/school.js +110 -3
  140. package/dist/routers/school.js.map +1 -1
  141. package/dist/routers/worksheet.d.ts +27 -0
  142. package/dist/routers/worksheet.d.ts.map +1 -1
  143. package/dist/routers/worksheet.js +10 -3
  144. package/dist/routers/worksheet.js.map +1 -1
  145. package/dist/services/academicCalendar.d.ts +173 -0
  146. package/dist/services/academicCalendar.d.ts.map +1 -0
  147. package/dist/services/academicCalendar.js +242 -0
  148. package/dist/services/academicCalendar.js.map +1 -0
  149. package/dist/services/adminInstitution.d.ts +2 -0
  150. package/dist/services/adminInstitution.d.ts.map +1 -1
  151. package/dist/services/agenda.d.ts +8 -0
  152. package/dist/services/agenda.d.ts.map +1 -1
  153. package/dist/services/assignment.d.ts +75 -0
  154. package/dist/services/assignment.d.ts.map +1 -1
  155. package/dist/services/assignment.js +91 -12
  156. package/dist/services/assignment.js.map +1 -1
  157. package/dist/services/attendance.d.ts +327 -10
  158. package/dist/services/attendance.d.ts.map +1 -1
  159. package/dist/services/attendance.js +389 -25
  160. package/dist/services/attendance.js.map +1 -1
  161. package/dist/services/attendanceMerge.d.ts +53 -0
  162. package/dist/services/attendanceMerge.d.ts.map +1 -0
  163. package/dist/services/attendanceMerge.js +87 -0
  164. package/dist/services/attendanceMerge.js.map +1 -0
  165. package/dist/services/attendanceRate.d.ts +24 -0
  166. package/dist/services/attendanceRate.d.ts.map +1 -0
  167. package/dist/services/attendanceRate.js +31 -0
  168. package/dist/services/attendanceRate.js.map +1 -0
  169. package/dist/services/attendanceStats.d.ts +22 -0
  170. package/dist/services/attendanceStats.d.ts.map +1 -0
  171. package/dist/services/attendanceStats.js +45 -0
  172. package/dist/services/attendanceStats.js.map +1 -0
  173. package/dist/services/class.d.ts +34 -2
  174. package/dist/services/class.d.ts.map +1 -1
  175. package/dist/services/class.js +27 -4
  176. package/dist/services/class.js.map +1 -1
  177. package/dist/services/event.d.ts +8 -0
  178. package/dist/services/event.d.ts.map +1 -1
  179. package/dist/services/fees.d.ts +422 -0
  180. package/dist/services/fees.d.ts.map +1 -0
  181. package/dist/services/fees.js +330 -0
  182. package/dist/services/fees.js.map +1 -0
  183. package/dist/services/feesAuthz.d.ts +46 -0
  184. package/dist/services/feesAuthz.d.ts.map +1 -0
  185. package/dist/services/feesAuthz.js +49 -0
  186. package/dist/services/feesAuthz.js.map +1 -0
  187. package/dist/services/file.d.ts +4 -0
  188. package/dist/services/file.d.ts.map +1 -1
  189. package/dist/services/gradebook.d.ts +18 -1
  190. package/dist/services/gradebook.d.ts.map +1 -1
  191. package/dist/services/gradebook.js +57 -2
  192. package/dist/services/gradebook.js.map +1 -1
  193. package/dist/services/idCard.d.ts +11 -0
  194. package/dist/services/idCard.d.ts.map +1 -0
  195. package/dist/services/idCard.js +122 -0
  196. package/dist/services/idCard.js.map +1 -0
  197. package/dist/services/marketplace.d.ts +301 -0
  198. package/dist/services/marketplace.d.ts.map +1 -0
  199. package/dist/services/marketplace.js +631 -0
  200. package/dist/services/marketplace.js.map +1 -0
  201. package/dist/services/moduleItem.d.ts +196 -0
  202. package/dist/services/moduleItem.d.ts.map +1 -0
  203. package/dist/services/moduleItem.js +204 -0
  204. package/dist/services/moduleItem.js.map +1 -0
  205. package/dist/services/notification.d.ts +58 -0
  206. package/dist/services/notification.d.ts.map +1 -1
  207. package/dist/services/notification.js +30 -2
  208. package/dist/services/notification.js.map +1 -1
  209. package/dist/services/parentPortal.d.ts +131 -0
  210. package/dist/services/parentPortal.d.ts.map +1 -0
  211. package/dist/services/parentPortal.js +314 -0
  212. package/dist/services/parentPortal.js.map +1 -0
  213. package/dist/services/school.d.ts +28 -3
  214. package/dist/services/school.d.ts.map +1 -1
  215. package/dist/services/school.js +98 -54
  216. package/dist/services/school.js.map +1 -1
  217. package/dist/services/studentImport.d.ts +34 -0
  218. package/dist/services/studentImport.d.ts.map +1 -0
  219. package/dist/services/studentImport.js +249 -0
  220. package/dist/services/studentImport.js.map +1 -0
  221. package/dist/services/transcript.d.ts +60 -0
  222. package/dist/services/transcript.d.ts.map +1 -0
  223. package/dist/services/transcript.js +231 -0
  224. package/dist/services/transcript.js.map +1 -0
  225. package/dist/services/worksheet.d.ts +22 -0
  226. package/dist/services/worksheet.d.ts.map +1 -1
  227. package/dist/services/worksheet.js +94 -2
  228. package/dist/services/worksheet.js.map +1 -1
  229. package/dist/trpc.d.ts +1 -1
  230. package/dist/trpc.d.ts.map +1 -1
  231. package/dist/trpc.js +5 -5
  232. package/dist/trpc.js.map +1 -1
  233. package/dist/utils/adminPanelAccess.d.ts +4 -5
  234. package/dist/utils/adminPanelAccess.d.ts.map +1 -1
  235. package/dist/utils/adminPanelAccess.js +12 -34
  236. package/dist/utils/adminPanelAccess.js.map +1 -1
  237. package/package.json +2 -1
  238. package/prisma/migrations/20260804120000_add_attendance_records_and_excusals/migration.sql +114 -0
  239. package/prisma/migrations/20260804120100_add_fee_plans_invoices_payments/migration.sql +101 -0
  240. package/prisma/migrations/20260804120200_add_marketplace_listings/migration.sql +54 -0
  241. package/prisma/migrations/20260804120300_content_platform_b3_b9/migration.sql +63 -0
  242. package/prisma/migrations/20260804120400_c_academic_ops/migration.sql +77 -0
  243. package/prisma/schema.prisma +371 -11
  244. package/scripts/import-nepal-cdc-curriculum.ts +402 -0
  245. package/src/lib/assignmentTypeDefaults.ts +222 -0
  246. package/src/lib/config/env.ts +0 -3
  247. package/src/lib/feePdf.ts +199 -0
  248. package/src/lib/feePdfFormat.ts +14 -0
  249. package/src/lib/idCardPdf.ts +336 -0
  250. package/src/lib/pdfLetterhead.ts +124 -0
  251. package/src/lib/transcriptPdf.ts +502 -0
  252. package/src/models/academicCalendar.ts +139 -0
  253. package/src/models/attendance.ts +702 -73
  254. package/src/models/class.ts +1 -0
  255. package/src/models/fees.ts +349 -0
  256. package/src/models/marketplace.ts +161 -0
  257. package/src/models/moduleItem.ts +125 -0
  258. package/src/models/school.ts +6 -0
  259. package/src/models/worksheet.ts +2 -0
  260. package/src/routers/_app.ts +10 -0
  261. package/src/routers/academicCalendar.ts +103 -0
  262. package/src/routers/assignment.ts +8 -0
  263. package/src/routers/attendance.ts +7 -3
  264. package/src/routers/class.ts +4 -0
  265. package/src/routers/fees.ts +126 -0
  266. package/src/routers/marketplace.ts +134 -0
  267. package/src/routers/moduleItem.ts +91 -0
  268. package/src/routers/parent.ts +68 -0
  269. package/src/routers/school.ts +149 -1
  270. package/src/routers/worksheet.ts +11 -0
  271. package/src/services/academicCalendar.ts +327 -0
  272. package/src/services/assignment.ts +122 -12
  273. package/src/services/attendance.ts +552 -26
  274. package/src/services/attendanceMerge.ts +139 -0
  275. package/src/services/attendanceRate.ts +41 -0
  276. package/src/services/attendanceStats.ts +63 -0
  277. package/src/services/class.ts +26 -2
  278. package/src/services/fees.ts +447 -0
  279. package/src/services/feesAuthz.ts +73 -0
  280. package/src/services/gradebook.ts +70 -0
  281. package/src/services/idCard.ts +147 -0
  282. package/src/services/marketplace.ts +790 -0
  283. package/src/services/moduleItem.ts +298 -0
  284. package/src/services/notification.ts +43 -0
  285. package/src/services/parentPortal.ts +367 -0
  286. package/src/services/school.ts +100 -54
  287. package/src/services/studentImport.ts +285 -0
  288. package/src/services/transcript.ts +301 -0
  289. package/src/services/worksheet.ts +111 -0
  290. package/src/trpc.ts +3 -3
  291. package/src/utils/adminPanelAccess.ts +12 -35
  292. package/tests/unit/assignmentTypeDefaults.test.ts +52 -0
  293. package/tests/unit/lib/feePdf.test.ts +15 -0
  294. package/tests/unit/lib/idCardPdf.test.ts +40 -0
  295. package/tests/unit/lib/transcriptPdf.test.ts +111 -0
  296. package/tests/unit/services/attendanceMerge.test.ts +90 -0
  297. package/tests/unit/services/attendanceRate.test.ts +38 -0
  298. package/tests/unit/services/attendanceStats.test.ts +54 -0
@@ -1 +1 @@
1
- {"version":3,"file":"school.d.ts","sourceRoot":"/","sources":["services/school.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"school.d.ts","sourceRoot":"/","sources":["services/school.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  * School service - school admin workflow, memberships, and invites.
3
3
  */
4
4
 
5
- !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]="70890b65-7dda-51a3-925f-31c75be34a33")}catch(e){}}();
5
+ !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]="7675f5a8-bfcb-53db-b66d-cdd4c8755f46")}catch(e){}}();
6
6
  import { SessionType } from "@prisma/client";
7
7
  import { TRPCError } from "@trpc/server";
8
8
  import { hash } from "bcryptjs";
@@ -51,6 +51,9 @@ export async function getCurrentSchool(userId, schoolId) {
51
51
  // signed URL through trpc.file.getSignedUrl when needed.
52
52
  logoPath: activeMembership.school.logo?.path ?? null,
53
53
  logoType: activeMembership.school.logo?.type ?? null,
54
+ letterheadFileId: activeMembership.school.letterheadFileId ?? null,
55
+ letterheadPath: activeMembership.school.letterhead?.path ?? null,
56
+ letterheadType: activeMembership.school.letterhead?.type ?? null,
54
57
  }
55
58
  : null;
56
59
  return {
@@ -73,11 +76,32 @@ export async function createSchoolRecord(userId, input) {
73
76
  }
74
77
  export async function updateSchoolDetails(userId, input) {
75
78
  await requireSchoolAdmin(input.schoolId, userId);
79
+ const brandingFileIds = [input.logoId, input.letterheadFileId].filter((id) => typeof id === "string");
80
+ if (brandingFileIds.length) {
81
+ const accessible = await prisma.file.findMany({
82
+ where: {
83
+ id: { in: brandingFileIds },
84
+ OR: [
85
+ { userId },
86
+ { folder: { schoolStorageId: input.schoolId } },
87
+ ],
88
+ },
89
+ select: { id: true },
90
+ });
91
+ const accessibleIds = new Set(accessible.map((f) => f.id));
92
+ if (brandingFileIds.some((id) => !accessibleIds.has(id))) {
93
+ throw new TRPCError({
94
+ code: "FORBIDDEN",
95
+ message: "File does not belong to this school",
96
+ });
97
+ }
98
+ }
76
99
  const updated = await updateSchoolRecord(input.schoolId, {
77
100
  name: input.name,
78
101
  description: input.description,
79
102
  subdomain: input.subdomain,
80
103
  logoId: input.logoId,
104
+ letterheadFileId: input.letterheadFileId,
81
105
  });
82
106
  return { school: updated };
83
107
  }
@@ -93,7 +117,13 @@ export async function getAdminOverview(userId, schoolId) {
93
117
  const roleCounts = school.memberships.reduce((counts, membership) => {
94
118
  counts[membership.role] += 1;
95
119
  return counts;
96
- }, { ADMIN: 0, TEACHER: 0, STUDENT: 0 });
120
+ }, {
121
+ ADMIN: 0,
122
+ TEACHER: 0,
123
+ STUDENT: 0,
124
+ ACCOUNTANT: 0,
125
+ PARENT: 0,
126
+ });
97
127
  return {
98
128
  school: {
99
129
  id: school.id,
@@ -423,16 +453,18 @@ export async function getStudentTimeline(userId, input) {
423
453
  message: "Student is not in this institution",
424
454
  });
425
455
  }
456
+ // Default to the last 12 months when no range is given, to bound reads.
457
+ const defaultFrom = new Date();
458
+ defaultFrom.setFullYear(defaultFrom.getFullYear() - 1);
426
459
  const range = {
427
- ...(input.from ? { gte: input.from } : {}),
460
+ gte: input.from ?? defaultFrom,
428
461
  ...(input.to ? { lte: input.to } : {}),
429
462
  };
430
- const hasRange = Object.keys(range).length > 0;
431
463
  const [events, assignments, attendance] = await Promise.all([
432
464
  prisma.event.findMany({
433
465
  where: {
434
466
  userId: input.studentId,
435
- ...(hasRange ? { startTime: range } : {}),
467
+ startTime: range,
436
468
  },
437
469
  select: {
438
470
  id: true,
@@ -452,7 +484,7 @@ export async function getStudentTimeline(userId, input) {
452
484
  students: { some: { id: input.studentId } },
453
485
  },
454
486
  template: false,
455
- ...(hasRange ? { dueDate: range } : {}),
487
+ dueDate: range,
456
488
  },
457
489
  select: {
458
490
  id: true,
@@ -484,35 +516,40 @@ export async function getStudentTimeline(userId, input) {
484
516
  },
485
517
  orderBy: { dueDate: "asc" },
486
518
  }),
487
- prisma.attendance.findMany({
519
+ prisma.attendanceRecord.findMany({
488
520
  where: {
489
- OR: [
490
- { present: { some: { id: input.studentId } } },
491
- { late: { some: { id: input.studentId } } },
492
- { absent: { some: { id: input.studentId } } },
493
- ],
494
- ...(hasRange ? { date: range } : {}),
521
+ studentId: input.studentId,
522
+ attendance: {
523
+ class: { schoolId: input.schoolId },
524
+ date: range,
525
+ },
495
526
  },
496
527
  select: {
497
528
  id: true,
498
- date: true,
499
- class: { select: { id: true, name: true, color: true } },
500
- present: { where: { id: input.studentId }, select: { id: true } },
501
- late: { where: { id: input.studentId }, select: { id: true } },
502
- absent: { where: { id: input.studentId }, select: { id: true } },
529
+ status: true,
530
+ note: true,
531
+ excusedByExcusalId: true,
532
+ attendance: {
533
+ select: {
534
+ id: true,
535
+ date: true,
536
+ class: { select: { id: true, name: true, color: true } },
537
+ },
538
+ },
539
+ excusedByExcusal: { select: { id: true, reason: true } },
503
540
  },
504
- orderBy: { date: "asc" },
541
+ orderBy: { attendance: { date: "asc" } },
505
542
  }),
506
543
  ]);
507
544
  const attendanceShaped = attendance.map((record) => ({
508
- id: record.id,
509
- date: record.date,
510
- class: record.class,
511
- status: record.present.length
512
- ? "PRESENT"
513
- : record.late.length
514
- ? "LATE"
515
- : "ABSENT",
545
+ id: record.attendance.id,
546
+ recordId: record.id,
547
+ date: record.attendance.date,
548
+ class: record.attendance.class,
549
+ status: record.status,
550
+ note: record.note,
551
+ lockedFromExcusal: Boolean(record.excusedByExcusalId),
552
+ reason: record.excusedByExcusal?.reason ?? null,
516
553
  }));
517
554
  return {
518
555
  student: studentMembership.user,
@@ -560,11 +597,13 @@ export async function getMemberTimeline(userId, input) {
560
597
  message: "This person is not in this institution",
561
598
  });
562
599
  }
600
+ // Default to the last 12 months when no range is given, to bound reads.
601
+ const defaultFrom = new Date();
602
+ defaultFrom.setFullYear(defaultFrom.getFullYear() - 1);
563
603
  const range = {
564
- ...(input.from ? { gte: input.from } : {}),
604
+ gte: input.from ?? defaultFrom,
565
605
  ...(input.to ? { lte: input.to } : {}),
566
606
  };
567
- const hasRange = Object.keys(range).length > 0;
568
607
  if (membership.role === "STUDENT") {
569
608
  if (!callerIsAdmin) {
570
609
  const sharedClass = await prisma.class.findFirst({
@@ -586,7 +625,7 @@ export async function getMemberTimeline(userId, input) {
586
625
  prisma.event.findMany({
587
626
  where: {
588
627
  userId: input.memberId,
589
- ...(hasRange ? { startTime: range } : {}),
628
+ startTime: range,
590
629
  },
591
630
  select: {
592
631
  id: true,
@@ -604,7 +643,7 @@ export async function getMemberTimeline(userId, input) {
604
643
  where: {
605
644
  class: { students: { some: { id: input.memberId } } },
606
645
  template: false,
607
- ...(hasRange ? { dueDate: range } : {}),
646
+ dueDate: range,
608
647
  },
609
648
  select: {
610
649
  id: true,
@@ -636,35 +675,40 @@ export async function getMemberTimeline(userId, input) {
636
675
  },
637
676
  orderBy: { dueDate: "asc" },
638
677
  }),
639
- prisma.attendance.findMany({
678
+ prisma.attendanceRecord.findMany({
640
679
  where: {
641
- OR: [
642
- { present: { some: { id: input.memberId } } },
643
- { late: { some: { id: input.memberId } } },
644
- { absent: { some: { id: input.memberId } } },
645
- ],
646
- ...(hasRange ? { date: range } : {}),
680
+ studentId: input.memberId,
681
+ attendance: {
682
+ class: { schoolId: input.schoolId },
683
+ date: range,
684
+ },
647
685
  },
648
686
  select: {
649
687
  id: true,
650
- date: true,
651
- class: { select: { id: true, name: true, color: true } },
652
- present: { where: { id: input.memberId }, select: { id: true } },
653
- late: { where: { id: input.memberId }, select: { id: true } },
654
- absent: { where: { id: input.memberId }, select: { id: true } },
688
+ status: true,
689
+ note: true,
690
+ excusedByExcusalId: true,
691
+ attendance: {
692
+ select: {
693
+ id: true,
694
+ date: true,
695
+ class: { select: { id: true, name: true, color: true } },
696
+ },
697
+ },
698
+ excusedByExcusal: { select: { id: true, reason: true } },
655
699
  },
656
- orderBy: { date: "asc" },
700
+ orderBy: { attendance: { date: "asc" } },
657
701
  }),
658
702
  ]);
659
703
  const attendanceShaped = attendance.map((record) => ({
660
- id: record.id,
661
- date: record.date,
662
- class: record.class,
663
- status: record.present.length
664
- ? "PRESENT"
665
- : record.late.length
666
- ? "LATE"
667
- : "ABSENT",
704
+ id: record.attendance.id,
705
+ recordId: record.id,
706
+ date: record.attendance.date,
707
+ class: record.attendance.class,
708
+ status: record.status,
709
+ note: record.note,
710
+ lockedFromExcusal: Boolean(record.excusedByExcusalId),
711
+ reason: record.excusedByExcusal?.reason ?? null,
668
712
  }));
669
713
  return {
670
714
  role: "STUDENT",
@@ -688,7 +732,7 @@ export async function getMemberTimeline(userId, input) {
688
732
  { userId: input.memberId },
689
733
  { class: { teachers: { some: { id: input.memberId } } } },
690
734
  ],
691
- ...(hasRange ? { startTime: range } : {}),
735
+ startTime: range,
692
736
  },
693
737
  select: {
694
738
  id: true,
@@ -865,4 +909,4 @@ export async function acceptInvite(userId, token) {
865
909
  return { membership };
866
910
  }
867
911
  //# sourceMappingURL=school.js.map
868
- //# debugId=70890b65-7dda-51a3-925f-31c75be34a33
912
+ //# debugId=7675f5a8-bfcb-53db-b66d-cdd4c8755f46
@@ -1 +1 @@
1
- {"version":3,"file":"school.js","sources":["services/school.ts"],"sourceRoot":"/","sourcesContent":["/**\n * School service - school admin workflow, memberships, and invites.\n */\nimport { SchoolMembershipRole, SessionType } from \"@prisma/client\";\nimport { TRPCError } from \"@trpc/server\";\nimport { hash } from \"bcryptjs\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { env } from \"../lib/config/env.js\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { sendMail } from \"../utils/email.js\";\nimport { generateUniqueUsername } from \"../utils/generateUsername.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n createSession,\n createUser,\n findUserByEmail,\n findUserById,\n findUserByUsername,\n} from \"../models/auth.js\";\nimport { upsertUserProfile } from \"../models/user.js\";\nimport {\n acceptSchoolInvite,\n countActiveAdmins,\n createSchoolInvite,\n createSchoolWithAdmin,\n deleteSchoolClassRecord,\n findActiveSchoolAdminMembership,\n findPendingInviteByToken,\n findSchoolClass,\n findSchoolMembership,\n getSchoolById,\n getSchoolMemberDetail,\n getSchoolOverview,\n listActiveSchoolMemberships,\n listMemberClasses,\n listRecentSchoolMembers,\n listSchoolClasses,\n listSchoolInvites,\n listSchoolMembers,\n listUserSchoolMemberships,\n removeSchoolMembershipPreservingContent,\n revokeSchoolInvite,\n updateSchoolClassMembers,\n updateSchoolMembershipRole,\n updateSchoolRecord,\n upsertSchoolMembership,\n} from \"../models/school.js\";\n\nasync function requireSchoolAdmin(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 perform this action\",\n });\n }\n return membership;\n}\n\nasync function requireSchoolMember(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 are not a member of this school\",\n });\n }\n return membership;\n}\n\nexport async function getCurrentSchool(userId: string, schoolId?: string) {\n const memberships = await listUserSchoolMemberships(userId);\n const activeMembership = schoolId\n ? memberships.find((membership) => membership.schoolId === schoolId)\n : memberships[0];\n\n const activeSchool = activeMembership?.school\n ? {\n id: activeMembership.school.id,\n name: activeMembership.school.name,\n description: activeMembership.school.description ?? null,\n subdomain: activeMembership.school.subdomain ?? null,\n logoId: activeMembership.school.logoId ?? null,\n // The path is the GCS object key — the frontend resolves it to a\n // signed URL through trpc.file.getSignedUrl when needed.\n logoPath: activeMembership.school.logo?.path ?? null,\n logoType: activeMembership.school.logo?.type ?? null,\n }\n : null;\n\n return {\n activeSchool,\n activeRole: activeMembership?.role ?? null,\n memberships,\n };\n}\n\nexport async function createSchoolRecord(\n userId: string,\n input: {\n name: string;\n description?: string;\n subdomain?: string;\n logoId?: string;\n }\n) {\n const school = await createSchoolWithAdmin({\n userId,\n name: input.name,\n subdomain: input.subdomain,\n logoId: input.logoId,\n });\n\n if (input.description) {\n await updateSchoolRecord(school.id, { description: input.description });\n }\n\n return { school };\n}\n\nexport async function updateSchoolDetails(\n userId: string,\n input: {\n schoolId: string;\n name?: string;\n description?: string | null;\n subdomain?: string | null;\n logoId?: string | null;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const updated = await updateSchoolRecord(input.schoolId, {\n name: input.name,\n description: input.description,\n subdomain: input.subdomain,\n logoId: input.logoId,\n });\n return { school: updated };\n}\n\nexport async function getAdminOverview(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n const [school, recentMembers] = await Promise.all([\n getSchoolOverview(schoolId),\n listRecentSchoolMembers(schoolId),\n ]);\n if (!school) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"School not found\" });\n }\n\n const roleCounts = school.memberships.reduce(\n (counts, membership) => {\n counts[membership.role] += 1;\n return counts;\n },\n { ADMIN: 0, TEACHER: 0, STUDENT: 0 } satisfies Record<SchoolMembershipRole, number>\n );\n\n return {\n school: {\n id: school.id,\n name: school.name,\n subdomain: school.subdomain,\n counts: {\n classes: school._count.classes,\n members: school._count.memberships,\n pendingInvites: school._count.invites,\n ...roleCounts,\n },\n recentClasses: school.classes,\n recentInvites: school.invites,\n recentMembers,\n },\n };\n}\n\nexport async function listClasses(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { classes: await listSchoolClasses(schoolId) };\n}\n\nexport async function createSchoolClass(\n userId: string,\n input: {\n schoolId: string;\n name: string;\n section: string;\n subject: string;\n color?: string;\n symbol?: string | null;\n departmentId?: string;\n teachers?: string[];\n students?: string[];\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n if (input.departmentId) {\n const dept = await prisma.department.findUnique({\n where: { id: input.departmentId },\n select: { schoolId: true },\n });\n if (!dept || dept.schoolId !== input.schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Department does not belong to this institution\",\n });\n }\n }\n\n const createdClass = await prisma.class.create({\n data: {\n name: input.name,\n section: input.section,\n subject: input.subject,\n color: input.color,\n symbol: input.symbol,\n schoolId: input.schoolId,\n departmentId: input.departmentId,\n teachers: input.teachers?.length\n ? { connect: input.teachers.map((id) => ({ id })) }\n : undefined,\n students: input.students?.length\n ? { connect: input.students.map((id) => ({ id })) }\n : undefined,\n },\n include: { teachers: true, students: true },\n });\n\n return { class: createdClass };\n}\n\nexport async function listMembers(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { members: await listSchoolMembers(schoolId) };\n}\n\nexport async function addMember(\n userId: string,\n input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const membership = await upsertSchoolMembership({\n schoolId: input.schoolId,\n userId: input.memberUserId,\n role: input.role,\n });\n return { membership };\n}\n\nexport async function updateMemberRole(\n userId: string,\n input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const current = await findSchoolMembership(input.schoolId, input.memberUserId);\n if (!current) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n if (current.role === \"ADMIN\" && input.role !== \"ADMIN\") {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount <= 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n const membership = await updateSchoolMembershipRole(\n input.schoolId,\n input.memberUserId,\n input.role\n );\n return { membership };\n}\n\nexport async function getMemberDetail(\n userId: string,\n input: { schoolId: string; memberUserId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const membership = await getSchoolMemberDetail(\n input.schoolId,\n input.memberUserId\n );\n if (!membership) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n const [teachingClasses, enrolledClasses] = await listMemberClasses(\n input.schoolId,\n input.memberUserId\n );\n\n const toClassSummary = (cls: (typeof teachingClasses)[number]) => ({\n id: cls.id,\n name: cls.name,\n section: cls.section,\n subject: cls.subject,\n color: cls.color,\n teacherCount: cls._count.teachers,\n studentCount: cls._count.students,\n });\n\n return {\n membership,\n teachingClasses: teachingClasses.map(toClassSummary),\n enrolledClasses: enrolledClasses.map(toClassSummary),\n };\n}\n\nexport async function bulkUpdateMemberRoles(\n userId: string,\n input: {\n schoolId: string;\n memberUserIds: string[];\n role: SchoolMembershipRole;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const memberships = await listActiveSchoolMemberships(\n input.schoolId,\n input.memberUserIds\n );\n if (memberships.length === 0) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"No members found\" });\n }\n\n if (input.role !== \"ADMIN\") {\n const demotedAdmins = memberships.filter((m) => m.role === \"ADMIN\").length;\n if (demotedAdmins > 0) {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount - demotedAdmins < 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n }\n\n await prisma.schoolMembership.updateMany({\n where: {\n schoolId: input.schoolId,\n userId: { in: memberships.map((m) => m.userId) },\n status: \"ACTIVE\",\n },\n data: { role: input.role },\n });\n return { updatedCount: memberships.length };\n}\n\nexport async function bulkRemoveMembers(\n userId: string,\n input: { schoolId: string; memberUserIds: string[] }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const targetIds = input.memberUserIds.filter((id) => id !== userId);\n const memberships = await listActiveSchoolMemberships(\n input.schoolId,\n targetIds\n );\n if (memberships.length === 0) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"No members found\" });\n }\n\n const removedAdmins = memberships.filter((m) => m.role === \"ADMIN\").length;\n if (removedAdmins > 0) {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount - removedAdmins < 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n for (const membership of memberships) {\n await removeSchoolMembershipPreservingContent(\n input.schoolId,\n membership.userId\n );\n }\n return { removedCount: memberships.length };\n}\n\nexport async function deleteSchoolClass(\n userId: string,\n input: { schoolId: string; classId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const cls = await findSchoolClass(input.schoolId, input.classId);\n if (!cls) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Class not found\" });\n }\n await deleteSchoolClassRecord(input.schoolId, input.classId);\n return { deletedClass: { id: input.classId } };\n}\n\nexport async function updateClassMembers(\n userId: string,\n input: {\n schoolId: string;\n classId: string;\n addTeacherIds?: string[];\n removeTeacherIds?: string[];\n addStudentIds?: string[];\n removeStudentIds?: string[];\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const cls = await findSchoolClass(input.schoolId, input.classId);\n if (!cls) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Class not found\" });\n }\n\n const addTeacherIds = input.addTeacherIds ?? [];\n const addStudentIds = input.addStudentIds ?? [];\n const addedIds = [...addTeacherIds, ...addStudentIds];\n if (addedIds.length > 0) {\n const memberships = await listActiveSchoolMemberships(\n input.schoolId,\n addedIds\n );\n const activeIds = new Set(memberships.map((m) => m.userId));\n if (addedIds.some((id) => !activeIds.has(id))) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"All added users must be active members of this school\",\n });\n }\n }\n\n const updated = await updateSchoolClassMembers(input.classId, {\n addTeacherIds,\n removeTeacherIds: input.removeTeacherIds ?? [],\n addStudentIds,\n removeStudentIds: input.removeStudentIds ?? [],\n });\n return { class: updated };\n}\n\nexport async function removeMember(\n userId: string,\n input: { schoolId: string; memberUserId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const current = await findSchoolMembership(input.schoolId, input.memberUserId);\n if (!current) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n if (current.role === \"ADMIN\" && current.status === \"ACTIVE\") {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount <= 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n await removeSchoolMembershipPreservingContent(input.schoolId, input.memberUserId);\n return { success: true };\n}\n\nexport async function listInvites(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { invites: await listSchoolInvites(schoolId) };\n}\n\n/**\n * Issue a direct-upload URL for a school-level asset (e.g. logo). The file\n * is created unattached and is owned by the requester until they associate\n * it via school.create or school.update.\n */\nexport async function getSchoolAssetUploadUrl(\n userId: string,\n input: { fileName: string; fileType: string; fileSize: number }\n) {\n const { createDirectUploadFiles } = await import(\"../lib/fileUpload.js\");\n const [uploadFile] = await createDirectUploadFiles(\n [\n {\n name: input.fileName,\n type: input.fileType,\n size: input.fileSize,\n },\n ],\n userId\n );\n return uploadFile;\n}\n\nexport async function confirmSchoolAssetUpload(\n userId: string,\n fileId: string,\n uploadSuccess: boolean\n) {\n const { confirmDirectUpload } = await import(\"../lib/fileUpload.js\");\n await confirmDirectUpload(fileId, uploadSuccess);\n return { success: true };\n}\n\n/**\n * Lightweight ID-only listing used to mask external user names in the UI.\n * Any active institution member can fetch this.\n */\nexport async function listMemberIds(userId: string, schoolId: string) {\n await requireSchoolMember(schoolId, userId);\n const rows = await prisma.schoolMembership.findMany({\n where: { schoolId, status: \"ACTIVE\" },\n select: { userId: true },\n });\n return rows.map((r) => r.userId);\n}\n\n/** Search active institution members by username, displayName, or email. */\nexport async function searchMembers(\n userId: string,\n schoolId: string,\n query: string,\n limit = 10,\n role?: \"ADMIN\" | \"TEACHER\" | \"STUDENT\"\n) {\n await requireSchoolMember(schoolId, userId);\n const trimmed = query.trim();\n if (!trimmed) return [];\n return prisma.user.findMany({\n where: {\n id: { not: userId },\n schoolMemberships: {\n some: {\n schoolId,\n status: \"ACTIVE\",\n ...(role ? { role } : {}),\n },\n },\n OR: [\n { username: { contains: trimmed, mode: \"insensitive\" } },\n { email: { contains: trimmed, mode: \"insensitive\" } },\n {\n profile: {\n displayName: { contains: trimmed, mode: \"insensitive\" },\n },\n },\n ],\n },\n take: limit,\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n schoolMemberships: {\n where: { schoolId, status: \"ACTIVE\" },\n select: { role: true },\n },\n },\n orderBy: { username: \"asc\" },\n });\n}\n\n/**\n * Combined student timeline: calendar events + assignments + attendance.\n * Visible to school admins (any student) and to teachers who share at least\n * one class with the student.\n */\nexport async function getStudentTimeline(\n userId: string,\n input: {\n schoolId: string;\n studentId: string;\n from?: Date;\n to?: Date;\n }\n) {\n const isAdmin = await findActiveSchoolAdminMembership(\n input.schoolId,\n userId\n );\n\n // Permission: admin OR shares a class.\n if (!isAdmin) {\n const sharedClass = await prisma.class.findFirst({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: userId } },\n students: { some: { id: input.studentId } },\n },\n select: { id: true },\n });\n if (!sharedClass) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't share a class with this student\",\n });\n }\n }\n\n // Make sure student is in the institution.\n const studentMembership = await prisma.schoolMembership.findFirst({\n where: { schoolId: input.schoolId, userId: input.studentId, status: \"ACTIVE\" },\n select: { role: true, user: { select: { id: true, username: true, profile: { select: { displayName: true, profilePicture: true } } } } },\n });\n if (!studentMembership) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Student is not in this institution\",\n });\n }\n\n const range = {\n ...(input.from ? { gte: input.from } : {}),\n ...(input.to ? { lte: input.to } : {}),\n };\n const hasRange = Object.keys(range).length > 0;\n\n const [events, assignments, attendance] = await Promise.all([\n prisma.event.findMany({\n where: {\n userId: input.studentId,\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.assignment.findMany({\n where: {\n class: {\n students: { some: { id: input.studentId } },\n },\n template: false,\n ...(hasRange ? { dueDate: range } : {}),\n },\n select: {\n id: true,\n title: true,\n dueDate: true,\n type: true,\n graded: true,\n maxGrade: true,\n weight: true,\n class: {\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n },\n },\n submissions: {\n where: { studentId: input.studentId },\n select: {\n id: true,\n submitted: true,\n submittedAt: true,\n returned: true,\n gradeReceived: true,\n },\n },\n },\n orderBy: { dueDate: \"asc\" },\n }),\n prisma.attendance.findMany({\n where: {\n OR: [\n { present: { some: { id: input.studentId } } },\n { late: { some: { id: input.studentId } } },\n { absent: { some: { id: input.studentId } } },\n ],\n ...(hasRange ? { date: range } : {}),\n },\n select: {\n id: true,\n date: true,\n class: { select: { id: true, name: true, color: true } },\n present: { where: { id: input.studentId }, select: { id: true } },\n late: { where: { id: input.studentId }, select: { id: true } },\n absent: { where: { id: input.studentId }, select: { id: true } },\n },\n orderBy: { date: \"asc\" },\n }),\n ]);\n\n const attendanceShaped = attendance.map((record) => ({\n id: record.id,\n date: record.date,\n class: record.class,\n status: record.present.length\n ? (\"PRESENT\" as const)\n : record.late.length\n ? (\"LATE\" as const)\n : (\"ABSENT\" as const),\n }));\n\n return {\n student: studentMembership.user,\n events,\n assignments,\n attendance: attendanceShaped,\n };\n}\n\n/**\n * Role-aware overview used by `/view/[userId]`.\n *\n * - For STUDENT members it returns the same timeline as `getStudentTimeline`\n * (events, assignments, attendance) so teachers/admins can audit progress.\n * - For TEACHER/ADMIN members it returns their teaching agenda: every event in\n * a class they teach plus their personal events, alongside the classes they\n * run with enrolment counts.\n *\n * Permissions:\n * - School admins can view anyone in the institution.\n * - A teacher can view a STUDENT they share a class with.\n * - A teacher/admin can always view their own overview.\n */\nexport async function getMemberTimeline(\n userId: string,\n input: {\n schoolId: string;\n memberId: string;\n from?: Date;\n to?: Date;\n }\n) {\n const callerIsAdmin = Boolean(\n await findActiveSchoolAdminMembership(input.schoolId, userId)\n );\n\n const membership = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: input.schoolId,\n userId: input.memberId,\n status: \"ACTIVE\",\n },\n select: {\n role: true,\n user: {\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true, profilePicture: true } },\n },\n },\n },\n });\n if (!membership) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"This person is not in this institution\",\n });\n }\n\n const range = {\n ...(input.from ? { gte: input.from } : {}),\n ...(input.to ? { lte: input.to } : {}),\n };\n const hasRange = Object.keys(range).length > 0;\n\n if (membership.role === \"STUDENT\") {\n if (!callerIsAdmin) {\n const sharedClass = await prisma.class.findFirst({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: userId } },\n students: { some: { id: input.memberId } },\n },\n select: { id: true },\n });\n if (!sharedClass) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't share a class with this student\",\n });\n }\n }\n\n const [events, assignments, attendance] = await Promise.all([\n prisma.event.findMany({\n where: {\n userId: input.memberId,\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.assignment.findMany({\n where: {\n class: { students: { some: { id: input.memberId } } },\n template: false,\n ...(hasRange ? { dueDate: range } : {}),\n },\n select: {\n id: true,\n title: true,\n dueDate: true,\n type: true,\n graded: true,\n maxGrade: true,\n weight: true,\n class: {\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n },\n },\n submissions: {\n where: { studentId: input.memberId },\n select: {\n id: true,\n submitted: true,\n submittedAt: true,\n returned: true,\n gradeReceived: true,\n },\n },\n },\n orderBy: { dueDate: \"asc\" },\n }),\n prisma.attendance.findMany({\n where: {\n OR: [\n { present: { some: { id: input.memberId } } },\n { late: { some: { id: input.memberId } } },\n { absent: { some: { id: input.memberId } } },\n ],\n ...(hasRange ? { date: range } : {}),\n },\n select: {\n id: true,\n date: true,\n class: { select: { id: true, name: true, color: true } },\n present: { where: { id: input.memberId }, select: { id: true } },\n late: { where: { id: input.memberId }, select: { id: true } },\n absent: { where: { id: input.memberId }, select: { id: true } },\n },\n orderBy: { date: \"asc\" },\n }),\n ]);\n\n const attendanceShaped = attendance.map((record) => ({\n id: record.id,\n date: record.date,\n class: record.class,\n status: record.present.length\n ? (\"PRESENT\" as const)\n : record.late.length\n ? (\"LATE\" as const)\n : (\"ABSENT\" as const),\n }));\n\n return {\n role: \"STUDENT\" as const,\n member: membership.user,\n events,\n assignments,\n attendance: attendanceShaped,\n };\n }\n\n // TEACHER or ADMIN: only admins (or the member themselves) may view.\n if (!callerIsAdmin && userId !== input.memberId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can view this member\",\n });\n }\n\n const [events, classes] = await Promise.all([\n prisma.event.findMany({\n where: {\n OR: [\n { userId: input.memberId },\n { class: { teachers: { some: { id: input.memberId } } } },\n ],\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.class.findMany({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: input.memberId } },\n },\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n _count: { select: { students: true } },\n },\n orderBy: { name: \"asc\" },\n }),\n ]);\n\n return {\n role: membership.role as \"TEACHER\" | \"ADMIN\",\n member: membership.user,\n events,\n classes: classes.map((c) => ({\n id: c.id,\n name: c.name,\n section: c.section,\n subject: c.subject,\n color: c.color,\n studentCount: c._count.students,\n })),\n };\n}\n\nexport async function createInvite(\n userId: string,\n input: {\n schoolId: string;\n email: string;\n role: SchoolMembershipRole;\n /** Optional display name set by the inviting admin. If omitted the user\n * picks their own when they complete the password reset flow. */\n displayName?: string;\n /** Optional username; if omitted we generate a friendly random one. */\n username?: string;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n // The institution invite flow is \"new account only\": if the email is\n // already in use we reject. This keeps the join experience simple — every\n // new institution member always lands on a password reset link.\n const existingUser = await findUserByEmail(input.email);\n if (existingUser) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message:\n \"An account with this email already exists. Ask them to log in and you can add them via search.\",\n });\n }\n\n let username: string;\n if (input.username) {\n const taken = await findUserByUsername(input.username);\n if (taken) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message: \"Username already taken\",\n });\n }\n username = input.username;\n } else {\n username = await generateUniqueUsername(async (candidate) => {\n const existing = await findUserByUsername(candidate);\n return Boolean(existing);\n });\n }\n\n const placeholderPassword = await hash(uuidv4(), 10);\n const user = await createUser({\n username,\n email: input.email,\n password: placeholderPassword,\n verified: true,\n });\n const createdUser = { id: user.id, username: user.username };\n\n if (input.displayName) {\n await upsertUserProfile(user.id, { displayName: input.displayName });\n }\n\n const resetSession = await createSession({\n id: uuidv4(),\n type: SessionType.PASSWORD_RESET,\n userId: user.id,\n expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),\n });\n const passwordResetToken = resetSession.id;\n\n const token = uuidv4();\n const invite = await createSchoolInvite({\n schoolId: input.schoolId,\n invitedById: userId,\n email: input.email,\n role: input.role,\n token,\n expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),\n });\n\n await acceptSchoolInvite(invite.id, createdUser.id);\n\n const passwordResetUrl = `${env.NEXT_PUBLIC_APP_URL}/reset-password/${passwordResetToken}`;\n const emailLines = [\n `You've been added to ${invite.school.name} on Studious.`,\n \"\",\n `We created an account for you with the username \"${createdUser.username}\".`,\n input.displayName\n ? `Your name is set to \"${input.displayName}\" — you can change it after signing in.`\n : `You can set your name once you sign in for the first time.`,\n \"\",\n `Set your password to get started: ${passwordResetUrl}`,\n ];\n\n try {\n await sendMail({\n from: \"hello@studious.sh\",\n to: input.email,\n subject: `Join ${invite.school.name} on Studious`,\n text: emailLines.join(\"\\n\"),\n });\n } catch (err) {\n logger.error(\"Failed to send school invite email\", {\n schoolId: input.schoolId,\n email: input.email,\n err,\n });\n }\n\n return {\n invite,\n createdUser,\n passwordResetUrl,\n };\n}\n\nexport async function revokeInvite(\n userId: string,\n input: { schoolId: string; inviteId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n return { invite: await revokeSchoolInvite(input.inviteId, input.schoolId) };\n}\n\nexport async function getInvite(token: string) {\n const invite = await findPendingInviteByToken(token);\n if (!invite || invite.status !== \"PENDING\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Invite not found\" });\n }\n if (invite.expiresAt < new Date()) {\n throw new TRPCError({ code: \"UNAUTHORIZED\", message: \"Invite expired\" });\n }\n return {\n invite: {\n id: invite.id,\n email: invite.email,\n role: invite.role,\n school: invite.school,\n expiresAt: invite.expiresAt,\n },\n };\n}\n\nexport async function acceptInvite(userId: string, token: string) {\n const invite = await findPendingInviteByToken(token);\n if (!invite || invite.status !== \"PENDING\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Invite not found\" });\n }\n if (invite.expiresAt < new Date()) {\n throw new TRPCError({ code: \"UNAUTHORIZED\", message: \"Invite expired\" });\n }\n\n const user = await findUserById(userId);\n if (!user) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"User not found\" });\n }\n if (user.email.toLowerCase() !== invite.email.toLowerCase()) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"This invite was sent to a different account\",\n });\n }\n\n const membership = await acceptSchoolInvite(invite.id, userId);\n return { membership };\n}\n"],"names":[],"mappings":"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","debug_id":"70890b65-7dda-51a3-925f-31c75be34a33"}
1
+ {"version":3,"file":"school.js","sources":["services/school.ts"],"sourceRoot":"/","sourcesContent":["/**\n * School service - school admin workflow, memberships, and invites.\n */\nimport { SchoolMembershipRole, SessionType } from \"@prisma/client\";\nimport { TRPCError } from \"@trpc/server\";\nimport { hash } from \"bcryptjs\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { env } from \"../lib/config/env.js\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { sendMail } from \"../utils/email.js\";\nimport { generateUniqueUsername } from \"../utils/generateUsername.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n createSession,\n createUser,\n findUserByEmail,\n findUserById,\n findUserByUsername,\n} from \"../models/auth.js\";\nimport { upsertUserProfile } from \"../models/user.js\";\nimport {\n acceptSchoolInvite,\n countActiveAdmins,\n createSchoolInvite,\n createSchoolWithAdmin,\n deleteSchoolClassRecord,\n findActiveSchoolAdminMembership,\n findPendingInviteByToken,\n findSchoolClass,\n findSchoolMembership,\n getSchoolById,\n getSchoolMemberDetail,\n getSchoolOverview,\n listActiveSchoolMemberships,\n listMemberClasses,\n listRecentSchoolMembers,\n listSchoolClasses,\n listSchoolInvites,\n listSchoolMembers,\n listUserSchoolMemberships,\n removeSchoolMembershipPreservingContent,\n revokeSchoolInvite,\n updateSchoolClassMembers,\n updateSchoolMembershipRole,\n updateSchoolRecord,\n upsertSchoolMembership,\n} from \"../models/school.js\";\n\nasync function requireSchoolAdmin(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 perform this action\",\n });\n }\n return membership;\n}\n\nasync function requireSchoolMember(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 are not a member of this school\",\n });\n }\n return membership;\n}\n\nexport async function getCurrentSchool(userId: string, schoolId?: string) {\n const memberships = await listUserSchoolMemberships(userId);\n const activeMembership = schoolId\n ? memberships.find((membership) => membership.schoolId === schoolId)\n : memberships[0];\n\n const activeSchool = activeMembership?.school\n ? {\n id: activeMembership.school.id,\n name: activeMembership.school.name,\n description: activeMembership.school.description ?? null,\n subdomain: activeMembership.school.subdomain ?? null,\n logoId: activeMembership.school.logoId ?? null,\n // The path is the GCS object key — the frontend resolves it to a\n // signed URL through trpc.file.getSignedUrl when needed.\n logoPath: activeMembership.school.logo?.path ?? null,\n logoType: activeMembership.school.logo?.type ?? null,\n letterheadFileId: activeMembership.school.letterheadFileId ?? null,\n letterheadPath: activeMembership.school.letterhead?.path ?? null,\n letterheadType: activeMembership.school.letterhead?.type ?? null,\n }\n : null;\n\n return {\n activeSchool,\n activeRole: activeMembership?.role ?? null,\n memberships,\n };\n}\n\nexport async function createSchoolRecord(\n userId: string,\n input: {\n name: string;\n description?: string;\n subdomain?: string;\n logoId?: string;\n }\n) {\n const school = await createSchoolWithAdmin({\n userId,\n name: input.name,\n subdomain: input.subdomain,\n logoId: input.logoId,\n });\n\n if (input.description) {\n await updateSchoolRecord(school.id, { description: input.description });\n }\n\n return { school };\n}\n\nexport async function updateSchoolDetails(\n userId: string,\n input: {\n schoolId: string;\n name?: string;\n description?: string | null;\n subdomain?: string | null;\n logoId?: string | null;\n letterheadFileId?: string | null;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const brandingFileIds = [input.logoId, input.letterheadFileId].filter(\n (id): id is string => typeof id === \"string\"\n );\n if (brandingFileIds.length) {\n const accessible = await prisma.file.findMany({\n where: {\n id: { in: brandingFileIds },\n OR: [\n { userId },\n { folder: { schoolStorageId: input.schoolId } },\n ],\n },\n select: { id: true },\n });\n const accessibleIds = new Set(accessible.map((f) => f.id));\n if (brandingFileIds.some((id) => !accessibleIds.has(id))) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"File does not belong to this school\",\n });\n }\n }\n const updated = await updateSchoolRecord(input.schoolId, {\n name: input.name,\n description: input.description,\n subdomain: input.subdomain,\n logoId: input.logoId,\n letterheadFileId: input.letterheadFileId,\n });\n return { school: updated };\n}\n\nexport async function getAdminOverview(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n const [school, recentMembers] = await Promise.all([\n getSchoolOverview(schoolId),\n listRecentSchoolMembers(schoolId),\n ]);\n if (!school) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"School not found\" });\n }\n\n const roleCounts = school.memberships.reduce(\n (counts, membership) => {\n counts[membership.role] += 1;\n return counts;\n },\n {\n ADMIN: 0,\n TEACHER: 0,\n STUDENT: 0,\n ACCOUNTANT: 0,\n PARENT: 0,\n } satisfies Record<SchoolMembershipRole, number>\n );\n\n return {\n school: {\n id: school.id,\n name: school.name,\n subdomain: school.subdomain,\n counts: {\n classes: school._count.classes,\n members: school._count.memberships,\n pendingInvites: school._count.invites,\n ...roleCounts,\n },\n recentClasses: school.classes,\n recentInvites: school.invites,\n recentMembers,\n },\n };\n}\n\nexport async function listClasses(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { classes: await listSchoolClasses(schoolId) };\n}\n\nexport async function createSchoolClass(\n userId: string,\n input: {\n schoolId: string;\n name: string;\n section: string;\n subject: string;\n color?: string;\n symbol?: string | null;\n departmentId?: string;\n teachers?: string[];\n students?: string[];\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n if (input.departmentId) {\n const dept = await prisma.department.findUnique({\n where: { id: input.departmentId },\n select: { schoolId: true },\n });\n if (!dept || dept.schoolId !== input.schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Department does not belong to this institution\",\n });\n }\n }\n\n const createdClass = await prisma.class.create({\n data: {\n name: input.name,\n section: input.section,\n subject: input.subject,\n color: input.color,\n symbol: input.symbol,\n schoolId: input.schoolId,\n departmentId: input.departmentId,\n teachers: input.teachers?.length\n ? { connect: input.teachers.map((id) => ({ id })) }\n : undefined,\n students: input.students?.length\n ? { connect: input.students.map((id) => ({ id })) }\n : undefined,\n },\n include: { teachers: true, students: true },\n });\n\n return { class: createdClass };\n}\n\nexport async function listMembers(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { members: await listSchoolMembers(schoolId) };\n}\n\nexport async function addMember(\n userId: string,\n input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const membership = await upsertSchoolMembership({\n schoolId: input.schoolId,\n userId: input.memberUserId,\n role: input.role,\n });\n return { membership };\n}\n\nexport async function updateMemberRole(\n userId: string,\n input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const current = await findSchoolMembership(input.schoolId, input.memberUserId);\n if (!current) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n if (current.role === \"ADMIN\" && input.role !== \"ADMIN\") {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount <= 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n const membership = await updateSchoolMembershipRole(\n input.schoolId,\n input.memberUserId,\n input.role\n );\n return { membership };\n}\n\nexport async function getMemberDetail(\n userId: string,\n input: { schoolId: string; memberUserId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const membership = await getSchoolMemberDetail(\n input.schoolId,\n input.memberUserId\n );\n if (!membership) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n const [teachingClasses, enrolledClasses] = await listMemberClasses(\n input.schoolId,\n input.memberUserId\n );\n\n const toClassSummary = (cls: (typeof teachingClasses)[number]) => ({\n id: cls.id,\n name: cls.name,\n section: cls.section,\n subject: cls.subject,\n color: cls.color,\n teacherCount: cls._count.teachers,\n studentCount: cls._count.students,\n });\n\n return {\n membership,\n teachingClasses: teachingClasses.map(toClassSummary),\n enrolledClasses: enrolledClasses.map(toClassSummary),\n };\n}\n\nexport async function bulkUpdateMemberRoles(\n userId: string,\n input: {\n schoolId: string;\n memberUserIds: string[];\n role: SchoolMembershipRole;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const memberships = await listActiveSchoolMemberships(\n input.schoolId,\n input.memberUserIds\n );\n if (memberships.length === 0) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"No members found\" });\n }\n\n if (input.role !== \"ADMIN\") {\n const demotedAdmins = memberships.filter((m) => m.role === \"ADMIN\").length;\n if (demotedAdmins > 0) {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount - demotedAdmins < 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n }\n\n await prisma.schoolMembership.updateMany({\n where: {\n schoolId: input.schoolId,\n userId: { in: memberships.map((m) => m.userId) },\n status: \"ACTIVE\",\n },\n data: { role: input.role },\n });\n return { updatedCount: memberships.length };\n}\n\nexport async function bulkRemoveMembers(\n userId: string,\n input: { schoolId: string; memberUserIds: string[] }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const targetIds = input.memberUserIds.filter((id) => id !== userId);\n const memberships = await listActiveSchoolMemberships(\n input.schoolId,\n targetIds\n );\n if (memberships.length === 0) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"No members found\" });\n }\n\n const removedAdmins = memberships.filter((m) => m.role === \"ADMIN\").length;\n if (removedAdmins > 0) {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount - removedAdmins < 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n for (const membership of memberships) {\n await removeSchoolMembershipPreservingContent(\n input.schoolId,\n membership.userId\n );\n }\n return { removedCount: memberships.length };\n}\n\nexport async function deleteSchoolClass(\n userId: string,\n input: { schoolId: string; classId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const cls = await findSchoolClass(input.schoolId, input.classId);\n if (!cls) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Class not found\" });\n }\n await deleteSchoolClassRecord(input.schoolId, input.classId);\n return { deletedClass: { id: input.classId } };\n}\n\nexport async function updateClassMembers(\n userId: string,\n input: {\n schoolId: string;\n classId: string;\n addTeacherIds?: string[];\n removeTeacherIds?: string[];\n addStudentIds?: string[];\n removeStudentIds?: string[];\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const cls = await findSchoolClass(input.schoolId, input.classId);\n if (!cls) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Class not found\" });\n }\n\n const addTeacherIds = input.addTeacherIds ?? [];\n const addStudentIds = input.addStudentIds ?? [];\n const addedIds = [...addTeacherIds, ...addStudentIds];\n if (addedIds.length > 0) {\n const memberships = await listActiveSchoolMemberships(\n input.schoolId,\n addedIds\n );\n const activeIds = new Set(memberships.map((m) => m.userId));\n if (addedIds.some((id) => !activeIds.has(id))) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"All added users must be active members of this school\",\n });\n }\n }\n\n const updated = await updateSchoolClassMembers(input.classId, {\n addTeacherIds,\n removeTeacherIds: input.removeTeacherIds ?? [],\n addStudentIds,\n removeStudentIds: input.removeStudentIds ?? [],\n });\n return { class: updated };\n}\n\nexport async function removeMember(\n userId: string,\n input: { schoolId: string; memberUserId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const current = await findSchoolMembership(input.schoolId, input.memberUserId);\n if (!current) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n if (current.role === \"ADMIN\" && current.status === \"ACTIVE\") {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount <= 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n await removeSchoolMembershipPreservingContent(input.schoolId, input.memberUserId);\n return { success: true };\n}\n\nexport async function listInvites(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { invites: await listSchoolInvites(schoolId) };\n}\n\n/**\n * Issue a direct-upload URL for a school-level asset (e.g. logo). The file\n * is created unattached and is owned by the requester until they associate\n * it via school.create or school.update.\n */\nexport async function getSchoolAssetUploadUrl(\n userId: string,\n input: { fileName: string; fileType: string; fileSize: number }\n) {\n const { createDirectUploadFiles } = await import(\"../lib/fileUpload.js\");\n const [uploadFile] = await createDirectUploadFiles(\n [\n {\n name: input.fileName,\n type: input.fileType,\n size: input.fileSize,\n },\n ],\n userId\n );\n return uploadFile;\n}\n\nexport async function confirmSchoolAssetUpload(\n userId: string,\n fileId: string,\n uploadSuccess: boolean\n) {\n const { confirmDirectUpload } = await import(\"../lib/fileUpload.js\");\n await confirmDirectUpload(fileId, uploadSuccess);\n return { success: true };\n}\n\n/**\n * Lightweight ID-only listing used to mask external user names in the UI.\n * Any active institution member can fetch this.\n */\nexport async function listMemberIds(userId: string, schoolId: string) {\n await requireSchoolMember(schoolId, userId);\n const rows = await prisma.schoolMembership.findMany({\n where: { schoolId, status: \"ACTIVE\" },\n select: { userId: true },\n });\n return rows.map((r) => r.userId);\n}\n\n/** Search active institution members by username, displayName, or email. */\nexport async function searchMembers(\n userId: string,\n schoolId: string,\n query: string,\n limit = 10,\n role?: SchoolMembershipRole\n) {\n await requireSchoolMember(schoolId, userId);\n const trimmed = query.trim();\n if (!trimmed) return [];\n return prisma.user.findMany({\n where: {\n id: { not: userId },\n schoolMemberships: {\n some: {\n schoolId,\n status: \"ACTIVE\",\n ...(role ? { role } : {}),\n },\n },\n OR: [\n { username: { contains: trimmed, mode: \"insensitive\" } },\n { email: { contains: trimmed, mode: \"insensitive\" } },\n {\n profile: {\n displayName: { contains: trimmed, mode: \"insensitive\" },\n },\n },\n ],\n },\n take: limit,\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n schoolMemberships: {\n where: { schoolId, status: \"ACTIVE\" },\n select: { role: true },\n },\n },\n orderBy: { username: \"asc\" },\n });\n}\n\n/**\n * Combined student timeline: calendar events + assignments + attendance.\n * Visible to school admins (any student) and to teachers who share at least\n * one class with the student.\n */\nexport async function getStudentTimeline(\n userId: string,\n input: {\n schoolId: string;\n studentId: string;\n from?: Date;\n to?: Date;\n }\n) {\n const isAdmin = await findActiveSchoolAdminMembership(\n input.schoolId,\n userId\n );\n\n // Permission: admin OR shares a class.\n if (!isAdmin) {\n const sharedClass = await prisma.class.findFirst({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: userId } },\n students: { some: { id: input.studentId } },\n },\n select: { id: true },\n });\n if (!sharedClass) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't share a class with this student\",\n });\n }\n }\n\n // Make sure student is in the institution.\n const studentMembership = await prisma.schoolMembership.findFirst({\n where: { schoolId: input.schoolId, userId: input.studentId, status: \"ACTIVE\" },\n select: { role: true, user: { select: { id: true, username: true, profile: { select: { displayName: true, profilePicture: true } } } } },\n });\n if (!studentMembership) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Student is not in this institution\",\n });\n }\n\n // Default to the last 12 months when no range is given, to bound reads.\n const defaultFrom = new Date();\n defaultFrom.setFullYear(defaultFrom.getFullYear() - 1);\n const range = {\n gte: input.from ?? defaultFrom,\n ...(input.to ? { lte: input.to } : {}),\n };\n const [events, assignments, attendance] = await Promise.all([\n prisma.event.findMany({\n where: {\n userId: input.studentId,\n startTime: range,\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.assignment.findMany({\n where: {\n class: {\n students: { some: { id: input.studentId } },\n },\n template: false,\n dueDate: range,\n },\n select: {\n id: true,\n title: true,\n dueDate: true,\n type: true,\n graded: true,\n maxGrade: true,\n weight: true,\n class: {\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n },\n },\n submissions: {\n where: { studentId: input.studentId },\n select: {\n id: true,\n submitted: true,\n submittedAt: true,\n returned: true,\n gradeReceived: true,\n },\n },\n },\n orderBy: { dueDate: \"asc\" },\n }),\n prisma.attendanceRecord.findMany({\n where: {\n studentId: input.studentId,\n attendance: {\n class: { schoolId: input.schoolId },\n date: range,\n },\n },\n select: {\n id: true,\n status: true,\n note: true,\n excusedByExcusalId: true,\n attendance: {\n select: {\n id: true,\n date: true,\n class: { select: { id: true, name: true, color: true } },\n },\n },\n excusedByExcusal: { select: { id: true, reason: true } },\n },\n orderBy: { attendance: { date: \"asc\" } },\n }),\n ]);\n\n const attendanceShaped = attendance.map((record) => ({\n id: record.attendance.id,\n recordId: record.id,\n date: record.attendance.date,\n class: record.attendance.class,\n status: record.status,\n note: record.note,\n lockedFromExcusal: Boolean(record.excusedByExcusalId),\n reason: record.excusedByExcusal?.reason ?? null,\n }));\n\n return {\n student: studentMembership.user,\n events,\n assignments,\n attendance: attendanceShaped,\n };\n}\n\n/**\n * Role-aware overview used by `/view/[userId]`.\n *\n * - For STUDENT members it returns the same timeline as `getStudentTimeline`\n * (events, assignments, attendance) so teachers/admins can audit progress.\n * - For TEACHER/ADMIN members it returns their teaching agenda: every event in\n * a class they teach plus their personal events, alongside the classes they\n * run with enrolment counts.\n *\n * Permissions:\n * - School admins can view anyone in the institution.\n * - A teacher can view a STUDENT they share a class with.\n * - A teacher/admin can always view their own overview.\n */\nexport async function getMemberTimeline(\n userId: string,\n input: {\n schoolId: string;\n memberId: string;\n from?: Date;\n to?: Date;\n }\n) {\n const callerIsAdmin = Boolean(\n await findActiveSchoolAdminMembership(input.schoolId, userId)\n );\n\n const membership = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: input.schoolId,\n userId: input.memberId,\n status: \"ACTIVE\",\n },\n select: {\n role: true,\n user: {\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true, profilePicture: true } },\n },\n },\n },\n });\n if (!membership) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"This person is not in this institution\",\n });\n }\n\n // Default to the last 12 months when no range is given, to bound reads.\n const defaultFrom = new Date();\n defaultFrom.setFullYear(defaultFrom.getFullYear() - 1);\n const range = {\n gte: input.from ?? defaultFrom,\n ...(input.to ? { lte: input.to } : {}),\n };\n\n if (membership.role === \"STUDENT\") {\n if (!callerIsAdmin) {\n const sharedClass = await prisma.class.findFirst({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: userId } },\n students: { some: { id: input.memberId } },\n },\n select: { id: true },\n });\n if (!sharedClass) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't share a class with this student\",\n });\n }\n }\n\n const [events, assignments, attendance] = await Promise.all([\n prisma.event.findMany({\n where: {\n userId: input.memberId,\n startTime: range,\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.assignment.findMany({\n where: {\n class: { students: { some: { id: input.memberId } } },\n template: false,\n dueDate: range,\n },\n select: {\n id: true,\n title: true,\n dueDate: true,\n type: true,\n graded: true,\n maxGrade: true,\n weight: true,\n class: {\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n },\n },\n submissions: {\n where: { studentId: input.memberId },\n select: {\n id: true,\n submitted: true,\n submittedAt: true,\n returned: true,\n gradeReceived: true,\n },\n },\n },\n orderBy: { dueDate: \"asc\" },\n }),\n prisma.attendanceRecord.findMany({\n where: {\n studentId: input.memberId,\n attendance: {\n class: { schoolId: input.schoolId },\n date: range,\n },\n },\n select: {\n id: true,\n status: true,\n note: true,\n excusedByExcusalId: true,\n attendance: {\n select: {\n id: true,\n date: true,\n class: { select: { id: true, name: true, color: true } },\n },\n },\n excusedByExcusal: { select: { id: true, reason: true } },\n },\n orderBy: { attendance: { date: \"asc\" } },\n }),\n ]);\n\n const attendanceShaped = attendance.map((record) => ({\n id: record.attendance.id,\n recordId: record.id,\n date: record.attendance.date,\n class: record.attendance.class,\n status: record.status,\n note: record.note,\n lockedFromExcusal: Boolean(record.excusedByExcusalId),\n reason: record.excusedByExcusal?.reason ?? null,\n }));\n\n return {\n role: \"STUDENT\" as const,\n member: membership.user,\n events,\n assignments,\n attendance: attendanceShaped,\n };\n }\n\n // TEACHER or ADMIN: only admins (or the member themselves) may view.\n if (!callerIsAdmin && userId !== input.memberId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can view this member\",\n });\n }\n\n const [events, classes] = await Promise.all([\n prisma.event.findMany({\n where: {\n OR: [\n { userId: input.memberId },\n { class: { teachers: { some: { id: input.memberId } } } },\n ],\n startTime: range,\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.class.findMany({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: input.memberId } },\n },\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n _count: { select: { students: true } },\n },\n orderBy: { name: \"asc\" },\n }),\n ]);\n\n return {\n role: membership.role as \"TEACHER\" | \"ADMIN\",\n member: membership.user,\n events,\n classes: classes.map((c) => ({\n id: c.id,\n name: c.name,\n section: c.section,\n subject: c.subject,\n color: c.color,\n studentCount: c._count.students,\n })),\n };\n}\n\nexport async function createInvite(\n userId: string,\n input: {\n schoolId: string;\n email: string;\n role: SchoolMembershipRole;\n /** Optional display name set by the inviting admin. If omitted the user\n * picks their own when they complete the password reset flow. */\n displayName?: string;\n /** Optional username; if omitted we generate a friendly random one. */\n username?: string;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n // The institution invite flow is \"new account only\": if the email is\n // already in use we reject. This keeps the join experience simple — every\n // new institution member always lands on a password reset link.\n const existingUser = await findUserByEmail(input.email);\n if (existingUser) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message:\n \"An account with this email already exists. Ask them to log in and you can add them via search.\",\n });\n }\n\n let username: string;\n if (input.username) {\n const taken = await findUserByUsername(input.username);\n if (taken) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message: \"Username already taken\",\n });\n }\n username = input.username;\n } else {\n username = await generateUniqueUsername(async (candidate) => {\n const existing = await findUserByUsername(candidate);\n return Boolean(existing);\n });\n }\n\n const placeholderPassword = await hash(uuidv4(), 10);\n const user = await createUser({\n username,\n email: input.email,\n password: placeholderPassword,\n verified: true,\n });\n const createdUser = { id: user.id, username: user.username };\n\n if (input.displayName) {\n await upsertUserProfile(user.id, { displayName: input.displayName });\n }\n\n const resetSession = await createSession({\n id: uuidv4(),\n type: SessionType.PASSWORD_RESET,\n userId: user.id,\n expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),\n });\n const passwordResetToken = resetSession.id;\n\n const token = uuidv4();\n const invite = await createSchoolInvite({\n schoolId: input.schoolId,\n invitedById: userId,\n email: input.email,\n role: input.role,\n token,\n expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),\n });\n\n await acceptSchoolInvite(invite.id, createdUser.id);\n\n const passwordResetUrl = `${env.NEXT_PUBLIC_APP_URL}/reset-password/${passwordResetToken}`;\n const emailLines = [\n `You've been added to ${invite.school.name} on Studious.`,\n \"\",\n `We created an account for you with the username \"${createdUser.username}\".`,\n input.displayName\n ? `Your name is set to \"${input.displayName}\" — you can change it after signing in.`\n : `You can set your name once you sign in for the first time.`,\n \"\",\n `Set your password to get started: ${passwordResetUrl}`,\n ];\n\n try {\n await sendMail({\n from: \"hello@studious.sh\",\n to: input.email,\n subject: `Join ${invite.school.name} on Studious`,\n text: emailLines.join(\"\\n\"),\n });\n } catch (err) {\n logger.error(\"Failed to send school invite email\", {\n schoolId: input.schoolId,\n email: input.email,\n err,\n });\n }\n\n return {\n invite,\n createdUser,\n passwordResetUrl,\n };\n}\n\nexport async function revokeInvite(\n userId: string,\n input: { schoolId: string; inviteId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n return { invite: await revokeSchoolInvite(input.inviteId, input.schoolId) };\n}\n\nexport async function getInvite(token: string) {\n const invite = await findPendingInviteByToken(token);\n if (!invite || invite.status !== \"PENDING\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Invite not found\" });\n }\n if (invite.expiresAt < new Date()) {\n throw new TRPCError({ code: \"UNAUTHORIZED\", message: \"Invite expired\" });\n }\n return {\n invite: {\n id: invite.id,\n email: invite.email,\n role: invite.role,\n school: invite.school,\n expiresAt: invite.expiresAt,\n },\n };\n}\n\nexport async function acceptInvite(userId: string, token: string) {\n const invite = await findPendingInviteByToken(token);\n if (!invite || invite.status !== \"PENDING\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Invite not found\" });\n }\n if (invite.expiresAt < new Date()) {\n throw new TRPCError({ code: \"UNAUTHORIZED\", message: \"Invite expired\" });\n }\n\n const user = await findUserById(userId);\n if (!user) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"User not found\" });\n }\n if (user.email.toLowerCase() !== invite.email.toLowerCase()) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"This invite was sent to a different account\",\n });\n }\n\n const membership = await acceptSchoolInvite(invite.id, userId);\n return { membership };\n}\n"],"names":[],"mappings":"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","debug_id":"7675f5a8-bfcb-53db-b66d-cdd4c8755f46"}
@@ -0,0 +1,34 @@
1
+ export type StudentCsvRowResult = {
2
+ ok: true;
3
+ row: number;
4
+ userId: string;
5
+ username: string;
6
+ email: string;
7
+ password: string;
8
+ displayName: string | null;
9
+ classId: string | null;
10
+ generatedUsername: boolean;
11
+ generatedPassword: boolean;
12
+ placeholderEmail: boolean;
13
+ } | {
14
+ ok: false;
15
+ row: number;
16
+ error: string;
17
+ raw?: string;
18
+ };
19
+ export declare function parseStudentCsv(csvText: string): {
20
+ headers: string[];
21
+ rows: Record<string, string>[];
22
+ };
23
+ export declare function importStudentsCsv(userId: string, input: {
24
+ schoolId: string;
25
+ csvText: string;
26
+ dryRun?: boolean;
27
+ }): Promise<{
28
+ dryRun: boolean;
29
+ created: number;
30
+ failed: number;
31
+ total: number;
32
+ results: StudentCsvRowResult[];
33
+ }>;
34
+ //# sourceMappingURL=studentImport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studentImport.d.ts","sourceRoot":"/","sources":["services/studentImport.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,mBAAmB,GAC3B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB,EAAE,OAAO,CAAC;CAC3B,GACD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAmDN,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CAChC,CAsBA;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE;;;;;;GAwK/D"}