first commit

This commit is contained in:
DerJesen
2025-12-10 20:20:39 +01:00
commit c24927fab1
136 changed files with 32253 additions and 0 deletions

View File

@@ -0,0 +1,255 @@
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"email" TEXT NOT NULL,
"username" TEXT NOT NULL,
"password" TEXT NOT NULL,
"role" TEXT NOT NULL DEFAULT 'Student',
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Subject" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"abbreviation" TEXT,
"color" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Subject_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Room" (
"id" SERIAL NOT NULL,
"number" TEXT NOT NULL,
"building" TEXT,
"capacity" INTEGER,
"equipment" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Room_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "TimetableEntry" (
"id" SERIAL NOT NULL,
"dayOfWeek" INTEGER NOT NULL,
"startTime" TEXT NOT NULL,
"endTime" TEXT NOT NULL,
"subjectId" INTEGER NOT NULL,
"teacherId" INTEGER,
"roomId" INTEGER,
"weekNumber" INTEGER,
"year" INTEGER,
"isRecurring" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "TimetableEntry_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Feedback" (
"id" SERIAL NOT NULL,
"studentId" INTEGER NOT NULL,
"teacherId" INTEGER NOT NULL,
"lessonId" INTEGER NOT NULL,
"lessonDate" TIMESTAMP(3) NOT NULL,
"overallRating" INTEGER NOT NULL,
"categories" JSONB,
"whatWasGood" TEXT,
"whatCanImprove" TEXT,
"additionalComments" TEXT,
"isAnonymous" BOOLEAN NOT NULL DEFAULT false,
"allowTeacherResponse" BOOLEAN NOT NULL DEFAULT true,
"teacherResponse" TEXT,
"teacherRespondedAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Feedback_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Grade" (
"id" SERIAL NOT NULL,
"studentId" INTEGER NOT NULL,
"timetableEntryId" INTEGER NOT NULL,
"weekNumber" INTEGER NOT NULL,
"year" INTEGER NOT NULL,
"grade" DOUBLE PRECISION NOT NULL,
"gradeType" TEXT NOT NULL,
"weight" DOUBLE PRECISION DEFAULT 1.0,
"teacherId" INTEGER NOT NULL,
"title" TEXT,
"description" TEXT,
"maxPoints" DOUBLE PRECISION,
"achievedPoints" DOUBLE PRECISION,
"date" TIMESTAMP(3) NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Grade_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ChatGroup" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"createdById" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "ChatGroup_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ChatGroupMember" (
"id" SERIAL NOT NULL,
"userId" INTEGER NOT NULL,
"groupId" INTEGER NOT NULL,
"joinedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "ChatGroupMember_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ChatMessage" (
"id" SERIAL NOT NULL,
"content" TEXT NOT NULL,
"userId" INTEGER NOT NULL,
"groupId" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "ChatMessage_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
-- CreateIndex
CREATE UNIQUE INDEX "Subject_name_key" ON "Subject"("name");
-- CreateIndex
CREATE INDEX "Subject_name_idx" ON "Subject"("name");
-- CreateIndex
CREATE UNIQUE INDEX "Room_number_key" ON "Room"("number");
-- CreateIndex
CREATE INDEX "Room_number_idx" ON "Room"("number");
-- CreateIndex
CREATE INDEX "TimetableEntry_dayOfWeek_idx" ON "TimetableEntry"("dayOfWeek");
-- CreateIndex
CREATE INDEX "TimetableEntry_weekNumber_year_idx" ON "TimetableEntry"("weekNumber", "year");
-- CreateIndex
CREATE INDEX "TimetableEntry_subjectId_idx" ON "TimetableEntry"("subjectId");
-- CreateIndex
CREATE INDEX "TimetableEntry_teacherId_idx" ON "TimetableEntry"("teacherId");
-- CreateIndex
CREATE INDEX "TimetableEntry_roomId_idx" ON "TimetableEntry"("roomId");
-- CreateIndex
CREATE INDEX "Feedback_studentId_idx" ON "Feedback"("studentId");
-- CreateIndex
CREATE INDEX "Feedback_teacherId_idx" ON "Feedback"("teacherId");
-- CreateIndex
CREATE INDEX "Feedback_lessonId_idx" ON "Feedback"("lessonId");
-- CreateIndex
CREATE UNIQUE INDEX "Feedback_studentId_lessonId_key" ON "Feedback"("studentId", "lessonId");
-- CreateIndex
CREATE INDEX "Grade_studentId_idx" ON "Grade"("studentId");
-- CreateIndex
CREATE INDEX "Grade_timetableEntryId_idx" ON "Grade"("timetableEntryId");
-- CreateIndex
CREATE INDEX "Grade_teacherId_idx" ON "Grade"("teacherId");
-- CreateIndex
CREATE INDEX "Grade_weekNumber_year_idx" ON "Grade"("weekNumber", "year");
-- CreateIndex
CREATE UNIQUE INDEX "Grade_studentId_timetableEntryId_weekNumber_year_gradeType_key" ON "Grade"("studentId", "timetableEntryId", "weekNumber", "year", "gradeType");
-- CreateIndex
CREATE INDEX "ChatGroup_createdById_idx" ON "ChatGroup"("createdById");
-- CreateIndex
CREATE INDEX "ChatGroupMember_userId_idx" ON "ChatGroupMember"("userId");
-- CreateIndex
CREATE INDEX "ChatGroupMember_groupId_idx" ON "ChatGroupMember"("groupId");
-- CreateIndex
CREATE UNIQUE INDEX "ChatGroupMember_userId_groupId_key" ON "ChatGroupMember"("userId", "groupId");
-- CreateIndex
CREATE INDEX "ChatMessage_groupId_idx" ON "ChatMessage"("groupId");
-- CreateIndex
CREATE INDEX "ChatMessage_userId_idx" ON "ChatMessage"("userId");
-- CreateIndex
CREATE INDEX "ChatMessage_createdAt_idx" ON "ChatMessage"("createdAt");
-- AddForeignKey
ALTER TABLE "TimetableEntry" ADD CONSTRAINT "TimetableEntry_subjectId_fkey" FOREIGN KEY ("subjectId") REFERENCES "Subject"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "TimetableEntry" ADD CONSTRAINT "TimetableEntry_teacherId_fkey" FOREIGN KEY ("teacherId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "TimetableEntry" ADD CONSTRAINT "TimetableEntry_roomId_fkey" FOREIGN KEY ("roomId") REFERENCES "Room"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Feedback" ADD CONSTRAINT "Feedback_studentId_fkey" FOREIGN KEY ("studentId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Feedback" ADD CONSTRAINT "Feedback_teacherId_fkey" FOREIGN KEY ("teacherId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Feedback" ADD CONSTRAINT "Feedback_lessonId_fkey" FOREIGN KEY ("lessonId") REFERENCES "TimetableEntry"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Grade" ADD CONSTRAINT "Grade_studentId_fkey" FOREIGN KEY ("studentId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Grade" ADD CONSTRAINT "Grade_timetableEntryId_fkey" FOREIGN KEY ("timetableEntryId") REFERENCES "TimetableEntry"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Grade" ADD CONSTRAINT "Grade_teacherId_fkey" FOREIGN KEY ("teacherId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ChatGroup" ADD CONSTRAINT "ChatGroup_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ChatGroupMember" ADD CONSTRAINT "ChatGroupMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ChatGroupMember" ADD CONSTRAINT "ChatGroupMember_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "ChatGroup"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ChatMessage" ADD CONSTRAINT "ChatMessage_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ChatMessage" ADD CONSTRAINT "ChatMessage_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "ChatGroup"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "User" ADD COLUMN "passwordResetExpires" TIMESTAMP(3),
ADD COLUMN "passwordResetToken" TEXT;

View File

@@ -0,0 +1,28 @@
-- AlterTable
ALTER TABLE "TimetableEntry" ADD COLUMN "allowStudentUploads" BOOLEAN NOT NULL DEFAULT false;
-- CreateTable
CREATE TABLE "File" (
"id" SERIAL NOT NULL,
"filename" TEXT NOT NULL,
"path" TEXT NOT NULL,
"mimetype" TEXT NOT NULL,
"size" INTEGER NOT NULL,
"uploadedById" INTEGER NOT NULL,
"timetableEntryId" INTEGER,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "File_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "File_uploadedById_idx" ON "File"("uploadedById");
-- CreateIndex
CREATE INDEX "File_timetableEntryId_idx" ON "File"("timetableEntryId");
-- AddForeignKey
ALTER TABLE "File" ADD CONSTRAINT "File_uploadedById_fkey" FOREIGN KEY ("uploadedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "File" ADD CONSTRAINT "File_timetableEntryId_fkey" FOREIGN KEY ("timetableEntryId") REFERENCES "TimetableEntry"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,32 @@
-- CreateTable
CREATE TABLE "students" (
"student_id" SERIAL NOT NULL,
"student_first_name" TEXT NOT NULL,
"student_last_name" TEXT NOT NULL,
"student_class_name" TEXT,
"student_rfid_card_uid" TEXT NOT NULL,
"student_card_is_active" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "students_pkey" PRIMARY KEY ("student_id")
);
-- CreateTable
CREATE TABLE "attendance_logs" (
"attendance_log_id" SERIAL NOT NULL,
"student_id" INTEGER NOT NULL,
"attendance_scanned_at" TIMESTAMP(3) NOT NULL,
"attendance_event_type" TEXT NOT NULL,
"was_manual_entry" BOOLEAN NOT NULL DEFAULT false,
"manual_entry_reason" TEXT,
CONSTRAINT "attendance_logs_pkey" PRIMARY KEY ("attendance_log_id")
);
-- CreateIndex
CREATE UNIQUE INDEX "students_student_rfid_card_uid_key" ON "students"("student_rfid_card_uid");
-- CreateIndex
CREATE INDEX "attendance_logs_student_id_attendance_scanned_at_idx" ON "attendance_logs"("student_id", "attendance_scanned_at");
-- AddForeignKey
ALTER TABLE "attendance_logs" ADD CONSTRAINT "attendance_logs_student_id_fkey" FOREIGN KEY ("student_id") REFERENCES "students"("student_id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"

View File

@@ -0,0 +1,279 @@
// 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")
}

View File

@@ -0,0 +1,236 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
console.log('🌱 Datenbank wird mit Testdaten befüllt...\n');
// 1. Benutzer erstellen (Lehrer und Schüler)
console.log('📝 Erstelle Benutzer...');
const admin = await prisma.user.upsert({
where: { email: 'admin@smartesklassenzimmer.de' },
update: {},
create: {
email: 'admin@smartesklassenzimmer.de',
username: 'admin',
password: '$2b$10$8I9F3DPBvqzm.tBz7yMgfur4z1gMyaHsPyhmL4VAGJ2OvnmTTn5KW', // admin123
role: 'Lehrer',
},
});
const teacher1 = await prisma.user.upsert({
where: { email: 'mueller@schule.de' },
update: {},
create: {
email: 'mueller@schule.de',
username: 'Frau Müller',
password: '$2b$10$8I9F3DPBvqzm.tBz7yMgfur4z1gMyaHsPyhmL4VAGJ2OvnmTTn5KW', // admin123
role: 'Lehrer',
},
});
const teacher2 = await prisma.user.upsert({
where: { email: 'schmidt@schule.de' },
update: {},
create: {
email: 'schmidt@schule.de',
username: 'Herr Schmidt',
password: '$2b$10$8I9F3DPBvqzm.tBz7yMgfur4z1gMyaHsPyhmL4VAGJ2OvnmTTn5KW', // admin123
role: 'Lehrer',
},
});
const student1 = await prisma.user.upsert({
where: { email: 'max@student.de' },
update: {},
create: {
email: 'max@student.de',
username: 'Max Mustermann',
password: '$2b$10$8I9F3DPBvqzm.tBz7yMgfur4z1gMyaHsPyhmL4VAGJ2OvnmTTn5KW', // admin123
role: 'Student',
},
});
const student2 = await prisma.user.upsert({
where: { email: 'anna@student.de' },
update: {},
create: {
email: 'anna@student.de',
username: 'Anna Schmidt',
password: '$2b$10$8I9F3DPBvqzm.tBz7yMgfur4z1gMyaHsPyhmL4VAGJ2OvnmTTn5KW', // admin123
role: 'Student',
},
});
console.log('✅ Benutzer erstellt\n');
// 2. Fächer erstellen
console.log('📚 Erstelle Fächer...');
const mathSubject = await prisma.subject.upsert({
where: { name: 'Mathematik' },
update: {},
create: {
name: 'Mathematik',
abbreviation: 'Mathe',
color: '#FF5733',
},
});
const germanSubject = await prisma.subject.upsert({
where: { name: 'Deutsch' },
update: {},
create: {
name: 'Deutsch',
abbreviation: 'DE',
color: '#33FF57',
},
});
const englishSubject = await prisma.subject.upsert({
where: { name: 'Englisch' },
update: {},
create: {
name: 'Englisch',
abbreviation: 'EN',
color: '#3357FF',
},
});
const physicsSubject = await prisma.subject.upsert({
where: { name: 'Physik' },
update: {},
create: {
name: 'Physik',
abbreviation: 'Phy',
color: '#FF33F5',
},
});
console.log('✅ Fächer erstellt\n');
// 3. Räume erstellen
console.log('🏫 Erstelle Räume...');
const roomA101 = await prisma.room.upsert({
where: { number: 'A101' },
update: {},
create: {
number: 'A101',
building: 'Hauptgebäude',
capacity: 30,
equipment: 'Beamer, Whiteboard',
},
});
const roomB203 = await prisma.room.upsert({
where: { number: 'B203' },
update: {},
create: {
number: 'B203',
building: 'Neubau',
capacity: 25,
equipment: 'Smartboard, Laptop',
},
});
const roomC105 = await prisma.room.upsert({
where: { number: 'C105' },
update: {},
create: {
number: 'C105',
building: 'Hauptgebäude',
capacity: 20,
equipment: 'Beamer',
},
});
console.log('✅ Räume erstellt\n');
// 4. Stundenplan-Einträge erstellen
console.log('📅 Erstelle Stundenplan-Einträge...');
// Montag
await prisma.timetableEntry.create({
data: {
dayOfWeek: 1,
startTime: '08:00',
endTime: '09:30',
subjectId: mathSubject.id,
teacherId: teacher1.id,
roomId: roomA101.id,
isRecurring: true,
},
});
await prisma.timetableEntry.create({
data: {
dayOfWeek: 1,
startTime: '10:00',
endTime: '11:30',
subjectId: germanSubject.id,
teacherId: teacher2.id,
roomId: roomB203.id,
isRecurring: true,
},
});
// Dienstag
await prisma.timetableEntry.create({
data: {
dayOfWeek: 2,
startTime: '08:00',
endTime: '09:30',
subjectId: englishSubject.id,
teacherId: teacher1.id,
roomId: roomC105.id,
isRecurring: true,
},
});
await prisma.timetableEntry.create({
data: {
dayOfWeek: 2,
startTime: '10:00',
endTime: '11:30',
subjectId: physicsSubject.id,
teacherId: teacher2.id,
roomId: roomA101.id,
isRecurring: true,
},
});
// Mittwoch
await prisma.timetableEntry.create({
data: {
dayOfWeek: 3,
startTime: '08:00',
endTime: '09:30',
subjectId: mathSubject.id,
teacherId: teacher1.id,
roomId: roomA101.id,
isRecurring: true,
},
});
console.log('✅ Stundenplan-Einträge erstellt\n');
console.log('\n=== LOGIN-DATEN ===');
console.log('👨‍🏫 Lehrer:');
console.log(' - Benutzername: admin, Passwort: admin123');
console.log(' - Benutzername: Frau Müller, Passwort: admin123');
console.log(' - Benutzername: Herr Schmidt, Passwort: admin123');
console.log('\n👨🎓 Schüler:');
console.log(' - Benutzername: Max Mustermann, Passwort: admin123');
console.log(' - Benutzername: Anna Schmidt, Passwort: admin123');
console.log('==================\n');
console.log('🎉 Datenbank erfolgreich mit Testdaten befüllt!\n');
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});