Files
lms-sb/prisma/schema.prisma
T
admins 48721759d3 Add comment field to user profile in admin panel
- Prisma: User.comment String? column + migration
- UserContactEditor: comment shown in view mode, textarea in edit mode
- updateUserContact action: saves comment to DB
2026-05-06 14:06:53 +00:00

323 lines
10 KiB
Plaintext

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
phone String?
birthday DateTime?
banned Boolean? @default(false)
banReason String?
banExpires DateTime?
comment String?
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?
impersonatedBy 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)
allowAudio 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?
coverImage 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?
status String @default("PENDING") // PENDING | REVIEWING | APPROVED | REJECTED
statusAt DateTime?
audioUrl String?
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
files Json? // [{name, url, size}]
audioUrl 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())
parentId String?
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
parent LessonComment? @relation("CommentReplies", fields: [parentId], references: [id], onDelete: SetNull)
replies LessonComment[] @relation("CommentReplies")
}
// ─────────────────────────────────────────────
// Platform Settings (key-value store)
// ─────────────────────────────────────────────
model Settings {
key String @id
value String @db.Text
updatedAt DateTime @updatedAt
}