@studious-lms/server 1.23.0 → 1.24.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.
- package/.env.example +0 -1
- package/data/curriculum/nepal-cdc-g4-g5/README.md +90 -0
- package/data/curriculum/nepal-cdc-g4-g5/manifest.json +97 -0
- package/data/curriculum/nepal-cdc-g4-g5/proficiency-scale.json +76 -0
- package/data/curriculum/nepal-cdc-g4-g5/subjects/english.json +6936 -0
- package/data/curriculum/nepal-cdc-g4-g5/subjects/health-physical-creative-arts.json +3401 -0
- package/data/curriculum/nepal-cdc-g4-g5/subjects/mathematics.json +1511 -0
- package/data/curriculum/nepal-cdc-g4-g5/subjects/nepali.json +7928 -0
- package/data/curriculum/nepal-cdc-g4-g5/subjects/science-technology.json +2420 -0
- package/data/curriculum/nepal-cdc-g4-g5/subjects/social-studies.json +2177 -0
- package/dist/lib/assignmentTypeDefaults.d.ts +41 -0
- package/dist/lib/assignmentTypeDefaults.d.ts.map +1 -0
- package/dist/lib/assignmentTypeDefaults.js +167 -0
- package/dist/lib/assignmentTypeDefaults.js.map +1 -0
- package/dist/lib/config/env.d.ts +0 -8
- package/dist/lib/config/env.d.ts.map +1 -1
- package/dist/lib/config/env.js +2 -5
- package/dist/lib/config/env.js.map +1 -1
- package/dist/lib/feePdf.d.ts +19 -0
- package/dist/lib/feePdf.d.ts.map +1 -0
- package/dist/lib/feePdf.js +167 -0
- package/dist/lib/feePdf.js.map +1 -0
- package/dist/lib/feePdfFormat.d.ts +4 -0
- package/dist/lib/feePdfFormat.d.ts.map +1 -0
- package/dist/lib/feePdfFormat.js +16 -0
- package/dist/lib/feePdfFormat.js.map +1 -0
- package/dist/lib/idCardPdf.d.ts +26 -0
- package/dist/lib/idCardPdf.d.ts.map +1 -0
- package/dist/lib/idCardPdf.js +272 -0
- package/dist/lib/idCardPdf.js.map +1 -0
- package/dist/lib/pdfLetterhead.d.ts +41 -0
- package/dist/lib/pdfLetterhead.d.ts.map +1 -0
- package/dist/lib/pdfLetterhead.js +86 -0
- package/dist/lib/pdfLetterhead.js.map +1 -0
- package/dist/lib/transcriptPdf.d.ts +55 -0
- package/dist/lib/transcriptPdf.d.ts.map +1 -0
- package/dist/lib/transcriptPdf.js +303 -0
- package/dist/lib/transcriptPdf.js.map +1 -0
- package/dist/models/academicCalendar.d.ts +198 -0
- package/dist/models/academicCalendar.d.ts.map +1 -0
- package/dist/models/academicCalendar.js +106 -0
- package/dist/models/academicCalendar.js.map +1 -0
- package/dist/models/agenda.d.ts +8 -0
- package/dist/models/agenda.d.ts.map +1 -1
- package/dist/models/announcement.d.ts +2 -0
- package/dist/models/announcement.d.ts.map +1 -1
- package/dist/models/assignment.d.ts +66 -0
- package/dist/models/assignment.d.ts.map +1 -1
- package/dist/models/attendance.d.ts +659 -21
- package/dist/models/attendance.d.ts.map +1 -1
- package/dist/models/attendance.js +544 -75
- package/dist/models/attendance.js.map +1 -1
- package/dist/models/auth.d.ts +2 -0
- package/dist/models/auth.d.ts.map +1 -1
- package/dist/models/class.d.ts +12 -0
- package/dist/models/class.d.ts.map +1 -1
- package/dist/models/class.js +3 -2
- package/dist/models/class.js.map +1 -1
- package/dist/models/event.d.ts +16 -0
- package/dist/models/event.d.ts.map +1 -1
- package/dist/models/fees.d.ts +554 -0
- package/dist/models/fees.d.ts.map +1 -0
- package/dist/models/fees.js +278 -0
- package/dist/models/fees.js.map +1 -0
- package/dist/models/file.d.ts +29 -0
- package/dist/models/file.d.ts.map +1 -1
- package/dist/models/folder.d.ts +2 -0
- package/dist/models/folder.d.ts.map +1 -1
- package/dist/models/labChat.d.ts +2 -0
- package/dist/models/labChat.d.ts.map +1 -1
- package/dist/models/marketplace.d.ts +178 -0
- package/dist/models/marketplace.d.ts.map +1 -0
- package/dist/models/marketplace.js +115 -0
- package/dist/models/marketplace.js.map +1 -0
- package/dist/models/moduleItem.d.ts +304 -0
- package/dist/models/moduleItem.d.ts.map +1 -0
- package/dist/models/moduleItem.js +78 -0
- package/dist/models/moduleItem.js.map +1 -0
- package/dist/models/newtonChat.d.ts +1 -0
- package/dist/models/newtonChat.d.ts.map +1 -1
- package/dist/models/school.d.ts +18 -0
- package/dist/models/school.d.ts.map +1 -1
- package/dist/models/school.js +7 -2
- package/dist/models/school.js.map +1 -1
- package/dist/models/section.d.ts +4 -0
- package/dist/models/section.d.ts.map +1 -1
- package/dist/models/worksheet.d.ts +19 -0
- package/dist/models/worksheet.d.ts.map +1 -1
- package/dist/models/worksheet.js +2 -2
- package/dist/models/worksheet.js.map +1 -1
- package/dist/routers/_app.d.ts +11341 -7097
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/_app.js +12 -2
- package/dist/routers/_app.js.map +1 -1
- package/dist/routers/academicCalendar.d.ts +229 -0
- package/dist/routers/academicCalendar.d.ts.map +1 -0
- package/dist/routers/academicCalendar.js +75 -0
- package/dist/routers/academicCalendar.js.map +1 -0
- package/dist/routers/admin.d.ts +2 -0
- package/dist/routers/admin.d.ts.map +1 -1
- package/dist/routers/agenda.d.ts +8 -0
- package/dist/routers/agenda.d.ts.map +1 -1
- package/dist/routers/assignment.d.ts +75 -0
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +10 -2
- package/dist/routers/assignment.js.map +1 -1
- package/dist/routers/attendance.d.ts +103 -0
- package/dist/routers/attendance.d.ts.map +1 -1
- package/dist/routers/attendance.js +8 -5
- package/dist/routers/attendance.js.map +1 -1
- package/dist/routers/class.d.ts +27 -0
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +6 -2
- package/dist/routers/class.js.map +1 -1
- package/dist/routers/event.d.ts +8 -0
- package/dist/routers/event.d.ts.map +1 -1
- package/dist/routers/fees.d.ts +513 -0
- package/dist/routers/fees.d.ts.map +1 -0
- package/dist/routers/fees.js +88 -0
- package/dist/routers/fees.js.map +1 -0
- package/dist/routers/file.d.ts +2 -0
- package/dist/routers/file.d.ts.map +1 -1
- package/dist/routers/gradebook.d.ts +4 -1
- package/dist/routers/gradebook.d.ts.map +1 -1
- package/dist/routers/marketplace.d.ts +371 -0
- package/dist/routers/marketplace.d.ts.map +1 -0
- package/dist/routers/marketplace.js +87 -0
- package/dist/routers/marketplace.js.map +1 -0
- package/dist/routers/moduleItem.d.ts +263 -0
- package/dist/routers/moduleItem.d.ts.map +1 -0
- package/dist/routers/moduleItem.js +60 -0
- package/dist/routers/moduleItem.js.map +1 -0
- package/dist/routers/parent.d.ts +169 -0
- package/dist/routers/parent.d.ts.map +1 -0
- package/dist/routers/parent.js +49 -0
- package/dist/routers/parent.js.map +1 -0
- package/dist/routers/school.d.ts +363 -7
- package/dist/routers/school.d.ts.map +1 -1
- package/dist/routers/school.js +100 -3
- package/dist/routers/school.js.map +1 -1
- package/dist/routers/worksheet.d.ts +27 -0
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/routers/worksheet.js +10 -3
- package/dist/routers/worksheet.js.map +1 -1
- package/dist/services/academicCalendar.d.ts +173 -0
- package/dist/services/academicCalendar.d.ts.map +1 -0
- package/dist/services/academicCalendar.js +214 -0
- package/dist/services/academicCalendar.js.map +1 -0
- package/dist/services/adminInstitution.d.ts +2 -0
- package/dist/services/adminInstitution.d.ts.map +1 -1
- package/dist/services/agenda.d.ts +8 -0
- package/dist/services/agenda.d.ts.map +1 -1
- package/dist/services/assignment.d.ts +75 -0
- package/dist/services/assignment.d.ts.map +1 -1
- package/dist/services/assignment.js +91 -12
- package/dist/services/assignment.js.map +1 -1
- package/dist/services/attendance.d.ts +323 -10
- package/dist/services/attendance.d.ts.map +1 -1
- package/dist/services/attendance.js +385 -25
- package/dist/services/attendance.js.map +1 -1
- package/dist/services/attendanceMerge.d.ts +53 -0
- package/dist/services/attendanceMerge.d.ts.map +1 -0
- package/dist/services/attendanceMerge.js +87 -0
- package/dist/services/attendanceMerge.js.map +1 -0
- package/dist/services/attendanceRate.d.ts +24 -0
- package/dist/services/attendanceRate.d.ts.map +1 -0
- package/dist/services/attendanceRate.js +31 -0
- package/dist/services/attendanceRate.js.map +1 -0
- package/dist/services/attendanceStats.d.ts +22 -0
- package/dist/services/attendanceStats.d.ts.map +1 -0
- package/dist/services/attendanceStats.js +45 -0
- package/dist/services/attendanceStats.js.map +1 -0
- package/dist/services/class.d.ts +27 -0
- package/dist/services/class.d.ts.map +1 -1
- package/dist/services/class.js +26 -3
- package/dist/services/class.js.map +1 -1
- package/dist/services/event.d.ts +8 -0
- package/dist/services/event.d.ts.map +1 -1
- package/dist/services/fees.d.ts +422 -0
- package/dist/services/fees.d.ts.map +1 -0
- package/dist/services/fees.js +310 -0
- package/dist/services/fees.js.map +1 -0
- package/dist/services/feesAuthz.d.ts +49 -0
- package/dist/services/feesAuthz.d.ts.map +1 -0
- package/dist/services/feesAuthz.js +52 -0
- package/dist/services/feesAuthz.js.map +1 -0
- package/dist/services/file.d.ts +4 -0
- package/dist/services/file.d.ts.map +1 -1
- package/dist/services/gradebook.d.ts +18 -1
- package/dist/services/gradebook.d.ts.map +1 -1
- package/dist/services/gradebook.js +57 -2
- package/dist/services/gradebook.js.map +1 -1
- package/dist/services/idCard.d.ts +11 -0
- package/dist/services/idCard.d.ts.map +1 -0
- package/dist/services/idCard.js +122 -0
- package/dist/services/idCard.js.map +1 -0
- package/dist/services/marketplace.d.ts +301 -0
- package/dist/services/marketplace.d.ts.map +1 -0
- package/dist/services/marketplace.js +628 -0
- package/dist/services/marketplace.js.map +1 -0
- package/dist/services/moduleItem.d.ts +196 -0
- package/dist/services/moduleItem.d.ts.map +1 -0
- package/dist/services/moduleItem.js +188 -0
- package/dist/services/moduleItem.js.map +1 -0
- package/dist/services/notification.d.ts +58 -0
- package/dist/services/notification.d.ts.map +1 -1
- package/dist/services/notification.js +30 -2
- package/dist/services/notification.js.map +1 -1
- package/dist/services/parentPortal.d.ts +133 -0
- package/dist/services/parentPortal.d.ts.map +1 -0
- package/dist/services/parentPortal.js +328 -0
- package/dist/services/parentPortal.js.map +1 -0
- package/dist/services/school.d.ts +28 -3
- package/dist/services/school.d.ts.map +1 -1
- package/dist/services/school.js +65 -45
- package/dist/services/school.js.map +1 -1
- package/dist/services/studentImport.d.ts +34 -0
- package/dist/services/studentImport.d.ts.map +1 -0
- package/dist/services/studentImport.js +236 -0
- package/dist/services/studentImport.js.map +1 -0
- package/dist/services/transcript.d.ts +61 -0
- package/dist/services/transcript.d.ts.map +1 -0
- package/dist/services/transcript.js +243 -0
- package/dist/services/transcript.js.map +1 -0
- package/dist/services/worksheet.d.ts +22 -0
- package/dist/services/worksheet.d.ts.map +1 -1
- package/dist/services/worksheet.js +94 -2
- package/dist/services/worksheet.js.map +1 -1
- package/dist/trpc.d.ts +1 -1
- package/dist/trpc.d.ts.map +1 -1
- package/dist/trpc.js +5 -5
- package/dist/trpc.js.map +1 -1
- package/dist/utils/adminPanelAccess.d.ts +4 -5
- package/dist/utils/adminPanelAccess.d.ts.map +1 -1
- package/dist/utils/adminPanelAccess.js +12 -34
- package/dist/utils/adminPanelAccess.js.map +1 -1
- package/package.json +2 -1
- package/prisma/migrations/20260804120000_add_attendance_records_and_excusals/migration.sql +114 -0
- package/prisma/migrations/20260804120100_add_fee_plans_invoices_payments/migration.sql +101 -0
- package/prisma/migrations/20260804120200_add_marketplace_listings/migration.sql +54 -0
- package/prisma/migrations/20260804120300_content_platform_b3_b9/migration.sql +63 -0
- package/prisma/migrations/20260804120400_c_academic_ops/migration.sql +77 -0
- package/prisma/schema.prisma +371 -11
- package/scripts/import-nepal-cdc-curriculum.ts +379 -0
- package/src/lib/assignmentTypeDefaults.ts +222 -0
- package/src/lib/config/env.ts +0 -3
- package/src/lib/feePdf.ts +199 -0
- package/src/lib/feePdfFormat.ts +14 -0
- package/src/lib/idCardPdf.ts +336 -0
- package/src/lib/pdfLetterhead.ts +124 -0
- package/src/lib/transcriptPdf.ts +502 -0
- package/src/models/academicCalendar.ts +139 -0
- package/src/models/attendance.ts +704 -73
- package/src/models/class.ts +1 -0
- package/src/models/fees.ts +349 -0
- package/src/models/marketplace.ts +158 -0
- package/src/models/moduleItem.ts +107 -0
- package/src/models/school.ts +6 -0
- package/src/models/worksheet.ts +2 -0
- package/src/routers/_app.ts +10 -0
- package/src/routers/academicCalendar.ts +103 -0
- package/src/routers/assignment.ts +8 -0
- package/src/routers/attendance.ts +7 -3
- package/src/routers/class.ts +4 -0
- package/src/routers/fees.ts +126 -0
- package/src/routers/marketplace.ts +134 -0
- package/src/routers/moduleItem.ts +89 -0
- package/src/routers/parent.ts +68 -0
- package/src/routers/school.ts +139 -1
- package/src/routers/worksheet.ts +11 -0
- package/src/services/academicCalendar.ts +299 -0
- package/src/services/assignment.ts +122 -12
- package/src/services/attendance.ts +548 -26
- package/src/services/attendanceMerge.ts +139 -0
- package/src/services/attendanceRate.ts +41 -0
- package/src/services/attendanceStats.ts +63 -0
- package/src/services/class.ts +25 -1
- package/src/services/fees.ts +424 -0
- package/src/services/feesAuthz.ts +77 -0
- package/src/services/gradebook.ts +70 -0
- package/src/services/idCard.ts +147 -0
- package/src/services/marketplace.ts +785 -0
- package/src/services/moduleItem.ts +274 -0
- package/src/services/notification.ts +43 -0
- package/src/services/parentPortal.ts +380 -0
- package/src/services/school.ts +65 -44
- package/src/services/studentImport.ts +273 -0
- package/src/services/transcript.ts +313 -0
- package/src/services/worksheet.ts +111 -0
- package/src/trpc.ts +3 -3
- package/src/utils/adminPanelAccess.ts +12 -35
- package/tests/unit/assignmentTypeDefaults.test.ts +52 -0
- package/tests/unit/lib/feePdf.test.ts +15 -0
- package/tests/unit/lib/idCardPdf.test.ts +40 -0
- package/tests/unit/lib/transcriptPdf.test.ts +111 -0
- package/tests/unit/services/attendanceMerge.test.ts +90 -0
- package/tests/unit/services/attendanceRate.test.ts +38 -0
- package/tests/unit/services/attendanceStats.test.ts +54 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createTRPCRouter, protectedProcedure } from "../trpc.js";
|
|
3
|
+
import {
|
|
4
|
+
createTerm,
|
|
5
|
+
createYear,
|
|
6
|
+
getCurrentYear,
|
|
7
|
+
listYears,
|
|
8
|
+
promoteStudents,
|
|
9
|
+
removeTerm,
|
|
10
|
+
removeYear,
|
|
11
|
+
updateTerm,
|
|
12
|
+
updateYear,
|
|
13
|
+
} from "../services/academicCalendar.js";
|
|
14
|
+
|
|
15
|
+
const schoolIdSchema = z.object({ schoolId: z.string() });
|
|
16
|
+
|
|
17
|
+
export const academicCalendarRouter = createTRPCRouter({
|
|
18
|
+
listYears: protectedProcedure
|
|
19
|
+
.input(schoolIdSchema)
|
|
20
|
+
.query(({ ctx, input }) => listYears(ctx.user!.id, input.schoolId)),
|
|
21
|
+
|
|
22
|
+
getCurrentYear: protectedProcedure
|
|
23
|
+
.input(schoolIdSchema)
|
|
24
|
+
.query(({ ctx, input }) => getCurrentYear(ctx.user!.id, input.schoolId)),
|
|
25
|
+
|
|
26
|
+
createYear: protectedProcedure
|
|
27
|
+
.input(
|
|
28
|
+
z.object({
|
|
29
|
+
schoolId: z.string(),
|
|
30
|
+
name: z.string().min(1),
|
|
31
|
+
startDate: z.date(),
|
|
32
|
+
endDate: z.date(),
|
|
33
|
+
isCurrent: z.boolean().optional(),
|
|
34
|
+
})
|
|
35
|
+
)
|
|
36
|
+
.mutation(({ ctx, input }) => createYear(ctx.user!.id, input)),
|
|
37
|
+
|
|
38
|
+
updateYear: protectedProcedure
|
|
39
|
+
.input(
|
|
40
|
+
z.object({
|
|
41
|
+
schoolId: z.string(),
|
|
42
|
+
yearId: z.string(),
|
|
43
|
+
name: z.string().min(1).optional(),
|
|
44
|
+
startDate: z.date().optional(),
|
|
45
|
+
endDate: z.date().optional(),
|
|
46
|
+
isCurrent: z.boolean().optional(),
|
|
47
|
+
})
|
|
48
|
+
)
|
|
49
|
+
.mutation(({ ctx, input }) => updateYear(ctx.user!.id, input)),
|
|
50
|
+
|
|
51
|
+
deleteYear: protectedProcedure
|
|
52
|
+
.input(z.object({ schoolId: z.string(), yearId: z.string() }))
|
|
53
|
+
.mutation(({ ctx, input }) => removeYear(ctx.user!.id, input)),
|
|
54
|
+
|
|
55
|
+
createTerm: protectedProcedure
|
|
56
|
+
.input(
|
|
57
|
+
z.object({
|
|
58
|
+
schoolId: z.string(),
|
|
59
|
+
yearId: z.string(),
|
|
60
|
+
name: z.string().min(1),
|
|
61
|
+
startDate: z.date(),
|
|
62
|
+
endDate: z.date(),
|
|
63
|
+
isCurrent: z.boolean().optional(),
|
|
64
|
+
})
|
|
65
|
+
)
|
|
66
|
+
.mutation(({ ctx, input }) => createTerm(ctx.user!.id, input)),
|
|
67
|
+
|
|
68
|
+
updateTerm: protectedProcedure
|
|
69
|
+
.input(
|
|
70
|
+
z.object({
|
|
71
|
+
schoolId: z.string(),
|
|
72
|
+
yearId: z.string(),
|
|
73
|
+
termId: z.string(),
|
|
74
|
+
name: z.string().min(1).optional(),
|
|
75
|
+
startDate: z.date().optional(),
|
|
76
|
+
endDate: z.date().optional(),
|
|
77
|
+
isCurrent: z.boolean().optional(),
|
|
78
|
+
})
|
|
79
|
+
)
|
|
80
|
+
.mutation(({ ctx, input }) => updateTerm(ctx.user!.id, input)),
|
|
81
|
+
|
|
82
|
+
deleteTerm: protectedProcedure
|
|
83
|
+
.input(
|
|
84
|
+
z.object({
|
|
85
|
+
schoolId: z.string(),
|
|
86
|
+
yearId: z.string(),
|
|
87
|
+
termId: z.string(),
|
|
88
|
+
})
|
|
89
|
+
)
|
|
90
|
+
.mutation(({ ctx, input }) => removeTerm(ctx.user!.id, input)),
|
|
91
|
+
|
|
92
|
+
/** C2: Move students from one class to another (basic promotion / rollover). */
|
|
93
|
+
promoteStudents: protectedProcedure
|
|
94
|
+
.input(
|
|
95
|
+
z.object({
|
|
96
|
+
schoolId: z.string(),
|
|
97
|
+
fromClassId: z.string(),
|
|
98
|
+
toClassId: z.string(),
|
|
99
|
+
studentUserIds: z.array(z.string()).min(1).max(500),
|
|
100
|
+
})
|
|
101
|
+
)
|
|
102
|
+
.mutation(({ ctx, input }) => promoteStudents(ctx.user!.id, input)),
|
|
103
|
+
});
|
|
@@ -78,6 +78,10 @@ const createAssignmentSchema = z.object({
|
|
|
78
78
|
gradingBoundaryId: z.string().optional(),
|
|
79
79
|
inProgress: z.boolean().optional(),
|
|
80
80
|
sourceAssignmentId: z.string().optional(),
|
|
81
|
+
timeLimitMinutes: z.number().int().min(1).max(1440).nullable().optional(),
|
|
82
|
+
singleAttempt: z.boolean().optional(),
|
|
83
|
+
allowLateSubmissions: z.boolean().optional(),
|
|
84
|
+
applyTypeDefaults: z.boolean().optional(),
|
|
81
85
|
});
|
|
82
86
|
|
|
83
87
|
const updateAssignmentSchema = z.object({
|
|
@@ -102,6 +106,10 @@ const updateAssignmentSchema = z.object({
|
|
|
102
106
|
sectionId: z.string().nullable().optional(),
|
|
103
107
|
type: z.enum(['HOMEWORK', 'QUIZ', 'TEST', 'PROJECT', 'ESSAY', 'DISCUSSION', 'PRESENTATION', 'LAB', 'OTHER']).optional(),
|
|
104
108
|
inProgress: z.boolean().optional(),
|
|
109
|
+
timeLimitMinutes: z.number().int().min(1).max(1440).nullable().optional(),
|
|
110
|
+
singleAttempt: z.boolean().optional(),
|
|
111
|
+
allowLateSubmissions: z.boolean().optional(),
|
|
112
|
+
applyTypeDefaults: z.boolean().optional(),
|
|
105
113
|
});
|
|
106
114
|
|
|
107
115
|
const deleteAssignmentSchema = z.object({
|
|
@@ -7,11 +7,15 @@ import {
|
|
|
7
7
|
import { TRPCError } from "@trpc/server";
|
|
8
8
|
import { getAttendance, updateAttendanceRecord } from "../services/attendance.js";
|
|
9
9
|
|
|
10
|
+
const studentRefSchema = z.object({ id: z.string(), username: z.string() });
|
|
11
|
+
|
|
10
12
|
const attendanceSchema = z.object({
|
|
11
13
|
eventId: z.string().optional(),
|
|
12
|
-
present: z.array(
|
|
13
|
-
late: z.array(
|
|
14
|
-
absent: z.array(
|
|
14
|
+
present: z.array(studentRefSchema),
|
|
15
|
+
late: z.array(studentRefSchema),
|
|
16
|
+
absent: z.array(studentRefSchema),
|
|
17
|
+
/** Optional; teachers may mark manual EXCUSED. Excusal-locked students stay EXCUSED. */
|
|
18
|
+
excused: z.array(studentRefSchema).optional(),
|
|
15
19
|
});
|
|
16
20
|
|
|
17
21
|
export const attendanceRouter = createTRPCRouter({
|
package/src/routers/class.ts
CHANGED
|
@@ -64,6 +64,10 @@ export const classRouter = createTRPCRouter({
|
|
|
64
64
|
discussionsEnabled: z.boolean().optional(),
|
|
65
65
|
studentsCanCreateDiscussions: z.boolean().optional(),
|
|
66
66
|
studentsCanReply: z.boolean().optional(),
|
|
67
|
+
sidebarFeatures: z
|
|
68
|
+
.record(z.string(), z.boolean())
|
|
69
|
+
.nullable()
|
|
70
|
+
.optional(),
|
|
67
71
|
})
|
|
68
72
|
)
|
|
69
73
|
.mutation(({ input }) => {
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createTRPCRouter, protectedProcedure } from "../trpc.js";
|
|
3
|
+
import {
|
|
4
|
+
createPlan,
|
|
5
|
+
generateMonthlyInvoices,
|
|
6
|
+
getInvoice,
|
|
7
|
+
getInvoicePdf,
|
|
8
|
+
getPlan,
|
|
9
|
+
getReceiptPdf,
|
|
10
|
+
listBalances,
|
|
11
|
+
listInvoices,
|
|
12
|
+
listPlans,
|
|
13
|
+
recordPayment,
|
|
14
|
+
setPlanStudents,
|
|
15
|
+
updatePlan,
|
|
16
|
+
} from "../services/fees.js";
|
|
17
|
+
import { getFeeCapabilities } from "../services/feesAuthz.js";
|
|
18
|
+
|
|
19
|
+
const schoolIdSchema = z.object({ schoolId: z.string() });
|
|
20
|
+
|
|
21
|
+
const paymentMethodSchema = z.enum(["CASH", "BANK", "ESEWA_REF"]);
|
|
22
|
+
const invoiceStatusSchema = z.enum(["UNPAID", "PARTIAL", "PAID", "VOID"]);
|
|
23
|
+
|
|
24
|
+
export const feesRouter = createTRPCRouter({
|
|
25
|
+
listPlans: protectedProcedure
|
|
26
|
+
.input(schoolIdSchema)
|
|
27
|
+
.query(({ ctx, input }) => listPlans(ctx.user!.id, input.schoolId)),
|
|
28
|
+
|
|
29
|
+
getPlan: protectedProcedure
|
|
30
|
+
.input(z.object({ planId: z.string() }))
|
|
31
|
+
.query(({ ctx, input }) => getPlan(ctx.user!.id, input.planId)),
|
|
32
|
+
|
|
33
|
+
createPlan: protectedProcedure
|
|
34
|
+
.input(
|
|
35
|
+
z.object({
|
|
36
|
+
schoolId: z.string(),
|
|
37
|
+
name: z.string().min(1),
|
|
38
|
+
description: z.string().nullable().optional(),
|
|
39
|
+
amountNpr: z.number().int().positive(),
|
|
40
|
+
studentIds: z.array(z.string()).optional(),
|
|
41
|
+
})
|
|
42
|
+
)
|
|
43
|
+
.mutation(({ ctx, input }) => createPlan(ctx.user!.id, input)),
|
|
44
|
+
|
|
45
|
+
updatePlan: protectedProcedure
|
|
46
|
+
.input(
|
|
47
|
+
z.object({
|
|
48
|
+
planId: z.string(),
|
|
49
|
+
name: z.string().min(1).optional(),
|
|
50
|
+
description: z.string().nullable().optional(),
|
|
51
|
+
amountNpr: z.number().int().positive().optional(),
|
|
52
|
+
isActive: z.boolean().optional(),
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
.mutation(({ ctx, input }) => updatePlan(ctx.user!.id, input)),
|
|
56
|
+
|
|
57
|
+
setPlanStudents: protectedProcedure
|
|
58
|
+
.input(
|
|
59
|
+
z.object({
|
|
60
|
+
planId: z.string(),
|
|
61
|
+
studentIds: z.array(z.string()),
|
|
62
|
+
})
|
|
63
|
+
)
|
|
64
|
+
.mutation(({ ctx, input }) => setPlanStudents(ctx.user!.id, input)),
|
|
65
|
+
|
|
66
|
+
generateMonthlyInvoices: protectedProcedure
|
|
67
|
+
.input(
|
|
68
|
+
z.object({
|
|
69
|
+
schoolId: z.string(),
|
|
70
|
+
feePlanId: z.string(),
|
|
71
|
+
year: z.number().int().min(2000).max(2100),
|
|
72
|
+
month: z.number().int().min(1).max(12),
|
|
73
|
+
studentIds: z.array(z.string()).optional(),
|
|
74
|
+
dueDate: z.coerce.date().nullable().optional(),
|
|
75
|
+
})
|
|
76
|
+
)
|
|
77
|
+
.mutation(({ ctx, input }) =>
|
|
78
|
+
generateMonthlyInvoices(ctx.user!.id, input)
|
|
79
|
+
),
|
|
80
|
+
|
|
81
|
+
listInvoices: protectedProcedure
|
|
82
|
+
.input(
|
|
83
|
+
z.object({
|
|
84
|
+
schoolId: z.string(),
|
|
85
|
+
year: z.number().int().optional(),
|
|
86
|
+
month: z.number().int().min(1).max(12).optional(),
|
|
87
|
+
studentId: z.string().optional(),
|
|
88
|
+
feePlanId: z.string().optional(),
|
|
89
|
+
status: invoiceStatusSchema.optional(),
|
|
90
|
+
})
|
|
91
|
+
)
|
|
92
|
+
.query(({ ctx, input }) => listInvoices(ctx.user!.id, input)),
|
|
93
|
+
|
|
94
|
+
getInvoice: protectedProcedure
|
|
95
|
+
.input(z.object({ invoiceId: z.string() }))
|
|
96
|
+
.query(({ ctx, input }) => getInvoice(ctx.user!.id, input.invoiceId)),
|
|
97
|
+
|
|
98
|
+
recordPayment: protectedProcedure
|
|
99
|
+
.input(
|
|
100
|
+
z.object({
|
|
101
|
+
invoiceId: z.string(),
|
|
102
|
+
amountNpr: z.number().int().positive(),
|
|
103
|
+
method: paymentMethodSchema,
|
|
104
|
+
reference: z.string().nullable().optional(),
|
|
105
|
+
paidAt: z.coerce.date().optional(),
|
|
106
|
+
notes: z.string().nullable().optional(),
|
|
107
|
+
})
|
|
108
|
+
)
|
|
109
|
+
.mutation(({ ctx, input }) => recordPayment(ctx.user!.id, input)),
|
|
110
|
+
|
|
111
|
+
listBalances: protectedProcedure
|
|
112
|
+
.input(schoolIdSchema)
|
|
113
|
+
.query(({ ctx, input }) => listBalances(ctx.user!.id, input.schoolId)),
|
|
114
|
+
|
|
115
|
+
getInvoicePdf: protectedProcedure
|
|
116
|
+
.input(z.object({ invoiceId: z.string() }))
|
|
117
|
+
.mutation(({ ctx, input }) => getInvoicePdf(ctx.user!.id, input.invoiceId)),
|
|
118
|
+
|
|
119
|
+
getReceiptPdf: protectedProcedure
|
|
120
|
+
.input(z.object({ paymentId: z.string() }))
|
|
121
|
+
.mutation(({ ctx, input }) => getReceiptPdf(ctx.user!.id, input.paymentId)),
|
|
122
|
+
|
|
123
|
+
getCapabilities: protectedProcedure
|
|
124
|
+
.input(schoolIdSchema)
|
|
125
|
+
.query(({ ctx, input }) => getFeeCapabilities(ctx.user!.id, input.schoolId)),
|
|
126
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marketplace tRPC router — B1 v1.
|
|
3
|
+
* Exercise/poll/kahoot listing types are deferred; only MARKSCHEME|WORKSHEET|FILE.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { createTRPCRouter, protectedProcedure } from "../trpc.js";
|
|
7
|
+
import {
|
|
8
|
+
getMarketplaceListing,
|
|
9
|
+
hideMarketplaceListing,
|
|
10
|
+
importMarketplaceListing,
|
|
11
|
+
listMarketplace,
|
|
12
|
+
listPublishableSources,
|
|
13
|
+
publishFileListing,
|
|
14
|
+
publishMarkSchemeListing,
|
|
15
|
+
publishWorksheetListing,
|
|
16
|
+
reportMarketplaceListing,
|
|
17
|
+
unpublishMarketplaceListing,
|
|
18
|
+
} from "../services/marketplace.js";
|
|
19
|
+
|
|
20
|
+
const listingTypeSchema = z.enum(["MARKSCHEME", "WORKSHEET", "FILE"]);
|
|
21
|
+
const visibilitySchema = z.enum(["SCHOOL", "PUBLIC"]);
|
|
22
|
+
const tagsSchema = z.array(z.string().trim().min(1).max(40)).max(12).optional();
|
|
23
|
+
|
|
24
|
+
const publishBase = {
|
|
25
|
+
title: z.string().trim().min(1).max(160),
|
|
26
|
+
description: z.string().trim().max(2000).optional(),
|
|
27
|
+
visibility: visibilitySchema,
|
|
28
|
+
schoolId: z.string().optional(),
|
|
29
|
+
tags: tagsSchema,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const marketplaceRouter = createTRPCRouter({
|
|
33
|
+
/** Search / list visible listings (school + public). */
|
|
34
|
+
list: protectedProcedure
|
|
35
|
+
.input(
|
|
36
|
+
z.object({
|
|
37
|
+
type: listingTypeSchema.optional(),
|
|
38
|
+
search: z.string().trim().max(120).optional(),
|
|
39
|
+
tags: tagsSchema,
|
|
40
|
+
schoolId: z.string().optional(),
|
|
41
|
+
cursor: z.string().optional(),
|
|
42
|
+
limit: z.number().int().min(1).max(50).default(20),
|
|
43
|
+
})
|
|
44
|
+
)
|
|
45
|
+
.query(({ ctx, input }) => listMarketplace(ctx.user!.id, input)),
|
|
46
|
+
|
|
47
|
+
get: protectedProcedure
|
|
48
|
+
.input(z.object({ listingId: z.string() }))
|
|
49
|
+
.query(({ ctx, input }) =>
|
|
50
|
+
getMarketplaceListing(ctx.user!.id, input.listingId)
|
|
51
|
+
),
|
|
52
|
+
|
|
53
|
+
/** Sources the caller can publish from (for the publish dialog). */
|
|
54
|
+
listPublishableSources: protectedProcedure
|
|
55
|
+
.input(
|
|
56
|
+
z.object({
|
|
57
|
+
classId: z.string().optional(),
|
|
58
|
+
schoolId: z.string().optional(),
|
|
59
|
+
})
|
|
60
|
+
)
|
|
61
|
+
.query(({ ctx, input }) => listPublishableSources(ctx.user!.id, input)),
|
|
62
|
+
|
|
63
|
+
publishMarkScheme: protectedProcedure
|
|
64
|
+
.input(
|
|
65
|
+
z.object({
|
|
66
|
+
...publishBase,
|
|
67
|
+
markSchemeId: z.string(),
|
|
68
|
+
})
|
|
69
|
+
)
|
|
70
|
+
.mutation(({ ctx, input }) =>
|
|
71
|
+
publishMarkSchemeListing(ctx.user!.id, input)
|
|
72
|
+
),
|
|
73
|
+
|
|
74
|
+
publishWorksheet: protectedProcedure
|
|
75
|
+
.input(
|
|
76
|
+
z.object({
|
|
77
|
+
...publishBase,
|
|
78
|
+
worksheetId: z.string(),
|
|
79
|
+
})
|
|
80
|
+
)
|
|
81
|
+
.mutation(({ ctx, input }) =>
|
|
82
|
+
publishWorksheetListing(ctx.user!.id, input)
|
|
83
|
+
),
|
|
84
|
+
|
|
85
|
+
publishFile: protectedProcedure
|
|
86
|
+
.input(
|
|
87
|
+
z.object({
|
|
88
|
+
...publishBase,
|
|
89
|
+
fileId: z.string(),
|
|
90
|
+
})
|
|
91
|
+
)
|
|
92
|
+
.mutation(({ ctx, input }) => publishFileListing(ctx.user!.id, input)),
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Import / download a listing copy into the caller's class, department,
|
|
96
|
+
* or storage folder.
|
|
97
|
+
*/
|
|
98
|
+
import: protectedProcedure
|
|
99
|
+
.input(
|
|
100
|
+
z.object({
|
|
101
|
+
listingId: z.string(),
|
|
102
|
+
classId: z.string().optional(),
|
|
103
|
+
departmentId: z.string().optional(),
|
|
104
|
+
folderId: z.string().optional(),
|
|
105
|
+
name: z.string().trim().min(1).max(160).optional(),
|
|
106
|
+
})
|
|
107
|
+
)
|
|
108
|
+
.mutation(({ ctx, input }) =>
|
|
109
|
+
importMarketplaceListing(ctx.user!.id, input)
|
|
110
|
+
),
|
|
111
|
+
|
|
112
|
+
report: protectedProcedure
|
|
113
|
+
.input(z.object({ listingId: z.string() }))
|
|
114
|
+
.mutation(({ ctx, input }) =>
|
|
115
|
+
reportMarketplaceListing(ctx.user!.id, input.listingId)
|
|
116
|
+
),
|
|
117
|
+
|
|
118
|
+
setHidden: protectedProcedure
|
|
119
|
+
.input(
|
|
120
|
+
z.object({
|
|
121
|
+
listingId: z.string(),
|
|
122
|
+
isHidden: z.boolean(),
|
|
123
|
+
})
|
|
124
|
+
)
|
|
125
|
+
.mutation(({ ctx, input }) =>
|
|
126
|
+
hideMarketplaceListing(ctx.user!.id, input.listingId, input.isHidden)
|
|
127
|
+
),
|
|
128
|
+
|
|
129
|
+
unpublish: protectedProcedure
|
|
130
|
+
.input(z.object({ listingId: z.string() }))
|
|
131
|
+
.mutation(({ ctx, input }) =>
|
|
132
|
+
unpublishMarketplaceListing(ctx.user!.id, input.listingId)
|
|
133
|
+
),
|
|
134
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
createTRPCRouter,
|
|
4
|
+
protectedClassMemberProcedure,
|
|
5
|
+
protectedTeacherProcedure,
|
|
6
|
+
} from "../trpc.js";
|
|
7
|
+
import {
|
|
8
|
+
createModuleItemRecord,
|
|
9
|
+
deleteModuleItemRecord,
|
|
10
|
+
getModuleItem,
|
|
11
|
+
listModuleItemsForClass,
|
|
12
|
+
listModuleItemsForSection,
|
|
13
|
+
reorderModuleItems,
|
|
14
|
+
updateModuleItemRecord,
|
|
15
|
+
} from "../services/moduleItem.js";
|
|
16
|
+
|
|
17
|
+
const directFileSchema = z.object({
|
|
18
|
+
name: z.string(),
|
|
19
|
+
type: z.string(),
|
|
20
|
+
size: z.number(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const moduleItemTypeSchema = z.enum(["PAGE", "FILES", "VIDEO"]);
|
|
24
|
+
|
|
25
|
+
export const moduleItemRouter = createTRPCRouter({
|
|
26
|
+
listByClass: protectedClassMemberProcedure
|
|
27
|
+
.input(z.object({ classId: z.string() }))
|
|
28
|
+
.query(({ ctx, input }) =>
|
|
29
|
+
listModuleItemsForClass(input.classId, ctx.user!.id)
|
|
30
|
+
),
|
|
31
|
+
|
|
32
|
+
listBySection: protectedClassMemberProcedure
|
|
33
|
+
.input(z.object({ sectionId: z.string() }))
|
|
34
|
+
.query(({ ctx, input }) =>
|
|
35
|
+
listModuleItemsForSection(input.sectionId, ctx.user!.id)
|
|
36
|
+
),
|
|
37
|
+
|
|
38
|
+
get: protectedClassMemberProcedure
|
|
39
|
+
.input(z.object({ id: z.string() }))
|
|
40
|
+
.query(({ ctx, input }) => getModuleItem(input.id, ctx.user!.id)),
|
|
41
|
+
|
|
42
|
+
create: protectedTeacherProcedure
|
|
43
|
+
.input(
|
|
44
|
+
z.object({
|
|
45
|
+
classId: z.string(),
|
|
46
|
+
sectionId: z.string(),
|
|
47
|
+
title: z.string().min(1).max(500),
|
|
48
|
+
type: moduleItemTypeSchema,
|
|
49
|
+
body: z.string().max(200_000).nullable().optional(),
|
|
50
|
+
published: z.boolean().optional(),
|
|
51
|
+
files: z.array(directFileSchema).optional(),
|
|
52
|
+
existingFileIds: z.array(z.string()).optional(),
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
.mutation(({ ctx, input }) => createModuleItemRecord(ctx.user!.id, input)),
|
|
56
|
+
|
|
57
|
+
update: protectedTeacherProcedure
|
|
58
|
+
.input(
|
|
59
|
+
z.object({
|
|
60
|
+
classId: z.string(),
|
|
61
|
+
id: z.string(),
|
|
62
|
+
title: z.string().min(1).max(500).optional(),
|
|
63
|
+
type: moduleItemTypeSchema.optional(),
|
|
64
|
+
body: z.string().max(200_000).nullable().optional(),
|
|
65
|
+
published: z.boolean().optional(),
|
|
66
|
+
sectionId: z.string().optional(),
|
|
67
|
+
order: z.number().int().nullable().optional(),
|
|
68
|
+
files: z.array(directFileSchema).optional(),
|
|
69
|
+
existingFileIds: z.array(z.string()).optional(),
|
|
70
|
+
})
|
|
71
|
+
)
|
|
72
|
+
.mutation(({ ctx, input }) => updateModuleItemRecord(ctx.user!.id, input)),
|
|
73
|
+
|
|
74
|
+
reorder: protectedTeacherProcedure
|
|
75
|
+
.input(
|
|
76
|
+
z.object({
|
|
77
|
+
classId: z.string(),
|
|
78
|
+
sectionId: z.string(),
|
|
79
|
+
orderedIds: z.array(z.string()),
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
.mutation(({ ctx, input }) => reorderModuleItems(ctx.user!.id, input)),
|
|
83
|
+
|
|
84
|
+
delete: protectedTeacherProcedure
|
|
85
|
+
.input(z.object({ classId: z.string(), id: z.string() }))
|
|
86
|
+
.mutation(({ ctx, input }) =>
|
|
87
|
+
deleteModuleItemRecord(ctx.user!.id, input.id)
|
|
88
|
+
),
|
|
89
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createTRPCRouter, protectedProcedure } from "../trpc.js";
|
|
3
|
+
import {
|
|
4
|
+
getChildAttendance,
|
|
5
|
+
getChildGrades,
|
|
6
|
+
linkParentToStudent,
|
|
7
|
+
listMyChildren,
|
|
8
|
+
listParentLinks,
|
|
9
|
+
unlinkParentFromStudent,
|
|
10
|
+
} from "../services/parentPortal.js";
|
|
11
|
+
|
|
12
|
+
export const parentRouter = createTRPCRouter({
|
|
13
|
+
linkStudent: protectedProcedure
|
|
14
|
+
.input(
|
|
15
|
+
z.object({
|
|
16
|
+
schoolId: z.string(),
|
|
17
|
+
parentUserId: z.string(),
|
|
18
|
+
studentUserId: z.string(),
|
|
19
|
+
})
|
|
20
|
+
)
|
|
21
|
+
.mutation(({ ctx, input }) => linkParentToStudent(ctx.user!.id, input)),
|
|
22
|
+
|
|
23
|
+
unlinkStudent: protectedProcedure
|
|
24
|
+
.input(
|
|
25
|
+
z.object({
|
|
26
|
+
schoolId: z.string(),
|
|
27
|
+
parentUserId: z.string(),
|
|
28
|
+
studentUserId: z.string(),
|
|
29
|
+
})
|
|
30
|
+
)
|
|
31
|
+
.mutation(({ ctx, input }) => unlinkParentFromStudent(ctx.user!.id, input)),
|
|
32
|
+
|
|
33
|
+
listLinks: protectedProcedure
|
|
34
|
+
.input(
|
|
35
|
+
z.object({
|
|
36
|
+
schoolId: z.string(),
|
|
37
|
+
parentUserId: z.string().optional(),
|
|
38
|
+
studentUserId: z.string().optional(),
|
|
39
|
+
})
|
|
40
|
+
)
|
|
41
|
+
.query(({ ctx, input }) => listParentLinks(ctx.user!.id, input)),
|
|
42
|
+
|
|
43
|
+
listMyChildren: protectedProcedure
|
|
44
|
+
.input(z.object({ schoolId: z.string() }))
|
|
45
|
+
.query(({ ctx, input }) => listMyChildren(ctx.user!.id, input.schoolId)),
|
|
46
|
+
|
|
47
|
+
getChildAttendance: protectedProcedure
|
|
48
|
+
.input(
|
|
49
|
+
z.object({
|
|
50
|
+
schoolId: z.string(),
|
|
51
|
+
studentUserId: z.string(),
|
|
52
|
+
classId: z.string().optional(),
|
|
53
|
+
from: z.date().optional(),
|
|
54
|
+
to: z.date().optional(),
|
|
55
|
+
})
|
|
56
|
+
)
|
|
57
|
+
.query(({ ctx, input }) => getChildAttendance(ctx.user!.id, input)),
|
|
58
|
+
|
|
59
|
+
getChildGrades: protectedProcedure
|
|
60
|
+
.input(
|
|
61
|
+
z.object({
|
|
62
|
+
schoolId: z.string(),
|
|
63
|
+
studentUserId: z.string(),
|
|
64
|
+
classId: z.string().optional(),
|
|
65
|
+
})
|
|
66
|
+
)
|
|
67
|
+
.query(({ ctx, input }) => getChildGrades(ctx.user!.id, input)),
|
|
68
|
+
});
|