Files
ihk-projekt/Smartes-Klassenzimmer-Backend/prisma/schema.prisma
2025-12-10 20:20:39 +01:00

280 lines
8.7 KiB
Plaintext

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
output = "../node_modules/.prisma/client"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
username String @unique
password String
role String @default("Student")
// Password Reset
passwordResetToken String?
passwordResetExpires DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
receivedGrades Grade[] @relation("ReceivedGrades") // Noten, die Schüler erhalten haben
assignedGrades Grade[] @relation("AssignedGrades") // Noten, die Lehrer vergeben haben
chatMessages ChatMessage[]
chatGroups ChatGroupMember[]
studentFeedbacks Feedback[] @relation("StudentFeedbacks")
teacherFeedbacks Feedback[] @relation("TeacherFeedbacks")
taughtTimetableEntries TimetableEntry[] @relation("TeacherTimetableEntries")
createdChatGroups ChatGroup[] @relation("ChatGroupCreator")
uploadedFiles File[]
}
// Neue Tabelle: File (Dateien)
model File {
id Int @id @default(autoincrement())
filename String
path String
mimetype String
size Int
uploadedById Int
uploadedBy User @relation(fields: [uploadedById], references: [id], onDelete: Cascade)
timetableEntryId Int?
timetableEntry TimetableEntry? @relation(fields: [timetableEntryId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@index([uploadedById])
@@index([timetableEntryId])
}
// Neue Tabelle: Subject (Fächer)
model Subject {
id Int @id @default(autoincrement())
name String @unique // z.B. "Mathematik", "Deutsch", "Englisch"
abbreviation String? // z.B. "Mathe", "DE", "EN"
color String? // Farbe für UI (z.B. "#FF5733")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
timetableEntries TimetableEntry[]
@@index([name])
}
// Neue Tabelle: Room (Räume)
model Room {
id Int @id @default(autoincrement())
number String @unique // z.B. "A101", "B203"
building String? // z.B. "Hauptgebäude", "Neubau"
capacity Int? // Anzahl Sitzplätze
equipment String? // z.B. "Beamer, Whiteboard"
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
timetableEntries TimetableEntry[]
@@index([number])
}
model TimetableEntry {
id Int @id @default(autoincrement())
dayOfWeek Int // 1 = Montag, 2 = Dienstag, ..., 5 = Freitag
startTime String // Format: "08:00"
endTime String // Format: "09:30"
// Normalisierte Relationen
subjectId Int
subject Subject @relation(fields: [subjectId], references: [id], onDelete: Restrict)
teacherId Int?
teacher User? @relation("TeacherTimetableEntries", fields: [teacherId], references: [id], onDelete: SetNull)
roomId Int?
room Room? @relation(fields: [roomId], references: [id], onDelete: SetNull)
// Wochenbasierte Planung
weekNumber Int? // Kalenderwoche (1-53), null = alle Wochen
year Int? // Jahr (z.B. 2025), null = alle Jahre
isRecurring Boolean @default(true) // true = wiederholt sich jede Woche, false = nur für spezifische Woche
allowStudentUploads Boolean @default(false)
files File[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
feedbacks Feedback[]
grades Grade[]
@@index([dayOfWeek])
@@index([weekNumber, year])
@@index([subjectId])
@@index([teacherId])
@@index([roomId])
}
model Feedback {
id Int @id @default(autoincrement())
// Foreign Key Relations zu User-Tabelle
studentId Int
student User @relation("StudentFeedbacks", fields: [studentId], references: [id], onDelete: Cascade)
teacherId Int
teacher User @relation("TeacherFeedbacks", fields: [teacherId], references: [id], onDelete: Cascade)
// Foreign Key Relation zu TimetableEntry
lessonId Int
timetableEntry TimetableEntry @relation(fields: [lessonId], references: [id], onDelete: Cascade)
lessonDate DateTime
overallRating Int
// Prisma Json-Typ für Kategorien
categories Json?
whatWasGood String?
whatCanImprove String?
additionalComments String?
isAnonymous Boolean @default(false)
allowTeacherResponse Boolean @default(true)
teacherResponse String?
teacherRespondedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Unique Constraint: Ein Schüler kann nur einmal pro Stunde Feedback geben
@@unique([studentId, lessonId])
@@index([studentId])
@@index([teacherId])
@@index([lessonId])
}
model Grade {
id Int @id @default(autoincrement())
// Schüler-Information (erhält die Note)
studentId Int
student User @relation("ReceivedGrades", fields: [studentId], references: [id], onDelete: Cascade)
// Stundenplan-Bezug
timetableEntryId Int
timetableEntry TimetableEntry @relation(fields: [timetableEntryId], references: [id], onDelete: Cascade)
// Wochenbezug (Note gilt für eine spezifische Woche)
weekNumber Int // Kalenderwoche (1-53)
year Int // Jahr (z.B. 2025)
// Noten-Details
grade Float // z.B. 1.0, 2.5, 3.0 (deutsches Notensystem)
gradeType String // z.B. "Klausur", "Mitarbeit", "Hausaufgabe", "Mündlich"
weight Float? @default(1.0) // Gewichtung der Note (z.B. Klausur = 2.0, Mitarbeit = 1.0)
// Lehrer-Information (vergibt die Note)
teacherId Int
teacher User @relation("AssignedGrades", fields: [teacherId], references: [id], onDelete: Restrict)
// Optional: Detailbeschreibung
title String? // z.B. "Mathearbeit Kapitel 3"
description String? // Zusätzliche Informationen
maxPoints Float? // Maximale Punktzahl
achievedPoints Float? // Erreichte Punktzahl
// Datum
date DateTime // Datum der Leistung
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([studentId, timetableEntryId, weekNumber, year, gradeType])
@@index([studentId])
@@index([timetableEntryId])
@@index([teacherId])
@@index([weekNumber, year])
}
model ChatGroup {
id Int @id @default(autoincrement())
name String
description String?
createdById Int // Lehrer, der die Gruppe erstellt hat
createdBy User @relation("ChatGroupCreator", fields: [createdById], references: [id], onDelete: Restrict)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
members ChatGroupMember[]
messages ChatMessage[]
@@index([createdById])
}
model ChatGroupMember {
id Int @id @default(autoincrement())
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
groupId Int
group ChatGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
joinedAt DateTime @default(now())
@@unique([userId, groupId])
@@index([userId])
@@index([groupId])
}
model ChatMessage {
id Int @id @default(autoincrement())
content String
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
groupId Int
group ChatGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@index([groupId])
@@index([userId])
@@index([createdAt])
}
model Student {
studentId Int @id @default(autoincrement()) @map("student_id")
studentFirstName String @map("student_first_name")
studentLastName String @map("student_last_name")
studentClassName String? @map("student_class_name")
studentRfidCardUid String @unique @map("student_rfid_card_uid")
studentCardIsActive Boolean @default(true) @map("student_card_is_active")
attendanceLogs AttendanceLog[]
@@map("students")
}
model AttendanceLog {
attendanceLogId Int @id @default(autoincrement()) @map("attendance_log_id")
studentId Int @map("student_id")
student Student @relation(fields: [studentId], references: [studentId], onDelete: Cascade)
attendanceScannedAt DateTime @map("attendance_scanned_at")
attendanceEventType String @map("attendance_event_type")
wasManualEntry Boolean @default(false) @map("was_manual_entry")
manualEntryReason String? @map("manual_entry_reason")
@@index([studentId, attendanceScannedAt])
@@map("attendance_logs")
}