generator client { provider = "prisma-client" output = "../src/generated/prisma" } datasource db { provider = "postgresql" } // ───────────────────────────────────────────── // Better Auth core tables // ───────────────────────────────────────────── model User { id String @id @default(cuid()) name String email String @unique emailVerified Boolean @default(false) image String? role String @default("student") // student | curator | admin banned Boolean? @default(false) banReason String? banExpires DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt sessions Session[] accounts Account[] enrollments CourseEnrollment[] progress LessonProgress[] submissions HomeworkSubmission[] comments LessonComment[] feedbacks HomeworkFeedback[] accessLogs AccessLog[] @relation("AccessLogUser") adminAccessLogs AccessLog[] @relation("AccessLogAdmin") } model Session { id String @id @default(cuid()) userId String token String @unique expiresAt DateTime ipAddress String? userAgent String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) } model Account { id String @id @default(cuid()) userId String accountId String providerId String accessToken String? refreshToken String? idToken String? accessTokenExpiresAt DateTime? refreshTokenExpiresAt DateTime? scope String? password String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) } model Verification { id String @id @default(cuid()) identifier String value String expiresAt DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } // ───────────────────────────────────────────── // LMS core tables // ───────────────────────────────────────────── model Category { id String @id @default(cuid()) title String slug String @unique order Int @default(0) createdAt DateTime @default(now()) courses Course[] } model Course { id String @id @default(cuid()) slug String @unique title String description String? coverImage String? published Boolean @default(false) order Int @default(0) categoryId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt category Category? @relation(fields: [categoryId], references: [id], onDelete: SetNull) modules Module[] enrollments CourseEnrollment[] accessLogs AccessLog[] } model Module { id String @id @default(cuid()) courseId String title String description String? order Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) lessons Lesson[] } model Lesson { id String @id @default(cuid()) moduleId String title String content Json? kinescopeId String? order Int @default(0) published Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt module Module @relation(fields: [moduleId], references: [id], onDelete: Cascade) progress LessonProgress[] quiz Quiz? homework Homework? comments LessonComment[] files LessonFile[] } model LessonFile { id String @id @default(cuid()) lessonId String name String url String size Int createdAt DateTime @default(now()) lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade) } model CourseEnrollment { userId String courseId String enrolledAt DateTime @default(now()) expiresAt DateTime? user User @relation(fields: [userId], references: [id], onDelete: Cascade) course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) @@id([userId, courseId]) } model AccessLog { id String @id @default(cuid()) courseId String userId String action String // "granted" | "revoked" method String @default("manual") grantedById String? note String? createdAt DateTime @default(now()) course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) user User @relation("AccessLogUser", fields: [userId], references: [id], onDelete: Cascade) grantedBy User? @relation("AccessLogAdmin", fields: [grantedById], references: [id], onDelete: SetNull) } model LessonProgress { userId String lessonId String completedAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade) @@id([userId, lessonId]) } // ───────────────────────────────────────────── // Quizzes // ───────────────────────────────────────────── model Quiz { id String @id @default(cuid()) lessonId String @unique showAnswers Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade) questions QuizQuestion[] attempts QuizAttempt[] } model QuizQuestion { id String @id @default(cuid()) quizId String text String type QuizQuestionType order Int @default(0) quiz Quiz @relation(fields: [quizId], references: [id], onDelete: Cascade) options QuizOption[] } model QuizOption { id String @id @default(cuid()) questionId String text String isCorrect Boolean @default(false) order Int @default(0) question QuizQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) } model QuizAttempt { id String @id @default(cuid()) userId String quizId String score Int answers Json completedAt DateTime @default(now()) quiz Quiz @relation(fields: [quizId], references: [id], onDelete: Cascade) } enum QuizQuestionType { SINGLE MULTIPLE TEXT } // ───────────────────────────────────────────── // Homework // ───────────────────────────────────────────── model Homework { id String @id @default(cuid()) lessonId String @unique description String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade) submissions HomeworkSubmission[] } model HomeworkSubmission { id String @id @default(cuid()) homeworkId String userId String text String? files Json? submittedAt DateTime @default(now()) homework Homework @relation(fields: [homeworkId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) feedbacks HomeworkFeedback[] } model HomeworkFeedback { id String @id @default(cuid()) submissionId String curatorId String text String createdAt DateTime @default(now()) submission HomeworkSubmission @relation(fields: [submissionId], references: [id], onDelete: Cascade) curator User @relation(fields: [curatorId], references: [id], onDelete: Cascade) } // ───────────────────────────────────────────── // Comments // ───────────────────────────────────────────── model LessonComment { id String @id @default(cuid()) lessonId String userId String text String deleted Boolean @default(false) createdAt DateTime @default(now()) lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) } // ───────────────────────────────────────────── // Platform Settings (key-value store) // ───────────────────────────────────────────── model Settings { key String @id value String @db.Text updatedAt DateTime @updatedAt }