@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
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Academic year / term service (C1) + student promotion (C2).
3
+ */
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]="d8dde89c-b5a2-5b31-be33-b365078aeaa2")}catch(e){}}();
6
+ import { TRPCError } from "@trpc/server";
7
+ import { prisma } from "../lib/prisma.js";
8
+ import { createAcademicTerm, createAcademicYear, deleteAcademicTerm, deleteAcademicYear, getAcademicYearById, getCurrentAcademicYear, listAcademicYears, updateAcademicTerm, updateAcademicYear, } from "../models/academicCalendar.js";
9
+ import { findActiveSchoolAdminMembership, findSchoolClass, listActiveSchoolMemberships, } from "../models/school.js";
10
+ async function requireSchoolAdmin(schoolId, userId) {
11
+ const membership = await findActiveSchoolAdminMembership(schoolId, userId);
12
+ if (!membership) {
13
+ throw new TRPCError({
14
+ code: "FORBIDDEN",
15
+ message: "Only school admins can perform this action",
16
+ });
17
+ }
18
+ return membership;
19
+ }
20
+ export async function listYears(userId, schoolId) {
21
+ await requireSchoolAdmin(schoolId, userId);
22
+ return { years: await listAcademicYears(schoolId) };
23
+ }
24
+ export async function getCurrentYear(userId, schoolId) {
25
+ await requireSchoolAdmin(schoolId, userId);
26
+ return { year: await getCurrentAcademicYear(schoolId) };
27
+ }
28
+ export async function createYear(userId, input) {
29
+ await requireSchoolAdmin(input.schoolId, userId);
30
+ if (input.endDate < input.startDate) {
31
+ throw new TRPCError({
32
+ code: "BAD_REQUEST",
33
+ message: "endDate must be on or after startDate",
34
+ });
35
+ }
36
+ try {
37
+ const year = await createAcademicYear(input);
38
+ return { year };
39
+ }
40
+ catch (err) {
41
+ if (err &&
42
+ typeof err === "object" &&
43
+ "code" in err &&
44
+ err.code === "P2002") {
45
+ throw new TRPCError({
46
+ code: "CONFLICT",
47
+ message: "An academic year with this name already exists",
48
+ });
49
+ }
50
+ throw err;
51
+ }
52
+ }
53
+ export async function updateYear(userId, input) {
54
+ await requireSchoolAdmin(input.schoolId, userId);
55
+ if (input.startDate !== undefined || input.endDate !== undefined) {
56
+ const existing = await getAcademicYearById(input.yearId, input.schoolId);
57
+ if (!existing) {
58
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic year not found" });
59
+ }
60
+ const nextStart = input.startDate ?? existing.startDate;
61
+ const nextEnd = input.endDate ?? existing.endDate;
62
+ if (nextEnd < nextStart) {
63
+ throw new TRPCError({
64
+ code: "BAD_REQUEST",
65
+ message: "endDate must be on or after startDate",
66
+ });
67
+ }
68
+ }
69
+ const year = await updateAcademicYear(input.yearId, input.schoolId, {
70
+ name: input.name,
71
+ startDate: input.startDate,
72
+ endDate: input.endDate,
73
+ isCurrent: input.isCurrent,
74
+ });
75
+ if (!year) {
76
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic year not found" });
77
+ }
78
+ return { year };
79
+ }
80
+ export async function removeYear(userId, input) {
81
+ await requireSchoolAdmin(input.schoolId, userId);
82
+ const result = await deleteAcademicYear(input.yearId, input.schoolId);
83
+ if (result.count === 0) {
84
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic year not found" });
85
+ }
86
+ return { ok: true };
87
+ }
88
+ export async function createTerm(userId, input) {
89
+ await requireSchoolAdmin(input.schoolId, userId);
90
+ const year = await getAcademicYearById(input.yearId, input.schoolId);
91
+ if (!year) {
92
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic year not found" });
93
+ }
94
+ if (input.endDate < input.startDate) {
95
+ throw new TRPCError({
96
+ code: "BAD_REQUEST",
97
+ message: "endDate must be on or after startDate",
98
+ });
99
+ }
100
+ try {
101
+ const term = await createAcademicTerm({
102
+ academicYearId: input.yearId,
103
+ name: input.name,
104
+ startDate: input.startDate,
105
+ endDate: input.endDate,
106
+ isCurrent: input.isCurrent,
107
+ });
108
+ return { term };
109
+ }
110
+ catch (err) {
111
+ if (err &&
112
+ typeof err === "object" &&
113
+ "code" in err &&
114
+ err.code === "P2002") {
115
+ throw new TRPCError({
116
+ code: "CONFLICT",
117
+ message: "A term with this name already exists in the year",
118
+ });
119
+ }
120
+ throw err;
121
+ }
122
+ }
123
+ export async function updateTerm(userId, input) {
124
+ await requireSchoolAdmin(input.schoolId, userId);
125
+ const year = await getAcademicYearById(input.yearId, input.schoolId);
126
+ if (!year) {
127
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic year not found" });
128
+ }
129
+ if (input.startDate !== undefined || input.endDate !== undefined) {
130
+ const existingTerm = year.terms.find((t) => t.id === input.termId);
131
+ if (!existingTerm) {
132
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic term not found" });
133
+ }
134
+ const nextStart = input.startDate ?? existingTerm.startDate;
135
+ const nextEnd = input.endDate ?? existingTerm.endDate;
136
+ if (nextEnd < nextStart) {
137
+ throw new TRPCError({
138
+ code: "BAD_REQUEST",
139
+ message: "endDate must be on or after startDate",
140
+ });
141
+ }
142
+ }
143
+ const term = await updateAcademicTerm(input.termId, input.yearId, {
144
+ name: input.name,
145
+ startDate: input.startDate,
146
+ endDate: input.endDate,
147
+ isCurrent: input.isCurrent,
148
+ });
149
+ if (!term) {
150
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic term not found" });
151
+ }
152
+ return { term };
153
+ }
154
+ export async function removeTerm(userId, input) {
155
+ await requireSchoolAdmin(input.schoolId, userId);
156
+ const year = await getAcademicYearById(input.yearId, input.schoolId);
157
+ if (!year) {
158
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic year not found" });
159
+ }
160
+ const result = await deleteAcademicTerm(input.termId, input.yearId);
161
+ if (result.count === 0) {
162
+ throw new TRPCError({ code: "NOT_FOUND", message: "Academic term not found" });
163
+ }
164
+ return { ok: true };
165
+ }
166
+ /**
167
+ * C2: Promote / move students from one class to another (basic rollover).
168
+ * Disconnects from `fromClassId` and connects to `toClassId`.
169
+ */
170
+ export async function promoteStudents(userId, input) {
171
+ await requireSchoolAdmin(input.schoolId, userId);
172
+ if (input.fromClassId === input.toClassId) {
173
+ throw new TRPCError({
174
+ code: "BAD_REQUEST",
175
+ message: "fromClassId and toClassId must differ",
176
+ });
177
+ }
178
+ if (input.studentUserIds.length === 0) {
179
+ throw new TRPCError({
180
+ code: "BAD_REQUEST",
181
+ message: "Select at least one student",
182
+ });
183
+ }
184
+ const [fromClass, toClass] = await Promise.all([
185
+ findSchoolClass(input.schoolId, input.fromClassId),
186
+ findSchoolClass(input.schoolId, input.toClassId),
187
+ ]);
188
+ if (!fromClass || !toClass) {
189
+ throw new TRPCError({
190
+ code: "NOT_FOUND",
191
+ message: "Source or destination class not found in this school",
192
+ });
193
+ }
194
+ const memberships = await listActiveSchoolMemberships(input.schoolId, input.studentUserIds);
195
+ const studentIds = memberships
196
+ .filter((m) => m.role === "STUDENT")
197
+ .map((m) => m.userId);
198
+ if (studentIds.length === 0) {
199
+ throw new TRPCError({
200
+ code: "BAD_REQUEST",
201
+ message: "No active student memberships found for the given users",
202
+ });
203
+ }
204
+ // Only move students currently enrolled in the source class.
205
+ const enrolled = await prisma.class.findFirst({
206
+ where: {
207
+ id: input.fromClassId,
208
+ schoolId: input.schoolId,
209
+ },
210
+ select: {
211
+ students: {
212
+ where: { id: { in: studentIds } },
213
+ select: { id: true },
214
+ },
215
+ },
216
+ });
217
+ const moveIds = (enrolled?.students ?? []).map((s) => s.id);
218
+ if (moveIds.length === 0) {
219
+ throw new TRPCError({
220
+ code: "BAD_REQUEST",
221
+ message: "None of the selected students are in the source class",
222
+ });
223
+ }
224
+ await prisma.$transaction([
225
+ prisma.class.update({
226
+ where: { id: input.fromClassId },
227
+ data: { students: { disconnect: moveIds.map((id) => ({ id })) } },
228
+ }),
229
+ prisma.class.update({
230
+ where: { id: input.toClassId },
231
+ data: { students: { connect: moveIds.map((id) => ({ id })) } },
232
+ }),
233
+ ]);
234
+ return {
235
+ promotedCount: moveIds.length,
236
+ studentUserIds: moveIds,
237
+ fromClassId: input.fromClassId,
238
+ toClassId: input.toClassId,
239
+ };
240
+ }
241
+ //# sourceMappingURL=academicCalendar.js.map
242
+ //# debugId=d8dde89c-b5a2-5b31-be33-b365078aeaa2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"academicCalendar.js","sources":["services/academicCalendar.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Academic year / term service (C1) + student promotion (C2).\n */\nimport { TRPCError } from \"@trpc/server\";\nimport { prisma } from \"../lib/prisma.js\";\nimport {\n createAcademicTerm,\n createAcademicYear,\n deleteAcademicTerm,\n deleteAcademicYear,\n getAcademicYearById,\n getCurrentAcademicYear,\n listAcademicYears,\n updateAcademicTerm,\n updateAcademicYear,\n} from \"../models/academicCalendar.js\";\nimport {\n findActiveSchoolAdminMembership,\n findSchoolClass,\n listActiveSchoolMemberships,\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\nexport async function listYears(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { years: await listAcademicYears(schoolId) };\n}\n\nexport async function getCurrentYear(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { year: await getCurrentAcademicYear(schoolId) };\n}\n\nexport async function createYear(\n userId: string,\n input: {\n schoolId: string;\n name: string;\n startDate: Date;\n endDate: Date;\n isCurrent?: boolean;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n if (input.endDate < input.startDate) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"endDate must be on or after startDate\",\n });\n }\n try {\n const year = await createAcademicYear(input);\n return { year };\n } catch (err: unknown) {\n if (\n err &&\n typeof err === \"object\" &&\n \"code\" in err &&\n (err as { code: string }).code === \"P2002\"\n ) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message: \"An academic year with this name already exists\",\n });\n }\n throw err;\n }\n}\n\nexport async function updateYear(\n userId: string,\n input: {\n schoolId: string;\n yearId: string;\n name?: string;\n startDate?: Date;\n endDate?: Date;\n isCurrent?: boolean;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n if (input.startDate !== undefined || input.endDate !== undefined) {\n const existing = await getAcademicYearById(input.yearId, input.schoolId);\n if (!existing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic year not found\" });\n }\n const nextStart = input.startDate ?? existing.startDate;\n const nextEnd = input.endDate ?? existing.endDate;\n if (nextEnd < nextStart) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"endDate must be on or after startDate\",\n });\n }\n }\n const year = await updateAcademicYear(input.yearId, input.schoolId, {\n name: input.name,\n startDate: input.startDate,\n endDate: input.endDate,\n isCurrent: input.isCurrent,\n });\n if (!year) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic year not found\" });\n }\n return { year };\n}\n\nexport async function removeYear(\n userId: string,\n input: { schoolId: string; yearId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const result = await deleteAcademicYear(input.yearId, input.schoolId);\n if (result.count === 0) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic year not found\" });\n }\n return { ok: true as const };\n}\n\nexport async function createTerm(\n userId: string,\n input: {\n schoolId: string;\n yearId: string;\n name: string;\n startDate: Date;\n endDate: Date;\n isCurrent?: boolean;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const year = await getAcademicYearById(input.yearId, input.schoolId);\n if (!year) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic year not found\" });\n }\n if (input.endDate < input.startDate) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"endDate must be on or after startDate\",\n });\n }\n try {\n const term = await createAcademicTerm({\n academicYearId: input.yearId,\n name: input.name,\n startDate: input.startDate,\n endDate: input.endDate,\n isCurrent: input.isCurrent,\n });\n return { term };\n } catch (err: unknown) {\n if (\n err &&\n typeof err === \"object\" &&\n \"code\" in err &&\n (err as { code: string }).code === \"P2002\"\n ) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message: \"A term with this name already exists in the year\",\n });\n }\n throw err;\n }\n}\n\nexport async function updateTerm(\n userId: string,\n input: {\n schoolId: string;\n yearId: string;\n termId: string;\n name?: string;\n startDate?: Date;\n endDate?: Date;\n isCurrent?: boolean;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const year = await getAcademicYearById(input.yearId, input.schoolId);\n if (!year) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic year not found\" });\n }\n if (input.startDate !== undefined || input.endDate !== undefined) {\n const existingTerm = year.terms.find((t) => t.id === input.termId);\n if (!existingTerm) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic term not found\" });\n }\n const nextStart = input.startDate ?? existingTerm.startDate;\n const nextEnd = input.endDate ?? existingTerm.endDate;\n if (nextEnd < nextStart) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"endDate must be on or after startDate\",\n });\n }\n }\n const term = await updateAcademicTerm(input.termId, input.yearId, {\n name: input.name,\n startDate: input.startDate,\n endDate: input.endDate,\n isCurrent: input.isCurrent,\n });\n if (!term) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic term not found\" });\n }\n return { term };\n}\n\nexport async function removeTerm(\n userId: string,\n input: { schoolId: string; yearId: string; termId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const year = await getAcademicYearById(input.yearId, input.schoolId);\n if (!year) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic year not found\" });\n }\n const result = await deleteAcademicTerm(input.termId, input.yearId);\n if (result.count === 0) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Academic term not found\" });\n }\n return { ok: true as const };\n}\n\n/**\n * C2: Promote / move students from one class to another (basic rollover).\n * Disconnects from `fromClassId` and connects to `toClassId`.\n */\nexport async function promoteStudents(\n userId: string,\n input: {\n schoolId: string;\n fromClassId: string;\n toClassId: string;\n studentUserIds: string[];\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n if (input.fromClassId === input.toClassId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"fromClassId and toClassId must differ\",\n });\n }\n if (input.studentUserIds.length === 0) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Select at least one student\",\n });\n }\n\n const [fromClass, toClass] = await Promise.all([\n findSchoolClass(input.schoolId, input.fromClassId),\n findSchoolClass(input.schoolId, input.toClassId),\n ]);\n if (!fromClass || !toClass) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Source or destination class not found in this school\",\n });\n }\n\n const memberships = await listActiveSchoolMemberships(\n input.schoolId,\n input.studentUserIds\n );\n const studentIds = memberships\n .filter((m) => m.role === \"STUDENT\")\n .map((m) => m.userId);\n if (studentIds.length === 0) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"No active student memberships found for the given users\",\n });\n }\n\n // Only move students currently enrolled in the source class.\n const enrolled = await prisma.class.findFirst({\n where: {\n id: input.fromClassId,\n schoolId: input.schoolId,\n },\n select: {\n students: {\n where: { id: { in: studentIds } },\n select: { id: true },\n },\n },\n });\n const moveIds = (enrolled?.students ?? []).map((s) => s.id);\n if (moveIds.length === 0) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"None of the selected students are in the source class\",\n });\n }\n\n await prisma.$transaction([\n prisma.class.update({\n where: { id: input.fromClassId },\n data: { students: { disconnect: moveIds.map((id) => ({ id })) } },\n }),\n prisma.class.update({\n where: { id: input.toClassId },\n data: { students: { connect: moveIds.map((id) => ({ id })) } },\n }),\n ]);\n\n return {\n promotedCount: moveIds.length,\n studentUserIds: moveIds,\n fromClassId: input.fromClassId,\n toClassId: input.toClassId,\n };\n}\n"],"names":[],"mappings":"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","debug_id":"d8dde89c-b5a2-5b31-be33-b365078aeaa2"}
@@ -16,6 +16,7 @@ export declare function listSchoolsForAdmin(input: {
16
16
  name: string;
17
17
  description: string | null;
18
18
  logoId: string | null;
19
+ letterheadFileId: string | null;
19
20
  subdomain: string | null;
20
21
  })[];
21
22
  total: number;
@@ -72,6 +73,7 @@ export declare function getSchoolForAdmin(id: string): Promise<{
72
73
  name: string;
73
74
  description: string | null;
74
75
  logoId: string | null;
76
+ letterheadFileId: string | null;
75
77
  subdomain: string | null;
76
78
  }>;
77
79
  export declare function listDepartmentsForAdmin(input: {
@@ -1 +1 @@
1
- {"version":3,"file":"adminInstitution.d.ts","sourceRoot":"/","sources":["services/adminInstitution.ts"],"names":[],"mappings":"AAIA,wBAAsB,mBAAmB,CAAC,KAAK,EAAE;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;;;;;;;;;;;;;GAsCA;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDjD;AAED,wBAAsB,uBAAuB,CAAC,KAAK,EAAE;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;;;;;;;;;;;;;;;;;;;;;;;;GA0BA;AAED,wBAAsB,qCAAqC,CAAC,KAAK,EAAE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BA;AAED,wBAAsB,+BAA+B,CAAC,KAAK,EAAE;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;;;;;;;;;;;GAmBA"}
1
+ {"version":3,"file":"adminInstitution.d.ts","sourceRoot":"/","sources":["services/adminInstitution.ts"],"names":[],"mappings":"AAIA,wBAAsB,mBAAmB,CAAC,KAAK,EAAE;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;;;;;;;;;;;;;;GAsCA;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDjD;AAED,wBAAsB,uBAAuB,CAAC,KAAK,EAAE;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;;;;;;;;;;;;;;;;;;;;;;;;GA0BA;AAED,wBAAsB,qCAAqC,CAAC,KAAK,EAAE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BA;AAED,wBAAsB,+BAA+B,CAAC,KAAK,EAAE;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;;;;;;;;;;;GAmBA"}
@@ -15,6 +15,7 @@ export declare function getAgenda(userId: string, weekStart: string): Promise<{
15
15
  discussionsEnabled: boolean;
16
16
  studentsCanCreateDiscussions: boolean;
17
17
  studentsCanReply: boolean;
18
+ sidebarFeatures: import("@prisma/client/runtime/library.js").JsonValue | null;
18
19
  treatMissingAsZero: boolean;
19
20
  gradeRoundingMode: import(".prisma/client").$Enums.GradeRoundingMode;
20
21
  } | null;
@@ -44,6 +45,9 @@ export declare function getAgenda(userId: string, weekStart: string): Promise<{
44
45
  order: number | null;
45
46
  gradingBoundaryId: string | null;
46
47
  gradeCategoryId: string | null;
48
+ timeLimitMinutes: number | null;
49
+ singleAttempt: boolean;
50
+ allowLateSubmissions: boolean;
47
51
  }[];
48
52
  } & {
49
53
  id: string;
@@ -70,6 +74,7 @@ export declare function getAgenda(userId: string, weekStart: string): Promise<{
70
74
  discussionsEnabled: boolean;
71
75
  studentsCanCreateDiscussions: boolean;
72
76
  studentsCanReply: boolean;
77
+ sidebarFeatures: import("@prisma/client/runtime/library.js").JsonValue | null;
73
78
  treatMissingAsZero: boolean;
74
79
  gradeRoundingMode: import(".prisma/client").$Enums.GradeRoundingMode;
75
80
  } | null;
@@ -99,6 +104,9 @@ export declare function getAgenda(userId: string, weekStart: string): Promise<{
99
104
  order: number | null;
100
105
  gradingBoundaryId: string | null;
101
106
  gradeCategoryId: string | null;
107
+ timeLimitMinutes: number | null;
108
+ singleAttempt: boolean;
109
+ allowLateSubmissions: boolean;
102
110
  }[];
103
111
  } & {
104
112
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"agenda.d.ts","sourceRoot":"/","sources":["services/agenda.ts"],"names":[],"mappings":"AAQA,sFAAsF;AACtF,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAWhE"}
1
+ {"version":3,"file":"agenda.d.ts","sourceRoot":"/","sources":["services/agenda.ts"],"names":[],"mappings":"AAQA,sFAAsF;AACtF,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAWhE"}