Sync LMS backend source

This commit is contained in:
2026-07-07 16:09:12 +09:00
commit 5a2ecd0fea
126 changed files with 22959 additions and 0 deletions
+666
View File
@@ -0,0 +1,666 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid()) @db.Uuid
authUserId String? @unique @map("auth_user_id") @db.Uuid
email String @unique
name String?
authRole String? @map("auth_role")
primaryOrganizationId String? @map("primary_organization_id") @db.Uuid
primaryOrganizationName String? @map("primary_organization_name")
primaryOrganizationType String? @map("primary_organization_type")
department String?
position String?
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
courses Course[] @relation("CourseTeacher")
progress CourseStudentProgress[]
weekProgress CourseStudentWeekProgress[]
groupMemberships StudentGroupMember[]
enrollments StudentEnrollment[]
studentChatThreads ChatThread[] @relation("ChatThreadStudent")
assignedChatThreads ChatThread[] @relation("ChatThreadInstructor")
chatMessages ChatMessage[]
platformControlSessions PlatformControlSession[]
platformControlQueueEntries PlatformControlQueueEntry[]
studioRepositories StudioRepository[]
submissionScores SubmissionScore[]
submissionTotalScores SubmissionTotalScore[]
@@index([authRole])
@@index([primaryOrganizationId])
@@map("users")
}
model StudentEnrollment {
id String @id @default(uuid()) @db.Uuid
userId String @map("user_id") @db.Uuid
courseId String @map("course_id") @db.Uuid
organizationId String? @map("organization_id") @db.Uuid
organizationName String @map("organization_name")
status String @default("ACTIVE")
removedAt DateTime? @map("removed_at") @db.Timestamptz(3)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
@@unique([userId, courseId])
@@index([courseId, status])
@@index([organizationId, status])
@@index([organizationName, status])
@@map("student_enrollments")
}
model StudentGroup {
id String @id @default(uuid()) @db.Uuid
organizationId String? @map("organization_id") @db.Uuid
organizationName String @map("organization_name")
name String
week Int @default(1)
status String @default("진행중")
platformName String? @map("platform_name")
instructorPlatformId String? @map("instructor_platform_id") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
members StudentGroupMember[]
instructorPlatform InstructorPlatform? @relation(fields: [instructorPlatformId], references: [id], onDelete: SetNull)
platformControlSessions PlatformControlSession[]
platformControlQueueEntries PlatformControlQueueEntry[]
curriculumSettings InstructorCurriculumSetting[]
@@unique([organizationName, name])
@@index([organizationId])
@@index([organizationName])
@@index([instructorPlatformId])
@@map("student_groups")
}
model InstructorPlatform {
id String @id @default(uuid()) @db.Uuid
organizationId String? @map("organization_id") @db.Uuid
organizationName String @map("organization_name")
platformId String @map("platform_id") @db.Uuid
displayName String @map("display_name")
instanceNo Int @map("instance_no")
status String @default("대기")
battery Int @default(100)
uptimeMinutes Int @default(0) @map("uptime_minutes")
speedMeters Decimal @default(0) @map("speed_meters") @db.Decimal(6, 2)
errorCount Int @default(0) @map("error_count")
emergencyStop Boolean @default(false) @map("emergency_stop")
vehicleType String @default("MK-mini") @map("vehicle_type")
wheelbaseMeters Decimal @default(0.325) @map("wheelbase_meters") @db.Decimal(6, 3)
maxSpeedMetersPerSecond Decimal @default(7.0) @map("max_speed_meters_per_second") @db.Decimal(6, 2)
maxSteeringAngleDegrees Decimal @default(30) @map("max_steering_angle_degrees") @db.Decimal(6, 2)
sensors Json @default("[]")
drivers Json @default("[]")
algorithms Json @default("{}")
studioSettingsOverride Json? @map("studio_settings_override")
controlDurationMinutes Int @default(30) @map("control_duration_minutes")
controlWarningMinutes Int @default(5) @map("control_warning_minutes")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
platform Platform @relation(fields: [platformId], references: [id], onDelete: Restrict)
assignedGroups StudentGroup[]
controlSessions PlatformControlSession[]
controlQueueEntries PlatformControlQueueEntry[]
@@unique([organizationName, displayName])
@@unique([organizationName, platformId, instanceNo])
@@index([organizationId])
@@index([organizationName])
@@index([platformId])
@@map("instructor_platforms")
}
model StudentGroupMember {
id String @id @default(uuid()) @db.Uuid
groupId String @map("group_id") @db.Uuid
userId String @map("user_id") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
group StudentGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([groupId, userId])
@@index([userId])
@@map("student_group_members")
}
model Course {
id String @id @default(uuid()) @db.Uuid
slug String @unique
title String
subtitle String?
description String?
organizationName String @map("organization_name")
teacherId String @map("teacher_id") @db.Uuid
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
teacher User @relation("CourseTeacher", fields: [teacherId], references: [id], onDelete: Restrict)
weeks CourseWeek[]
platforms CoursePlatform[]
studentProgress CourseStudentProgress[]
studentWeekProgress CourseStudentWeekProgress[]
chatThreads ChatThread[]
enrollments StudentEnrollment[]
instructorCurriculumSettings InstructorCurriculumSetting[]
instructorCurriculumWeekOverrides InstructorCurriculumWeekOverride[]
environmentProfiles CourseEnvironmentProfile[]
visualizationSelections CourseWeekVisualizationPlatform[]
submissionScores SubmissionScore[]
submissionTotalScores SubmissionTotalScore[]
@@index([isActive])
@@index([teacherId])
@@map("courses")
}
model CourseEnvironmentProfile {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
week Int
platformKey String @default("futuredrive-local-pc") @map("platform_key")
profileType String @map("profile_type")
name String
config Json
enabled Boolean @default(true)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
@@unique([courseId, week, platformKey])
@@index([courseId, week])
@@index([profileType])
@@map("course_environment_profiles")
}
model VisualizationPlatform {
key String @id @map("platform_key")
type String @unique
displayName String @map("display_name")
description String?
defaultConfig Json @map("default_config")
sortOrder Int @default(0) @map("sort_order")
enabled Boolean @default(true)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
courseWeekSelections CourseWeekVisualizationPlatform[]
@@index([enabled, sortOrder])
@@map("visualization_platforms")
}
model CourseWeekVisualizationPlatform {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
week Int
platformKey String @map("platform_key")
enabled Boolean @default(true)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
platform VisualizationPlatform @relation(fields: [platformKey], references: [key], onDelete: Cascade)
@@unique([courseId, week, platformKey])
@@index([courseId, week])
@@index([platformKey])
@@map("course_week_visualization_platforms")
}
model InstructorCurriculumSetting {
id String @id @default(uuid()) @db.Uuid
organizationId String? @map("organization_id") @db.Uuid
organizationName String @map("organization_name")
groupId String? @map("group_id") @db.Uuid
courseId String @map("course_id") @db.Uuid
activeWeek Int @default(1) @map("active_week")
activeLearningStep String? @map("active_learning_step")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Restrict)
group StudentGroup? @relation(fields: [groupId], references: [id], onDelete: Cascade)
@@index([organizationId])
@@index([organizationName])
@@index([groupId])
@@index([courseId])
@@map("instructor_curriculum_settings")
}
model InstructorCurriculumWeekOverride {
id String @id @default(uuid()) @db.Uuid
organizationId String? @map("organization_id") @db.Uuid
organizationName String @map("organization_name")
courseId String @map("course_id") @db.Uuid
week Int
tagLabel String? @map("tag_label")
title String?
duration String?
overview String?
deliverable String?
requiresSourceSubmission Boolean? @default(true) @map("requires_source_submission")
learningSteps Json? @map("learning_steps")
topics Json?
topicDetails Json? @map("topic_details")
topicVideoUrls Json? @map("topic_video_urls")
practiceContents Json? @map("practice_contents")
disabledModuleIds Json? @map("disabled_module_ids")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
@@unique([organizationName, courseId, week])
@@index([organizationId])
@@index([organizationName])
@@index([courseId])
@@map("instructor_curriculum_week_overrides")
}
model Platform {
id String @id @default(uuid()) @db.Uuid
platformKey String @unique @map("platform_key")
displayName String @map("display_name")
description String
organizationName String @map("organization_name")
iconKey String @map("icon_key")
isActive Boolean @default(true) @map("is_active")
curriculumTagOnly Boolean @default(false) @map("curriculum_tag_only")
vehicleType String @default("MK-mini") @map("vehicle_type")
wheelbaseMeters Decimal @default(0.325) @map("wheelbase_meters") @db.Decimal(6, 3)
maxSpeedMetersPerSecond Decimal @default(7.0) @map("max_speed_meters_per_second") @db.Decimal(6, 2)
maxSteeringAngleDegrees Decimal @default(30) @map("max_steering_angle_degrees") @db.Decimal(6, 2)
sensors Json @default("[]")
drivers Json @default("[]")
algorithms Json @default("{}")
defaultStudioSettings Json @default("{\"workspaceRoot\":\"~/autonomy-studio/workspaces\",\"giteaBaseUrl\":\"http://localhost:3000\",\"giteaOwner\":\"student\"}") @map("default_studio_settings")
controlDurationMinutes Int @default(30) @map("control_duration_minutes")
controlWarningMinutes Int @default(5) @map("control_warning_minutes")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
courses CoursePlatform[]
instructorPlatforms InstructorPlatform[]
controlSessions PlatformControlSession[]
controlQueueEntries PlatformControlQueueEntry[]
@@index([organizationName])
@@index([isActive])
@@map("platforms")
}
model CoursePlatform {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
platformId String @map("platform_id") @db.Uuid
status String
action String
state String
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
platform Platform @relation(fields: [platformId], references: [id], onDelete: Restrict)
@@unique([courseId, platformId])
@@index([courseId, sortOrder])
@@index([platformId])
@@map("course_platforms")
}
model PlatformControlSession {
id String @id @default(uuid()) @db.Uuid
organizationId String? @map("organization_id") @db.Uuid
organizationName String @map("organization_name")
platformId String? @map("platform_id") @db.Uuid
instructorPlatformId String? @map("instructor_platform_id") @db.Uuid
holderUserId String @map("holder_user_id") @db.Uuid
groupId String? @map("group_id") @db.Uuid
status String @default("ACTIVE")
startedAt DateTime @default(now()) @map("started_at") @db.Timestamptz(3)
endsAt DateTime @map("ends_at") @db.Timestamptz(3)
warningAt DateTime @map("warning_at") @db.Timestamptz(3)
warningSentAt DateTime? @map("warning_sent_at") @db.Timestamptz(3)
releasedAt DateTime? @map("released_at") @db.Timestamptz(3)
endReason String? @map("end_reason")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
platform Platform? @relation(fields: [platformId], references: [id], onDelete: Restrict)
instructorPlatform InstructorPlatform? @relation(fields: [instructorPlatformId], references: [id], onDelete: Restrict)
holderUser User @relation(fields: [holderUserId], references: [id], onDelete: Cascade)
group StudentGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull)
@@index([organizationId])
@@index([organizationName])
@@index([platformId, status])
@@index([instructorPlatformId, status])
@@index([holderUserId, status])
@@index([endsAt, status])
@@map("platform_control_sessions")
}
model PlatformControlQueueEntry {
id String @id @default(uuid()) @db.Uuid
organizationId String? @map("organization_id") @db.Uuid
organizationName String @map("organization_name")
platformId String? @map("platform_id") @db.Uuid
instructorPlatformId String? @map("instructor_platform_id") @db.Uuid
userId String @map("user_id") @db.Uuid
groupId String? @map("group_id") @db.Uuid
status String @default("WAITING")
requestedAt DateTime @default(now()) @map("requested_at") @db.Timestamptz(3)
grantedAt DateTime? @map("granted_at") @db.Timestamptz(3)
canceledAt DateTime? @map("canceled_at") @db.Timestamptz(3)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
platform Platform? @relation(fields: [platformId], references: [id], onDelete: Restrict)
instructorPlatform InstructorPlatform? @relation(fields: [instructorPlatformId], references: [id], onDelete: Restrict)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
group StudentGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull)
@@index([organizationId])
@@index([organizationName])
@@index([platformId, status, requestedAt])
@@index([instructorPlatformId, status, requestedAt])
@@index([userId, status])
@@map("platform_control_queue_entries")
}
model CourseStudentProgress {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
userId String @map("user_id") @db.Uuid
completedWeeks Int @default(0) @map("completed_weeks")
totalWeeks Int @default(0) @map("total_weeks")
learningHours Int @default(0) @map("learning_hours")
commitCount Int @default(0) @map("commit_count")
averageScore Int @default(0) @map("average_score")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([courseId, userId])
@@index([userId])
@@map("course_student_progress")
}
model CourseStudentWeekProgress {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
userId String @map("user_id") @db.Uuid
week Int
submittedAt DateTime? @map("submitted_at") @db.Timestamptz(3)
commitCount Int @default(0) @map("commit_count")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([courseId, userId, week])
@@index([userId])
@@map("course_student_week_progress")
}
model CourseWeek {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
week Int
title String
tags String[]
progress Int @default(0)
state String
duration String
github String
overview String
deliverable String
requiresSourceSubmission Boolean @default(true) @map("requires_source_submission")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
topics CourseWeekTopic[]
practices CourseWeekPractice[]
references CourseWeekReference[]
modules CourseWeekModule[]
chatThreads ChatThread[]
submissionScores SubmissionScore[]
submissionTotalScores SubmissionTotalScore[]
@@unique([courseId, week])
@@index([courseId])
@@map("course_weeks")
}
model CourseWeekModule {
id String @id @default(uuid()) @db.Uuid
weekId String @map("week_id") @db.Uuid
sortOrder Int @map("sort_order")
category String
name String
folderName String @map("folder_name")
templateRepositoryUrl String? @map("template_repository_url")
sourceType String @default("GIT") @map("source_type")
prebuiltArtifacts Json @default("[]") @map("prebuilt_artifacts")
dockerImage String? @map("docker_image")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
week CourseWeek @relation(fields: [weekId], references: [id], onDelete: Cascade)
studioRepositories StudioRepository[]
submissionScores SubmissionScore[]
@@unique([weekId, folderName])
@@unique([weekId, sortOrder])
@@index([weekId])
@@map("course_week_modules")
}
model StudioRepository {
id String @id @default(uuid()) @db.Uuid
userId String @map("user_id") @db.Uuid
weekId String @map("week_id") @db.Uuid
moduleId String @map("module_id") @db.Uuid
repoOwner String @map("repo_owner")
repoName String @map("repo_name")
repositoryUrl String @map("repository_url")
templateRepositoryUrl String @map("template_repository_url")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
module CourseWeekModule @relation(fields: [moduleId], references: [id], onDelete: Cascade)
@@unique([userId, moduleId])
@@index([weekId])
@@index([repoOwner, repoName])
@@map("studio_repositories")
}
model SubmissionScore {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
weekId String @map("week_id") @db.Uuid
moduleId String @map("module_id") @db.Uuid
studentId String @map("student_id") @db.Uuid
score Int @default(0)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
week CourseWeek @relation(fields: [weekId], references: [id], onDelete: Cascade)
module CourseWeekModule @relation(fields: [moduleId], references: [id], onDelete: Cascade)
student User @relation(fields: [studentId], references: [id], onDelete: Cascade)
@@unique([studentId, moduleId])
@@index([courseId])
@@index([weekId])
@@index([moduleId])
@@map("submission_scores")
}
model SubmissionTotalScore {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
weekId String @map("week_id") @db.Uuid
studentId String @map("student_id") @db.Uuid
score Int @default(0)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
week CourseWeek @relation(fields: [weekId], references: [id], onDelete: Cascade)
student User @relation(fields: [studentId], references: [id], onDelete: Cascade)
@@unique([studentId, weekId])
@@index([courseId])
@@index([weekId])
@@map("submission_total_scores")
}
model CourseWeekTopic {
id String @id @default(uuid()) @db.Uuid
weekId String @map("week_id") @db.Uuid
title String
detail String
sortOrder Int @map("sort_order")
week CourseWeek @relation(fields: [weekId], references: [id], onDelete: Cascade)
@@unique([weekId, sortOrder])
@@index([weekId])
@@map("course_week_topics")
}
model CourseWeekPractice {
id String @id @default(uuid()) @db.Uuid
weekId String @map("week_id") @db.Uuid
title String
description String
sortOrder Int @map("sort_order")
week CourseWeek @relation(fields: [weekId], references: [id], onDelete: Cascade)
@@unique([weekId, sortOrder])
@@index([weekId])
@@map("course_week_practices")
}
model CourseWeekReference {
id String @id @default(uuid()) @db.Uuid
weekId String @map("week_id") @db.Uuid
kind String @default("REFERENCE")
title String
originalFileName String @map("original_file_name")
storedFileName String @map("stored_file_name")
contentType String? @map("content_type")
fileSizeBytes Int @default(0) @map("file_size_bytes")
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
week CourseWeek @relation(fields: [weekId], references: [id], onDelete: Cascade)
@@unique([weekId, storedFileName])
@@index([weekId])
@@index([weekId, kind])
@@map("course_week_references")
}
enum ChatThreadType {
AI
INSTRUCTOR
MIXED
}
enum ChatThreadStatus {
OPEN
WAITING_INSTRUCTOR
RESOLVED
ARCHIVED
}
enum ChatSenderType {
STUDENT
AI
INSTRUCTOR
SYSTEM
}
enum ChatContentFormat {
TEXT
MARKDOWN
}
enum ChatMessageStatus {
ACTIVE
CANCELED
}
enum AiChatRunStatus {
SUCCEEDED
FAILED
}
model ChatThread {
id String @id @default(uuid()) @db.Uuid
courseId String @map("course_id") @db.Uuid
weekId String? @map("week_id") @db.Uuid
studentId String @map("student_id") @db.Uuid
assignedInstructorId String? @map("assigned_instructor_id") @db.Uuid
type ChatThreadType
status ChatThreadStatus @default(OPEN)
title String?
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
lastMessageAt DateTime @default(now()) @map("last_message_at") @db.Timestamptz(3)
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
week CourseWeek? @relation(fields: [weekId], references: [id], onDelete: SetNull)
student User @relation("ChatThreadStudent", fields: [studentId], references: [id], onDelete: Cascade)
assignedInstructor User? @relation("ChatThreadInstructor", fields: [assignedInstructorId], references: [id], onDelete: SetNull)
messages ChatMessage[]
@@index([courseId, type, lastMessageAt])
@@index([studentId, type, lastMessageAt])
@@index([weekId])
@@index([assignedInstructorId])
@@map("chat_threads")
}
model ChatMessage {
id String @id @default(uuid()) @db.Uuid
threadId String @map("thread_id") @db.Uuid
senderType ChatSenderType @map("sender_type")
senderUserId String? @map("sender_user_id") @db.Uuid
content String
contentFormat ChatContentFormat @default(TEXT) @map("content_format")
status ChatMessageStatus @default(ACTIVE)
metadata Json?
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
canceledAt DateTime? @map("canceled_at") @db.Timestamptz(3)
deletedAt DateTime? @map("deleted_at") @db.Timestamptz(3)
thread ChatThread @relation(fields: [threadId], references: [id], onDelete: Cascade)
senderUser User? @relation(fields: [senderUserId], references: [id], onDelete: SetNull)
aiRun AiChatRun?
@@index([threadId, createdAt])
@@index([threadId, status, createdAt])
@@index([senderUserId])
@@map("chat_messages")
}
model AiChatRun {
id String @id @default(uuid()) @db.Uuid
messageId String @unique @map("message_id") @db.Uuid
model String
promptTokens Int? @map("prompt_tokens")
completionTokens Int? @map("completion_tokens")
totalTokens Int? @map("total_tokens")
latencyMs Int? @map("latency_ms")
status AiChatRunStatus
error String?
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
message ChatMessage @relation(fields: [messageId], references: [id], onDelete: Cascade)
@@index([status, createdAt])
@@map("ai_chat_runs")
}