feat: add new API Implementation Guide for Modules B, F, H
Co-authored-by: cetinmustafa83 <30570791+cetinmustafa83@users.noreply.github.com>
This commit is contained in:
11 files changed
+1800
No files matched your search
@@ -0,0 +1,90 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "exam_sessions" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"schoolId" TEXT NOT NULL,
|
||||
"assessmentId" TEXT NOT NULL,
|
||||
"studentId" TEXT NOT NULL,
|
||||
"startTime" DATETIME NOT NULL,
|
||||
"endTime" DATETIME,
|
||||
"submittedAt" DATETIME,
|
||||
"status" TEXT NOT NULL DEFAULT 'not_started',
|
||||
"score" REAL,
|
||||
"totalPoints" REAL,
|
||||
"lockdownEnabled" BOOLEAN NOT NULL DEFAULT true,
|
||||
"cameraMonitor" BOOLEAN NOT NULL DEFAULT false,
|
||||
"screenShare" BOOLEAN NOT NULL DEFAULT false,
|
||||
"environmentNotes" TEXT,
|
||||
"suspiciousActivity" TEXT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "exam_sessions_schoolId_fkey" FOREIGN KEY ("schoolId") REFERENCES "School" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT "exam_sessions_assessmentId_fkey" FOREIGN KEY ("assessmentId") REFERENCES "Assessment" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT "exam_sessions_studentId_fkey" FOREIGN KEY ("studentId") REFERENCES "Student" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "exam_answers" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"examSessionId" TEXT NOT NULL,
|
||||
"questionId" TEXT NOT NULL,
|
||||
"answer" TEXT,
|
||||
"submittedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isCorrect" BOOLEAN,
|
||||
"pointsAwarded" REAL,
|
||||
"reviewedAt" DATETIME,
|
||||
CONSTRAINT "exam_answers_examSessionId_fkey" FOREIGN KEY ("examSessionId") REFERENCES "exam_sessions" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "exam_events" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"examSessionId" TEXT NOT NULL,
|
||||
"eventType" TEXT NOT NULL,
|
||||
"severity" TEXT NOT NULL DEFAULT 'info',
|
||||
"description" TEXT,
|
||||
"timestamp" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"metadata" TEXT,
|
||||
CONSTRAINT "exam_events_examSessionId_fkey" FOREIGN KEY ("examSessionId") REFERENCES "exam_sessions" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "exam_warnings" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"examSessionId" TEXT NOT NULL,
|
||||
"studentId" TEXT NOT NULL,
|
||||
"warningType" TEXT NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"acknowledged" BOOLEAN NOT NULL DEFAULT false,
|
||||
"acknowledgedAt" DATETIME,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "exam_warnings_examSessionId_fkey" FOREIGN KEY ("examSessionId") REFERENCES "exam_sessions" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_sessions_schoolId_idx" ON "exam_sessions"("schoolId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_sessions_assessmentId_idx" ON "exam_sessions"("assessmentId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_sessions_studentId_idx" ON "exam_sessions"("studentId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_sessions_status_idx" ON "exam_sessions"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_answers_examSessionId_idx" ON "exam_answers"("examSessionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_answers_questionId_idx" ON "exam_answers"("questionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_events_examSessionId_idx" ON "exam_events"("examSessionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_events_eventType_idx" ON "exam_events"("eventType");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_warnings_examSessionId_idx" ON "exam_warnings"("examSessionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "exam_warnings_studentId_idx" ON "exam_warnings"("studentId");
|
||||
@@ -0,0 +1,60 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "notification_hubs" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"schoolId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"category" TEXT NOT NULL,
|
||||
"priority" TEXT NOT NULL DEFAULT 'normal',
|
||||
"title" TEXT NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"actionUrl" TEXT,
|
||||
"actionLabel" TEXT,
|
||||
"isRead" BOOLEAN NOT NULL DEFAULT false,
|
||||
"readAt" DATETIME,
|
||||
"isDismissed" BOOLEAN NOT NULL DEFAULT false,
|
||||
"dismissedAt" DATETIME,
|
||||
"sourceType" TEXT,
|
||||
"sourceId" TEXT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"expiresAt" DATETIME,
|
||||
CONSTRAINT "notification_hubs_schoolId_fkey" FOREIGN KEY ("schoolId") REFERENCES "School" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT "notification_hubs_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "notification_archives" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"schoolId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"originalId" TEXT,
|
||||
"title" TEXT NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"category" TEXT NOT NULL,
|
||||
"archivedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "notification_archives_schoolId_fkey" FOREIGN KEY ("schoolId") REFERENCES "School" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT "notification_archives_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notification_hubs_schoolId_idx" ON "notification_hubs"("schoolId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notification_hubs_userId_idx" ON "notification_hubs"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notification_hubs_isRead_idx" ON "notification_hubs"("isRead");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notification_hubs_category_idx" ON "notification_hubs"("category");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notification_hubs_createdAt_idx" ON "notification_hubs"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notification_archives_schoolId_idx" ON "notification_archives"("schoolId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notification_archives_userId_idx" ON "notification_archives"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notification_archives_archivedAt_idx" ON "notification_archives"("archivedAt");
|
||||
Binary file not shown.
@@ -127,6 +127,11 @@ model School {
|
||||
signageMessages SignageMessage[]
|
||||
signageSchedules SignageSchedule[]
|
||||
signageAuditLogs SignageAuditLog[]
|
||||
// Module F exam mode relations
|
||||
examSessions ExamSession[]
|
||||
// Module H notifications relations
|
||||
notificationHubs NotificationHub[]
|
||||
notificationArchives NotificationArchive[]
|
||||
}
|
||||
|
||||
model User {
|
||||
@@ -226,6 +231,9 @@ model User {
|
||||
deletionFlagsApproved DeletionFlag[] @relation("DeletionFlagApprover")
|
||||
// Module B signage relations
|
||||
signageMessagesCreated SignageMessage[]
|
||||
// Module H notifications relations
|
||||
notificationHubs NotificationHub[]
|
||||
notificationArchives NotificationArchive[]
|
||||
}
|
||||
|
||||
model SchoolYear {
|
||||
@@ -349,6 +357,8 @@ model Student {
|
||||
wellnessCheckins WellnessCheckin[]
|
||||
wellnessScores WellnessScore[]
|
||||
careerProfile CareerProfile?
|
||||
// Module F exam mode relations
|
||||
examSessions ExamSession[]
|
||||
|
||||
@@index([userId])
|
||||
}
|
||||
@@ -521,6 +531,8 @@ model Assessment {
|
||||
gradingReviews TeacherGradingReview[]
|
||||
gradingAnnotations GradingAnnotation[]
|
||||
examPlan ExamPlan?
|
||||
// Module F exam mode relations
|
||||
examSessions ExamSession[]
|
||||
}
|
||||
|
||||
model AssessmentCompetencyLink {
|
||||
@@ -3425,3 +3437,138 @@ model SignageAuditLog {
|
||||
@@index([action])
|
||||
@@map("signage_audit_logs")
|
||||
}
|
||||
|
||||
// ─── Module F: Exam Mode / Digital Test Environment ──────────────────
|
||||
|
||||
model ExamSession {
|
||||
id String @id @default(cuid())
|
||||
schoolId String
|
||||
assessmentId String
|
||||
studentId String
|
||||
startTime DateTime
|
||||
endTime DateTime?
|
||||
submittedAt DateTime?
|
||||
status String @default("not_started") // not_started, in_progress, submitted, graded
|
||||
score Float?
|
||||
totalPoints Float?
|
||||
lockdownEnabled Boolean @default(true) // Kiosk mode lockdown
|
||||
cameraMonitor Boolean @default(false) // Enable face monitoring
|
||||
screenShare Boolean @default(false) // Allow screen sharing for proctoring
|
||||
environmentNotes String? // JSON: { browser, os, resolution, etc }
|
||||
suspiciousActivity String? // JSON array of incidents
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
school School @relation(fields: [schoolId], references: [id])
|
||||
assessment Assessment @relation(fields: [assessmentId], references: [id])
|
||||
student Student @relation(fields: [studentId], references: [id])
|
||||
answers ExamAnswer[]
|
||||
events ExamEvent[]
|
||||
warnings ExamWarning[]
|
||||
|
||||
@@index([schoolId])
|
||||
@@index([assessmentId])
|
||||
@@index([studentId])
|
||||
@@index([status])
|
||||
@@map("exam_sessions")
|
||||
}
|
||||
|
||||
model ExamAnswer {
|
||||
id String @id @default(cuid())
|
||||
examSessionId String
|
||||
questionId String
|
||||
answer String? // JSON: selected choice, free text, etc
|
||||
submittedAt DateTime @default(now())
|
||||
isCorrect Boolean?
|
||||
pointsAwarded Float?
|
||||
reviewedAt DateTime?
|
||||
|
||||
examSession ExamSession @relation(fields: [examSessionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([examSessionId])
|
||||
@@index([questionId])
|
||||
@@map("exam_answers")
|
||||
}
|
||||
|
||||
model ExamEvent {
|
||||
id String @id @default(cuid())
|
||||
examSessionId String
|
||||
eventType String // tab_switch, copy_paste, window_blur, camera_detected_none, suspicious_movement, time_warning
|
||||
severity String @default("info") // info, warning, critical
|
||||
description String?
|
||||
timestamp DateTime @default(now())
|
||||
metadata String? // JSON: additional context
|
||||
|
||||
examSession ExamSession @relation(fields: [examSessionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([examSessionId])
|
||||
@@index([eventType])
|
||||
@@map("exam_events")
|
||||
}
|
||||
|
||||
model ExamWarning {
|
||||
id String @id @default(cuid())
|
||||
examSessionId String
|
||||
studentId String
|
||||
warningType String // time_low, behavior_suspicious, multiple_tabs, camera_issue
|
||||
message String
|
||||
acknowledged Boolean @default(false)
|
||||
acknowledgedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
examSession ExamSession @relation(fields: [examSessionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([examSessionId])
|
||||
@@index([studentId])
|
||||
@@map("exam_warnings")
|
||||
}
|
||||
|
||||
// ─── Module H: Centralized Notifications Hub ───────────────────────
|
||||
|
||||
model NotificationHub {
|
||||
id String @id @default(cuid())
|
||||
schoolId String
|
||||
userId String
|
||||
category String // assessment, behavior, communication, wellness, system, announcement
|
||||
priority String @default("normal") // low, normal, high, critical
|
||||
title String
|
||||
message String
|
||||
actionUrl String? // Link to related resource
|
||||
actionLabel String? // e.g. "View Grade", "Respond"
|
||||
isRead Boolean @default(false)
|
||||
readAt DateTime?
|
||||
isDismissed Boolean @default(false)
|
||||
dismissedAt DateTime?
|
||||
sourceType String? // assessment, incident, message, announcement, etc
|
||||
sourceId String? // ID of related entity
|
||||
createdAt DateTime @default(now())
|
||||
expiresAt DateTime? // Auto-archive if set
|
||||
|
||||
school School @relation(fields: [schoolId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
@@index([schoolId])
|
||||
@@index([userId])
|
||||
@@index([isRead])
|
||||
@@index([category])
|
||||
@@index([createdAt])
|
||||
@@map("notification_hubs")
|
||||
}
|
||||
|
||||
model NotificationArchive {
|
||||
id String @id @default(cuid())
|
||||
schoolId String
|
||||
userId String
|
||||
originalId String? // reference to NotificationHub.id if archived
|
||||
title String
|
||||
message String
|
||||
category String
|
||||
archivedAt DateTime @default(now())
|
||||
|
||||
school School @relation(fields: [schoolId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
@@index([schoolId])
|
||||
@@index([userId])
|
||||
@@index([archivedAt])
|
||||
@@map("notification_archives")
|
||||
}
|
||||
Reference in new issue
Block a user