@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.
- 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 +547 -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 +180 -0
- package/dist/models/marketplace.d.ts.map +1 -0
- package/dist/models/marketplace.js +116 -0
- package/dist/models/marketplace.js.map +1 -0
- package/dist/models/moduleItem.d.ts +308 -0
- package/dist/models/moduleItem.d.ts.map +1 -0
- package/dist/models/moduleItem.js +93 -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 +12024 -7778
- 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 +61 -0
- package/dist/routers/moduleItem.js.map +1 -0
- package/dist/routers/parent.d.ts +170 -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 +110 -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 +242 -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 +327 -10
- package/dist/services/attendance.d.ts.map +1 -1
- package/dist/services/attendance.js +389 -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 +34 -2
- package/dist/services/class.d.ts.map +1 -1
- package/dist/services/class.js +27 -4
- 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 +330 -0
- package/dist/services/fees.js.map +1 -0
- package/dist/services/feesAuthz.d.ts +46 -0
- package/dist/services/feesAuthz.d.ts.map +1 -0
- package/dist/services/feesAuthz.js +49 -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 +631 -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 +204 -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 +131 -0
- package/dist/services/parentPortal.d.ts.map +1 -0
- package/dist/services/parentPortal.js +314 -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 +98 -54
- 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 +249 -0
- package/dist/services/studentImport.js.map +1 -0
- package/dist/services/transcript.d.ts +60 -0
- package/dist/services/transcript.d.ts.map +1 -0
- package/dist/services/transcript.js +231 -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 +402 -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 +702 -73
- package/src/models/class.ts +1 -0
- package/src/models/fees.ts +349 -0
- package/src/models/marketplace.ts +161 -0
- package/src/models/moduleItem.ts +125 -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 +91 -0
- package/src/routers/parent.ts +68 -0
- package/src/routers/school.ts +149 -1
- package/src/routers/worksheet.ts +11 -0
- package/src/services/academicCalendar.ts +327 -0
- package/src/services/assignment.ts +122 -12
- package/src/services/attendance.ts +552 -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 +26 -2
- package/src/services/fees.ts +447 -0
- package/src/services/feesAuthz.ts +73 -0
- package/src/services/gradebook.ts +70 -0
- package/src/services/idCard.ts +147 -0
- package/src/services/marketplace.ts +790 -0
- package/src/services/moduleItem.ts +298 -0
- package/src/services/notification.ts +43 -0
- package/src/services/parentPortal.ts +367 -0
- package/src/services/school.ts +100 -54
- package/src/services/studentImport.ts +285 -0
- package/src/services/transcript.ts +301 -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
package/prisma/schema.prisma
CHANGED
|
@@ -103,6 +103,10 @@ enum SchoolMembershipRole {
|
|
|
103
103
|
ADMIN
|
|
104
104
|
TEACHER
|
|
105
105
|
STUDENT
|
|
106
|
+
/// Nepal-pilot: fee/payment operations (authz stubs until A2 fees land).
|
|
107
|
+
ACCOUNTANT
|
|
108
|
+
/// Nepal-pilot: guardian linked to one or more students via ParentStudentLink.
|
|
109
|
+
PARENT
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
enum SchoolMembershipStatus {
|
|
@@ -118,24 +122,99 @@ enum SchoolInviteStatus {
|
|
|
118
122
|
EXPIRED
|
|
119
123
|
}
|
|
120
124
|
|
|
125
|
+
/// Marketplace listing resource kinds for B1 v1.
|
|
126
|
+
/// Exercise/poll/kahoot types are reserved for a later milestone — do not add
|
|
127
|
+
/// them here until that product surface ships.
|
|
128
|
+
enum MarketplaceListingType {
|
|
129
|
+
MARKSCHEME
|
|
130
|
+
WORKSHEET
|
|
131
|
+
FILE
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
enum MarketplaceVisibility {
|
|
135
|
+
SCHOOL
|
|
136
|
+
PUBLIC
|
|
137
|
+
}
|
|
138
|
+
|
|
121
139
|
model School {
|
|
122
140
|
id String @id @default(uuid())
|
|
123
141
|
name String
|
|
124
142
|
description String?
|
|
125
143
|
logo File? @relation("SchoolLogo", references: [id], fields: [logoId])
|
|
126
144
|
logoId String?
|
|
145
|
+
/// Optional PDF/image letterhead used when stamping branded PDFs
|
|
146
|
+
/// (fee invoices/receipts, transcripts).
|
|
147
|
+
letterhead File? @relation("SchoolLetterhead", references: [id], fields: [letterheadFileId])
|
|
148
|
+
letterheadFileId String?
|
|
127
149
|
subdomain String? @unique
|
|
128
150
|
createdAt DateTime @default(now())
|
|
129
151
|
updatedAt DateTime @updatedAt
|
|
130
152
|
|
|
131
|
-
users
|
|
132
|
-
memberships
|
|
133
|
-
invites
|
|
134
|
-
classes
|
|
135
|
-
departments
|
|
136
|
-
tags
|
|
137
|
-
storageRoot
|
|
138
|
-
permissions
|
|
153
|
+
users User[]
|
|
154
|
+
memberships SchoolMembership[]
|
|
155
|
+
invites SchoolInvite[]
|
|
156
|
+
classes Class[]
|
|
157
|
+
departments Department[]
|
|
158
|
+
tags Tag[]
|
|
159
|
+
storageRoot Folder? @relation("SchoolStorageRoot")
|
|
160
|
+
permissions Permission[] @relation("SchoolPermissions")
|
|
161
|
+
excusals StudentExcusal[]
|
|
162
|
+
feePlans FeePlan[]
|
|
163
|
+
feeInvoices FeeInvoice[]
|
|
164
|
+
feePayments FeePayment[]
|
|
165
|
+
marketplaceListings MarketplaceListing[]
|
|
166
|
+
academicYears AcademicYear[]
|
|
167
|
+
parentLinks ParentStudentLink[]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/// School academic calendar year (e.g. "2025-2026" or "2082"). No BS calendar logic.
|
|
171
|
+
model AcademicYear {
|
|
172
|
+
id String @id @default(uuid())
|
|
173
|
+
schoolId String
|
|
174
|
+
school School @relation(fields: [schoolId], references: [id], onDelete: Cascade)
|
|
175
|
+
name String
|
|
176
|
+
startDate DateTime
|
|
177
|
+
endDate DateTime
|
|
178
|
+
isCurrent Boolean @default(false)
|
|
179
|
+
createdAt DateTime @default(now())
|
|
180
|
+
updatedAt DateTime @updatedAt
|
|
181
|
+
|
|
182
|
+
terms AcademicTerm[]
|
|
183
|
+
|
|
184
|
+
@@unique([schoolId, name])
|
|
185
|
+
@@index([schoolId, isCurrent])
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
model AcademicTerm {
|
|
189
|
+
id String @id @default(uuid())
|
|
190
|
+
academicYearId String
|
|
191
|
+
academicYear AcademicYear @relation(fields: [academicYearId], references: [id], onDelete: Cascade)
|
|
192
|
+
name String
|
|
193
|
+
startDate DateTime
|
|
194
|
+
endDate DateTime
|
|
195
|
+
isCurrent Boolean @default(false)
|
|
196
|
+
createdAt DateTime @default(now())
|
|
197
|
+
updatedAt DateTime @updatedAt
|
|
198
|
+
|
|
199
|
+
@@unique([academicYearId, name])
|
|
200
|
+
@@index([academicYearId, isCurrent])
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/// Links a PARENT membership user to a STUDENT membership user within a school.
|
|
204
|
+
model ParentStudentLink {
|
|
205
|
+
id String @id @default(uuid())
|
|
206
|
+
schoolId String
|
|
207
|
+
school School @relation(fields: [schoolId], references: [id], onDelete: Cascade)
|
|
208
|
+
parentUserId String
|
|
209
|
+
parent User @relation("ParentLinks", fields: [parentUserId], references: [id], onDelete: Cascade)
|
|
210
|
+
studentUserId String
|
|
211
|
+
student User @relation("StudentParentLinks", fields: [studentUserId], references: [id], onDelete: Cascade)
|
|
212
|
+
createdAt DateTime @default(now())
|
|
213
|
+
updatedAt DateTime @updatedAt
|
|
214
|
+
|
|
215
|
+
@@unique([schoolId, parentUserId, studentUserId])
|
|
216
|
+
@@index([schoolId, parentUserId])
|
|
217
|
+
@@index([schoolId, studentUserId])
|
|
139
218
|
}
|
|
140
219
|
|
|
141
220
|
model Department {
|
|
@@ -218,10 +297,18 @@ model User {
|
|
|
218
297
|
lateAttendance Attendance[] @relation("LateAttendance")
|
|
219
298
|
absentAttendance Attendance[] @relation("AbsentAttendance")
|
|
220
299
|
|
|
300
|
+
attendanceRecords AttendanceRecord[] @relation("AttendanceRecordStudent")
|
|
301
|
+
updatedAttendanceRecords AttendanceRecord[] @relation("AttendanceRecordUpdatedBy")
|
|
302
|
+
createdExcusals StudentExcusal[] @relation("StudentExcusalCreatedBy")
|
|
303
|
+
revokedExcusals StudentExcusal[] @relation("StudentExcusalRevokedBy")
|
|
304
|
+
studentExcusals StudentExcusalStudent[]
|
|
305
|
+
|
|
221
306
|
school School? @relation(fields: [schoolId], references: [id])
|
|
222
307
|
schoolId String?
|
|
223
308
|
schoolMemberships SchoolMembership[]
|
|
224
309
|
sentSchoolInvites SchoolInvite[] @relation("SchoolInviteInvitedBy")
|
|
310
|
+
parentLinks ParentStudentLink[] @relation("ParentLinks")
|
|
311
|
+
studentParentLinks ParentStudentLink[] @relation("StudentParentLinks")
|
|
225
312
|
|
|
226
313
|
departments Department[] @relation("UserDepartments")
|
|
227
314
|
tags Tag[] @relation("UserTags")
|
|
@@ -243,6 +330,11 @@ model User {
|
|
|
243
330
|
discussionReads DiscussionRead[]
|
|
244
331
|
customGradeEntries CustomGradeEntry[] @relation("UserCustomGradeEntries")
|
|
245
332
|
fileAnnotations FileAnnotation[] @relation("AuthoredFileAnnotations")
|
|
333
|
+
marketplaceListings MarketplaceListing[] @relation("MarketplaceListingAuthor")
|
|
334
|
+
|
|
335
|
+
feePlanEnrollments FeePlanEnrollment[]
|
|
336
|
+
feeInvoices FeeInvoice[]
|
|
337
|
+
feePaymentsRecorded FeePayment[] @relation("FeePaymentRecordedBy")
|
|
246
338
|
}
|
|
247
339
|
|
|
248
340
|
model SchoolMembership {
|
|
@@ -336,6 +428,10 @@ model Class {
|
|
|
336
428
|
studentsCanCreateDiscussions Boolean @default(true)
|
|
337
429
|
studentsCanReply Boolean @default(true)
|
|
338
430
|
|
|
431
|
+
/// Teacher-controlled ClassSidebar visibility. Keys match nav hrefs
|
|
432
|
+
/// without leading slash (e.g. "assignments", "quizzes"). Null = all defaults on.
|
|
433
|
+
sidebarFeatures Json?
|
|
434
|
+
|
|
339
435
|
gradeCategories GradeCategory[]
|
|
340
436
|
customGradeColumns CustomGradeColumn[]
|
|
341
437
|
|
|
@@ -407,6 +503,7 @@ model MarkScheme {
|
|
|
407
503
|
structured String
|
|
408
504
|
assignments Assignment[]
|
|
409
505
|
tags Tag[] @relation("MarkSchemeTags")
|
|
506
|
+
marketplaceListings MarketplaceListing[]
|
|
410
507
|
|
|
411
508
|
@@index([classId])
|
|
412
509
|
@@index([departmentId])
|
|
@@ -509,12 +606,17 @@ model File {
|
|
|
509
606
|
discussionReply DiscussionReply? @relation("DiscussionReplyFiles", fields: [discussionReplyId], references: [id], onDelete: Cascade)
|
|
510
607
|
discussionReplyId String?
|
|
511
608
|
|
|
609
|
+
moduleItem ModuleItem? @relation("ModuleItemFiles", fields: [moduleItemId], references: [id], onDelete: Cascade)
|
|
610
|
+
moduleItemId String?
|
|
611
|
+
|
|
512
612
|
schools School[] @relation("SchoolLogo")
|
|
613
|
+
schoolLetterheads School[] @relation("SchoolLetterhead")
|
|
513
614
|
|
|
514
615
|
schoolDevelopementProgram SchoolDevelopementProgram? @relation("SchoolDevelopementProgramSupportingDocumentation", fields: [schoolDevelopementProgramId], references: [id], onDelete: Cascade)
|
|
515
616
|
schoolDevelopementProgramId String?
|
|
516
617
|
|
|
517
618
|
fileAnnotations FileAnnotation[] @relation("FileAnnotations")
|
|
619
|
+
marketplaceListings MarketplaceListing[]
|
|
518
620
|
}
|
|
519
621
|
|
|
520
622
|
enum FileAnnotationType {
|
|
@@ -585,6 +687,13 @@ model Assignment {
|
|
|
585
687
|
gradeCategoryId String?
|
|
586
688
|
worksheets Worksheet[] @relation("AssignmentWorksheets")
|
|
587
689
|
targetedBySubmissions Submission[] @relation("SubmissionTargetedAssignment")
|
|
690
|
+
|
|
691
|
+
/// Optional timed window for QUIZ/TEST (minutes). Null = untimed.
|
|
692
|
+
timeLimitMinutes Int?
|
|
693
|
+
/// When true, students cannot unsubmit after submitting (typical for quizzes).
|
|
694
|
+
singleAttempt Boolean @default(false)
|
|
695
|
+
/// When false, file uploads and (re)submits after due date are rejected.
|
|
696
|
+
allowLateSubmissions Boolean @default(true)
|
|
588
697
|
}
|
|
589
698
|
|
|
590
699
|
model Announcement {
|
|
@@ -773,10 +882,35 @@ model Section {
|
|
|
773
882
|
classId String
|
|
774
883
|
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
|
|
775
884
|
assignments Assignment[]
|
|
885
|
+
moduleItems ModuleItem[]
|
|
776
886
|
color String? @default("#3B82F6")
|
|
777
887
|
order Int?
|
|
778
888
|
}
|
|
779
889
|
|
|
890
|
+
/// Canvas-style module content: a rich page, a file collection, or a video item.
|
|
891
|
+
enum ModuleItemType {
|
|
892
|
+
PAGE
|
|
893
|
+
FILES
|
|
894
|
+
VIDEO
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
model ModuleItem {
|
|
898
|
+
id String @id @default(uuid())
|
|
899
|
+
sectionId String
|
|
900
|
+
section Section @relation(fields: [sectionId], references: [id], onDelete: Cascade)
|
|
901
|
+
title String
|
|
902
|
+
type ModuleItemType
|
|
903
|
+
/// Rich HTML/markdown body for PAGE items.
|
|
904
|
+
body String?
|
|
905
|
+
order Int?
|
|
906
|
+
published Boolean @default(true)
|
|
907
|
+
files File[] @relation("ModuleItemFiles")
|
|
908
|
+
createdAt DateTime @default(now())
|
|
909
|
+
updatedAt DateTime @updatedAt
|
|
910
|
+
|
|
911
|
+
@@index([sectionId])
|
|
912
|
+
}
|
|
913
|
+
|
|
780
914
|
enum SessionType {
|
|
781
915
|
AUTH
|
|
782
916
|
EMAIL_VERIFICATION
|
|
@@ -811,6 +945,13 @@ model Event {
|
|
|
811
945
|
attendance Attendance[]
|
|
812
946
|
}
|
|
813
947
|
|
|
948
|
+
enum AttendanceStatus {
|
|
949
|
+
PRESENT
|
|
950
|
+
LATE
|
|
951
|
+
ABSENT
|
|
952
|
+
EXCUSED
|
|
953
|
+
}
|
|
954
|
+
|
|
814
955
|
model Attendance {
|
|
815
956
|
id String @id @default(uuid())
|
|
816
957
|
date DateTime @default(now())
|
|
@@ -821,9 +962,68 @@ model Attendance {
|
|
|
821
962
|
event Event? @relation(fields: [eventId], references: [id], onDelete: Cascade)
|
|
822
963
|
eventId String?
|
|
823
964
|
|
|
824
|
-
present User[]
|
|
825
|
-
late User[]
|
|
826
|
-
absent User[]
|
|
965
|
+
present User[] @relation("PresentAttendance")
|
|
966
|
+
late User[] @relation("LateAttendance")
|
|
967
|
+
absent User[] @relation("AbsentAttendance")
|
|
968
|
+
records AttendanceRecord[]
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/// Per-student status for an attendance session (dual-written with legacy present/late/absent lists).
|
|
972
|
+
model AttendanceRecord {
|
|
973
|
+
id String @id @default(uuid())
|
|
974
|
+
attendanceId String
|
|
975
|
+
studentId String
|
|
976
|
+
status AttendanceStatus
|
|
977
|
+
note String?
|
|
978
|
+
excusedByExcusalId String?
|
|
979
|
+
updatedById String?
|
|
980
|
+
createdAt DateTime @default(now())
|
|
981
|
+
updatedAt DateTime @updatedAt
|
|
982
|
+
|
|
983
|
+
attendance Attendance @relation(fields: [attendanceId], references: [id], onDelete: Cascade)
|
|
984
|
+
student User @relation("AttendanceRecordStudent", fields: [studentId], references: [id], onDelete: Cascade)
|
|
985
|
+
excusedByExcusal StudentExcusal? @relation(fields: [excusedByExcusalId], references: [id], onDelete: SetNull)
|
|
986
|
+
updatedBy User? @relation("AttendanceRecordUpdatedBy", fields: [updatedById], references: [id], onDelete: SetNull)
|
|
987
|
+
|
|
988
|
+
@@unique([attendanceId, studentId])
|
|
989
|
+
@@index([studentId, status])
|
|
990
|
+
@@index([excusedByExcusalId])
|
|
991
|
+
@@index([attendanceId])
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/// School-admin excusal covering one or more students for a date range.
|
|
995
|
+
model StudentExcusal {
|
|
996
|
+
id String @id @default(uuid())
|
|
997
|
+
schoolId String
|
|
998
|
+
startDate DateTime @db.Date
|
|
999
|
+
endDate DateTime @db.Date
|
|
1000
|
+
reason String
|
|
1001
|
+
note String?
|
|
1002
|
+
createdById String
|
|
1003
|
+
createdAt DateTime @default(now())
|
|
1004
|
+
updatedAt DateTime @updatedAt
|
|
1005
|
+
revokedAt DateTime?
|
|
1006
|
+
revokedById String?
|
|
1007
|
+
|
|
1008
|
+
school School @relation(fields: [schoolId], references: [id], onDelete: Cascade)
|
|
1009
|
+
createdBy User @relation("StudentExcusalCreatedBy", fields: [createdById], references: [id], onDelete: Cascade)
|
|
1010
|
+
revokedBy User? @relation("StudentExcusalRevokedBy", fields: [revokedById], references: [id], onDelete: SetNull)
|
|
1011
|
+
students StudentExcusalStudent[]
|
|
1012
|
+
attendanceRecords AttendanceRecord[]
|
|
1013
|
+
|
|
1014
|
+
@@index([schoolId, startDate, endDate])
|
|
1015
|
+
@@index([schoolId, revokedAt])
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
model StudentExcusalStudent {
|
|
1019
|
+
excusalId String
|
|
1020
|
+
studentId String
|
|
1021
|
+
|
|
1022
|
+
excusal StudentExcusal @relation(fields: [excusalId], references: [id], onDelete: Cascade)
|
|
1023
|
+
student User @relation(fields: [studentId], references: [id], onDelete: Cascade)
|
|
1024
|
+
|
|
1025
|
+
@@id([excusalId, studentId])
|
|
1026
|
+
@@index([studentId])
|
|
827
1027
|
}
|
|
828
1028
|
|
|
829
1029
|
enum NotificationType {
|
|
@@ -834,6 +1034,10 @@ enum NotificationType {
|
|
|
834
1034
|
DISCUSSION_MENTION
|
|
835
1035
|
ANNOUNCEMENT
|
|
836
1036
|
ATTENDANCE
|
|
1037
|
+
/// Fee due / paid / reminder events (A2 fees will emit these).
|
|
1038
|
+
FEES
|
|
1039
|
+
/// Excusal request/decision hooks (A1 owns StudentExcusal; emitters call helpers).
|
|
1040
|
+
EXCUSAL
|
|
837
1041
|
SYSTEM
|
|
838
1042
|
}
|
|
839
1043
|
|
|
@@ -987,6 +1191,7 @@ model Worksheet {
|
|
|
987
1191
|
|
|
988
1192
|
status JobStatus? @default(NOT_STARTED)
|
|
989
1193
|
tags ClassTag[] @relation("WorksheetToTag")
|
|
1194
|
+
marketplaceListings MarketplaceListing[]
|
|
990
1195
|
|
|
991
1196
|
@@unique([classId, sourceUrl])
|
|
992
1197
|
}
|
|
@@ -1005,6 +1210,13 @@ model WorksheetQuestion {
|
|
|
1005
1210
|
createdAt DateTime @default(now())
|
|
1006
1211
|
updatedAt DateTime @updatedAt
|
|
1007
1212
|
studentResponses StudentQuestionProgress[]
|
|
1213
|
+
|
|
1214
|
+
/// Parent/child subquestions (e.g. multi-part worksheet items).
|
|
1215
|
+
parentQuestionId String?
|
|
1216
|
+
parentQuestion WorksheetQuestion? @relation("WorksheetSubquestions", fields: [parentQuestionId], references: [id], onDelete: Cascade)
|
|
1217
|
+
subquestions WorksheetQuestion[] @relation("WorksheetSubquestions")
|
|
1218
|
+
|
|
1219
|
+
@@index([parentQuestionId])
|
|
1008
1220
|
}
|
|
1009
1221
|
|
|
1010
1222
|
model StudentWorksheetResponse {
|
|
@@ -1180,6 +1392,47 @@ enum PermissionLevel {
|
|
|
1180
1392
|
WRITE
|
|
1181
1393
|
}
|
|
1182
1394
|
|
|
1395
|
+
/// User-created shareable content listing (markschemes, worksheets, files).
|
|
1396
|
+
/// Isolated Marketplace* tables — must not share schema with Attendance/Fee.
|
|
1397
|
+
/// Exercise/poll types are intentionally omitted from MarketplaceListingType for v1.
|
|
1398
|
+
model MarketplaceListing {
|
|
1399
|
+
id String @id @default(uuid())
|
|
1400
|
+
type MarketplaceListingType
|
|
1401
|
+
title String
|
|
1402
|
+
description String?
|
|
1403
|
+
authorId String
|
|
1404
|
+
author User @relation("MarketplaceListingAuthor", fields: [authorId], references: [id], onDelete: Cascade)
|
|
1405
|
+
schoolId String?
|
|
1406
|
+
school School? @relation(fields: [schoolId], references: [id], onDelete: SetNull)
|
|
1407
|
+
visibility MarketplaceVisibility @default(SCHOOL)
|
|
1408
|
+
|
|
1409
|
+
/// Live refs to the source resource (optional; source may later be deleted).
|
|
1410
|
+
markSchemeId String?
|
|
1411
|
+
markScheme MarkScheme? @relation(fields: [markSchemeId], references: [id], onDelete: SetNull)
|
|
1412
|
+
worksheetId String?
|
|
1413
|
+
worksheet Worksheet? @relation(fields: [worksheetId], references: [id], onDelete: SetNull)
|
|
1414
|
+
fileId String?
|
|
1415
|
+
file File? @relation(fields: [fileId], references: [id], onDelete: SetNull)
|
|
1416
|
+
|
|
1417
|
+
/// Snapshot captured at publish time so import survives source deletion.
|
|
1418
|
+
/// Shape varies by type — see marketplace service publish helpers.
|
|
1419
|
+
payload Json
|
|
1420
|
+
|
|
1421
|
+
tags String[] @default([])
|
|
1422
|
+
|
|
1423
|
+
createdAt DateTime @default(now())
|
|
1424
|
+
updatedAt DateTime @updatedAt
|
|
1425
|
+
|
|
1426
|
+
/// C10 moderation stubs — light reporting only; no full moderation queue yet.
|
|
1427
|
+
reportCount Int @default(0)
|
|
1428
|
+
isHidden Boolean @default(false)
|
|
1429
|
+
|
|
1430
|
+
@@index([type, visibility, createdAt])
|
|
1431
|
+
@@index([schoolId, visibility, createdAt])
|
|
1432
|
+
@@index([authorId])
|
|
1433
|
+
@@index([isHidden])
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1183
1436
|
/// Explicit ACL grant on a folder. Sits on top of (and is purely additive
|
|
1184
1437
|
/// to) the scope-derived defaults computed from FolderScope. Files inherit
|
|
1185
1438
|
/// from their parent folder — file-level overrides are deliberately deferred
|
|
@@ -1224,3 +1477,110 @@ model Permission {
|
|
|
1224
1477
|
@@index([departmentId])
|
|
1225
1478
|
@@index([schoolId])
|
|
1226
1479
|
}
|
|
1480
|
+
|
|
1481
|
+
// ---------------------------------------------------------------------------
|
|
1482
|
+
// A2 — Monthly student fees + manual payment ledger (Nepal pilot)
|
|
1483
|
+
// Billing period = FeeInvoice.year + FeeInvoice.month (no separate term table;
|
|
1484
|
+
// AcademicYear/Term from other pilots can attach later without conflict).
|
|
1485
|
+
// ---------------------------------------------------------------------------
|
|
1486
|
+
|
|
1487
|
+
enum FeePaymentMethod {
|
|
1488
|
+
CASH
|
|
1489
|
+
BANK
|
|
1490
|
+
ESEWA_REF
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
enum FeeInvoiceStatus {
|
|
1494
|
+
UNPAID
|
|
1495
|
+
PARTIAL
|
|
1496
|
+
PAID
|
|
1497
|
+
VOID
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/// Recurring monthly fee definition (e.g. "Tuition", "Transport").
|
|
1501
|
+
model FeePlan {
|
|
1502
|
+
id String @id @default(uuid())
|
|
1503
|
+
schoolId String
|
|
1504
|
+
name String
|
|
1505
|
+
description String?
|
|
1506
|
+
/// Whole NPR amount charged per billing month.
|
|
1507
|
+
amountNpr Int
|
|
1508
|
+
currency String @default("NPR")
|
|
1509
|
+
isActive Boolean @default(true)
|
|
1510
|
+
createdAt DateTime @default(now())
|
|
1511
|
+
updatedAt DateTime @updatedAt
|
|
1512
|
+
|
|
1513
|
+
school School @relation(fields: [schoolId], references: [id], onDelete: Cascade)
|
|
1514
|
+
enrollments FeePlanEnrollment[]
|
|
1515
|
+
invoices FeeInvoice[]
|
|
1516
|
+
|
|
1517
|
+
@@index([schoolId])
|
|
1518
|
+
@@unique([schoolId, name])
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
/// Students enrolled on a fee plan. Empty enrollments = all ACTIVE STUDENT members at invoice generation.
|
|
1522
|
+
model FeePlanEnrollment {
|
|
1523
|
+
id String @id @default(uuid())
|
|
1524
|
+
feePlanId String
|
|
1525
|
+
studentId String
|
|
1526
|
+
createdAt DateTime @default(now())
|
|
1527
|
+
|
|
1528
|
+
feePlan FeePlan @relation(fields: [feePlanId], references: [id], onDelete: Cascade)
|
|
1529
|
+
student User @relation(fields: [studentId], references: [id], onDelete: Cascade)
|
|
1530
|
+
|
|
1531
|
+
@@unique([feePlanId, studentId])
|
|
1532
|
+
@@index([studentId])
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
model FeeInvoice {
|
|
1536
|
+
id String @id @default(uuid())
|
|
1537
|
+
schoolId String
|
|
1538
|
+
feePlanId String
|
|
1539
|
+
studentId String
|
|
1540
|
+
/// Billing period (calendar month).
|
|
1541
|
+
year Int
|
|
1542
|
+
month Int
|
|
1543
|
+
/// Snapshot of plan amount at generation time.
|
|
1544
|
+
amountNpr Int
|
|
1545
|
+
currency String @default("NPR")
|
|
1546
|
+
status FeeInvoiceStatus @default(UNPAID)
|
|
1547
|
+
dueDate DateTime? @db.Date
|
|
1548
|
+
issuedAt DateTime @default(now())
|
|
1549
|
+
notes String?
|
|
1550
|
+
createdAt DateTime @default(now())
|
|
1551
|
+
updatedAt DateTime @updatedAt
|
|
1552
|
+
|
|
1553
|
+
school School @relation(fields: [schoolId], references: [id], onDelete: Cascade)
|
|
1554
|
+
feePlan FeePlan @relation(fields: [feePlanId], references: [id], onDelete: Restrict)
|
|
1555
|
+
student User @relation(fields: [studentId], references: [id], onDelete: Cascade)
|
|
1556
|
+
payments FeePayment[]
|
|
1557
|
+
|
|
1558
|
+
@@unique([schoolId, studentId, feePlanId, year, month])
|
|
1559
|
+
@@index([schoolId, year, month])
|
|
1560
|
+
@@index([studentId])
|
|
1561
|
+
@@index([feePlanId])
|
|
1562
|
+
@@index([status])
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
model FeePayment {
|
|
1566
|
+
id String @id @default(uuid())
|
|
1567
|
+
schoolId String
|
|
1568
|
+
invoiceId String
|
|
1569
|
+
amountNpr Int
|
|
1570
|
+
method FeePaymentMethod
|
|
1571
|
+
/// Required for BANK / ESEWA_REF (cheque no., eSewa txn id, etc.).
|
|
1572
|
+
reference String?
|
|
1573
|
+
paidAt DateTime @default(now())
|
|
1574
|
+
recordedById String
|
|
1575
|
+
notes String?
|
|
1576
|
+
createdAt DateTime @default(now())
|
|
1577
|
+
updatedAt DateTime @updatedAt
|
|
1578
|
+
|
|
1579
|
+
school School @relation(fields: [schoolId], references: [id], onDelete: Cascade)
|
|
1580
|
+
invoice FeeInvoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
|
1581
|
+
recordedBy User @relation("FeePaymentRecordedBy", fields: [recordedById], references: [id], onDelete: Restrict)
|
|
1582
|
+
|
|
1583
|
+
@@index([invoiceId])
|
|
1584
|
+
@@index([schoolId])
|
|
1585
|
+
@@index([paidAt])
|
|
1586
|
+
}
|