Untitled
Anonymous
Plain Text
02/09/2026 1:51 PM
13.8 KB
11
Indexable
Never
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ================ ENUMS ================
enum Role {
ADMIN
TEACHER
APPLICANT
STUDENT
}
enum StatusPpdb {
PENDING
ACCEPTED
REJECTED
}
enum AttendanceStatus {
HADIR
SAKIT
IZIN
ALPHA
}
enum RoomType {
CLASSROOM
LABORATORY
PRACTICE
LIBRARY
OFFICE
HALL
TOILET
OTHER
}
enum TimePreference {
MORNING // 07:00 - 10:00
MIDDAY // 10:00 - 13:00
AFTERNOON // 13:00 - 16:00
ANY // No preference
}
enum GradeLevel {
GRADE_10 // Kelas X
GRADE_11 // Kelas XI
GRADE_12 // Kelas XII
}
// ================ MODEL UTAMA ================
model User {
id Int @id @default(autoincrement())
email String @unique
password String // hashed
role Role
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relasi ke role spesifik
admin Admin?
teacher Teacher?
applicant Applicant?
student Student?
staff Staff?
@@index([email])
@@index([role])
}
// ================ ADMIN ================
model Admin {
id Int @id @default(autoincrement())
name String
nip String @unique
phone String?
address String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([nip])
}
// ================ GURU ================
model Teacher {
id Int @id @default(autoincrement())
name String
nip String @unique
phone String?
address String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
schedules Schedule[]
attendances Attendance[]
gradeClasses GradeClass[] @relation("GradeClassHomeroom") // Wali kelas
teacherSubjects TeacherSubject[] // Many-to-many dengan Subject
preference TeacherPreference?
@@index([nip])
}
// ================ CALON SISWA (PPDB) ================
model Applicant {
id Int @id @default(autoincrement())
name String
nisn String @unique
phone String
address String
birthDate DateTime
schoolOrigin String
status StatusPpdb @default(PENDING)
registeredAt DateTime @default(now())
feedback String?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int? @unique
// Profile Lengkap (nullable karena diisi setelah registrasi)
gender String? // "MALE" / "FEMALE"
birthPlace String?
fullAddress String?
postalCode String?
ijazahNumber String?
ijazahYear Int?
skhunNumber String?
desiredMajor String? // "IPA" / "IPS" / "Bahasa"
bloodType String? // "A" / "B" / "AB" / "O"
childPosition Int? // Anak ke-
totalSiblings Int? // Dari berapa bersaudara
hobby String?
height Float? // Tinggi badan (cm)
weight Float? // Berat badan (kg)
achievements String? @db.Text // JSON array
// Data Orang Tua
livingWith String? // "PARENTS" / "GUARDIAN"
motherName String?
fatherName String?
motherOccupation String?
fatherOccupation String?
parentsPhone String?
fatherIncome Int? // Range: "< 1jt", "1-3jt", etc
motherIncome Int?
// Data Wali (jika tinggal dengan wali)
guardianName String?
guardianOccupation String?
guardianAddress String?
guardianPhone String?
guardianIncome Int?
// Upload Dokumen (store file paths)
sttbFile String? // STTB SMP
skhunFile String? // SKHUN SMP
birthCertFile String? // Akte Kelahiran
photoFile String? // Pas foto
ijazahFile String? // Ijazah/Bukti Kelulusan
achievementFiles Json? // Array of achievement file paths
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([nisn])
@@index([status])
@@index([userId])
}
// ================ SISWA AKTIF ================
model Student {
id Int @id @default(autoincrement())
name String
nisn String @unique
phone String
address String
birthDate DateTime
schoolOrigin String // Asal sekolah SMP
enrollmentYear Int // Tahun masuk (contoh: 2024)
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int? @unique
// Relasi ke kelas
gradeClass GradeClass? @relation(fields: [gradeClassId], references: [id])
gradeClassId Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relasi ke absensi
attendances Attendance[]
@@index([nisn])
@@index([gradeClassId])
@@index([enrollmentYear])
}
// ================ STAFF ================
model Staff {
id Int @id @default(autoincrement())
name String
employeeId String @unique
position String?
phone String?
address String?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int? @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([employeeId])
}
// ================ MATA PELAJARAN ================
model Subject {
id Int @id @default(autoincrement())
name String // Nama mata pelajaran (e.g., "Matematika", "Bahasa Indonesia")
code String @unique // Kode mata pelajaran (e.g., "MAT", "BIN")
description String? @db.Text
category String? // Kategori: "Wajib", "Peminatan", "Lintas Minat"
// Grade Level - untuk menentukan subject ini untuk kelas berapa
gradeLevel GradeLevel // GRADE_10, GRADE_11, atau GRADE_12
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relasi ke jadwal
schedules Schedule[]
teacherSubjects TeacherSubject[] // Many-to-many dengan Teacher
subjectHours SubjectHours[]
@@unique([code, gradeLevel]) // Kode + grade level harus unik (misal: MAT untuk Grade 10, MAT untuk Grade 11)
@@index([code])
@@index([category])
@@index([gradeLevel])
attendances Attendance[]
}
// ================ JUNCTION TABLE: GURU <-> MATA PELAJARAN ================
model TeacherSubject {
id Int @id @default(autoincrement())
teacher Teacher @relation(fields: [teacherId], references: [id], onDelete: Cascade)
teacherId Int
subject Subject @relation(fields: [subjectId], references: [id], onDelete: Cascade)
subjectId Int
// Metadata tambahan (opsional)
isPrimary Boolean @default(false) // Apakah guru ini pengampu utama untuk mata pelajaran ini
assignedAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([teacherId, subjectId]) // Satu guru tidak bisa di-assign ke mata pelajaran yang sama 2x
@@index([teacherId])
@@index([subjectId])
}
model SchoolTimeConfig {
id Int @id @default(autoincrement())
academicYear String @unique
schoolStartTime String // e.g., "07:00"
schoolEndTime String // e.g., "16:00"
periodDuration Int // dalam menit, e.g., 45
breakDuration Int // dalam menit, e.g., 15
maxPeriodsPerDay Int // maksimal jam pelajaran per hari
// Break times - JSON array of { afterPeriod: number, duration: number }
// e.g., [{ afterPeriod: 2, duration: 20 }, { afterPeriod: 5, duration: 30 }]
breakTimes Json
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([academicYear])
}
// Jam pelajaran per subject
model SubjectHours {
id Int @id @default(autoincrement())
subject Subject @relation(fields: [subjectId], references: [id], onDelete: Cascade)
subjectId Int
gradeClass GradeClass @relation(fields: [gradeClassId], references: [id], onDelete: Cascade)
gradeClassId Int
hoursPerWeek Int // Jam pelajaran per minggu untuk subject ini
preferredDays Json? // Optional: [1,2,3] = prefer Monday, Tuesday, Wednesday
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([subjectId, gradeClassId])
@@index([subjectId])
@@index([gradeClassId])
}
model TeacherPreference {
id Int @id @default(autoincrement())
teacher Teacher @relation(fields: [teacherId], references: [id], onDelete: Cascade)
teacherId Int @unique
timePreference TimePreference @default(ANY)
maxHoursPerDay Int @default(8)
maxHoursPerWeek Int @default(40)
unavailableDays Json? // Array of days: [1,3] = Monday, Wednesday
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ================ KELAS (GRADE) ================
model GradeClass {
id Int @id @default(autoincrement())
name String // Contoh: "X-1", "XI IPA 2", "XII IPS 1"
gradeLevel GradeLevel // GRADE_10, GRADE_11, GRADE_12
academicYear String // Contoh: "2024/2025"
capacity Int @default(30)
// Wali kelas
homeroom Teacher? @relation("GradeClassHomeroom", fields: [homeroomId], references: [id])
homeroomId Int?
// Ruang kelas
classroom MapRoom? @relation(fields: [classroomId], references: [id])
classroomId Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relasi
students Student[]
schedules Schedule[]
subjectHours SubjectHours[]
@@unique([name, academicYear]) // Nama kelas + tahun ajaran harus unik
@@index([gradeLevel])
@@index([academicYear])
@@index([homeroomId])
@@index([classroomId])
attendances Attendance[]
}
// ================ ABSENSI ================
model Attendance {
id Int @id @default(autoincrement())
date DateTime @default(now())
status AttendanceStatus @default(HADIR)
notes String? // Catatan tambahan (alasan izin/sakit, dll)
// Relasi ke siswa
student Student @relation(fields: [studentId], references: [id], onDelete: Cascade)
studentId Int
// Relasi ke guru yang mencatat
teacher Teacher @relation(fields: [teacherId], references: [id])
teacherId Int
// Relasi ke jadwal (opsional - untuk absensi per mata pelajaran)
schedule Schedule? @relation(fields: [scheduleId], references: [id])
scheduleId Int?
subjectId Int
subject Subject @relation(fields: [subjectId], references: [id])
gradeClassId Int
gradeClass GradeClass @relation(fields: [gradeClassId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([studentId, date, subjectId]) // Satu siswa hanya bisa punya 1 absensi per hari per jadwal
@@index([date])
@@index([studentId])
@@index([teacherId])
@@index([status])
}
// ================ JADWAL ================
model Schedule {
id Int @id @default(autoincrement())
day Int // 1=Monday, ..., 6=Saturday
period Int // Period number (1st hour, 2nd hour, etc.)
// Waktu mulai dan selesai
startTime String // Format: "07:00"
endTime String // Format: "08:30"
// Relasi ke mata pelajaran
subject Subject @relation(fields: [subjectId], references: [id], onDelete: Cascade)
subjectId Int
// Relasi ke kelas
gradeClass GradeClass @relation(fields: [gradeClassId], references: [id], onDelete: Cascade)
gradeClassId Int
// Relasi ke ruangan
room MapRoom? @relation(fields: [roomId], references: [id])
roomId Int?
// Relasi ke guru
teacher Teacher @relation(fields: [teacherId], references: [id])
teacherId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relasi ke absensi
attendances Attendance[]
@@unique([gradeClassId, day, period]) // Satu kelas tidak bisa punya 2 jadwal di waktu yang sama
@@index([day])
@@index([teacherId])
@@index([gradeClassId])
@@index([subjectId])
}
// ================ FEEDBACK (dari publik) ================
model Feedback {
id Int @id @default(autoincrement())
name String
email String?
message String @db.Text
isRead Boolean @default(false)
createdAt DateTime @default(now())
@@index([isRead])
@@index([createdAt])
}
// ================ DENAH SEKOLAH (CAMPUS MAP) ================
model CampusMap {
id Int @id @default(autoincrement())
name String @default("Denah Utama")
svgPath String // e.g., "/uploads/maps/school.svg"
uploadedAt DateTime @default(now())
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
rooms MapRoom[]
@@index([isActive])
}
// ================ RUANGAN DI DENAH ================
model MapRoom {
id Int @id @default(autoincrement())
roomId String // Harus sesuai dengan `id` elemen di SVG (e.g., "class-101")
name String
type RoomType @default(OTHER)
capacity Int @default(0)
floor Int @default(1) // Lantai berapa
building String? // Gedung (contoh: "Gedung A", "Gedung B")
description String? @db.Text
metadata Json? // Optional: { x: 120, y: 200, color: "#3b82f6" }
campusMap CampusMap @relation(fields: [campusMapId], references: [id], onDelete: Cascade)
campusMapId Int
schedules Schedule[]
gradeClasses GradeClass[]
@@unique([campusMapId, roomId]) // roomId harus unik per denah
@@index([type])
@@index([campusMapId])
}Editor is loading...
Leave a Comment