generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) email String @unique name String? image String? createdAt DateTime @default(now()) emailVerified DateTime? role String @default("user") accounts Account[] comments Comment[] replies CommentReply[] enrollments Enrollment[] sessions Session[] likes VideoLike[] progress VideoProgress[] unlocks VideoUnlock[] watchSegments VideoWatchSegment[] uploadedVideos Video[] @relation("VideoUploader") createdCourses Course[] @relation("CourseCreator") createdPlaylists Playlist[] @relation("PlaylistCreator") } model Course { id String @id @default(cuid()) code String @unique title String description String? userId String? createdAt DateTime @default(now()) creator User? @relation("CourseCreator", fields: [userId], references: [id], onDelete: SetNull) enrollments Enrollment[] playlists Playlist[] playlistMappings CoursePlaylist[] courseVideos VideoCourse[] } model Enrollment { id String @id @default(cuid()) userId String courseId String createdAt DateTime @default(now()) course Course @relation(fields: [courseId], references: [id]) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([userId, courseId]) @@index([courseId]) } model Playlist { id String @id @default(cuid()) title String description String? courseId String // Primary course (backwards compatibility) userId String? sortOrder Int @default(0) createdAt DateTime @default(now()) course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) creator User? @relation("PlaylistCreator", fields: [userId], references: [id], onDelete: SetNull) videos Video[] courses CoursePlaylist[] // Additional courses this playlist is assigned to @@index([courseId]) } model CoursePlaylist { id String @id @default(cuid()) courseId String playlistId String createdAt DateTime @default(now()) course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) playlist Playlist @relation(fields: [playlistId], references: [id], onDelete: Cascade) @@unique([courseId, playlistId]) @@index([courseId]) @@index([playlistId]) } model Video { id String @id @default(cuid()) title String playlistId String userId String? durationSec Int? url String thumbnail String? index Int @default(0) locked Boolean @default(false) createdAt DateTime @default(now()) description String? instantAccess Boolean @default(false) transcodingStatus String @default("uploaded") comments Comment[] playlist Playlist @relation(fields: [playlistId], references: [id]) uploader User? @relation("VideoUploader", fields: [userId], references: [id], onDelete: SetNull) likes VideoLike[] progress VideoProgress[] unlocks VideoUnlock[] watchSegments VideoWatchSegment[] videoCourses VideoCourse[] @@unique([playlistId, index]) @@index([playlistId]) @@index([userId]) @@index([transcodingStatus]) } model VideoCourse { id String @id @default(cuid()) videoId String courseId String exclusive Boolean @default(true) createdAt DateTime @default(now()) video Video @relation(fields: [videoId], references: [id], onDelete: Cascade) course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) @@unique([videoId, courseId]) @@index([courseId]) @@index([videoId]) } model VideoProgress { id String @id @default(cuid()) userId String videoId String updatedAt DateTime @updatedAt completed Boolean @default(false) createdAt DateTime @default(now()) lastPos Int? percent Int @default(0) watchedSec Int @default(0) durationSec Int? user User @relation(fields: [userId], references: [id], onDelete: Cascade) video Video @relation(fields: [videoId], references: [id], onDelete: Cascade) watchSegments VideoWatchSegment[] @@unique([userId, videoId]) } model VideoWatchSegment { id String @id @default(cuid()) userId String videoId String startSec Int endSec Int watchedAt DateTime @default(now()) createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) progress VideoProgress @relation(fields: [userId, videoId], references: [userId, videoId], onDelete: Cascade) video Video @relation(fields: [videoId], references: [id], onDelete: Cascade) @@index([userId, videoId]) @@index([watchedAt]) @@index([userId]) @@index([videoId]) } model VideoUnlock { id String @id @default(cuid()) userId String videoId String unlockedAt DateTime @default(now()) createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) video Video @relation(fields: [videoId], references: [id], onDelete: Cascade) @@unique([userId, videoId]) @@index([userId]) @@index([videoId]) @@index([userId, videoId]) } model VideoLike { id String @id @default(cuid()) userId String videoId String createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) video Video @relation(fields: [videoId], references: [id], onDelete: Cascade) @@unique([userId, videoId]) @@index([userId]) @@index([videoId]) } model Account { id String @id @default(cuid()) userId String type String provider String providerAccountId String refresh_token String? access_token String? expires_at Int? token_type String? scope String? id_token String? session_state String? user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([provider, providerAccountId]) @@index([userId]) } model Session { id String @id @default(cuid()) sessionToken String @unique userId String expires DateTime user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) } model VerificationToken { identifier String token String @unique expires DateTime @@unique([identifier, token]) } model Comment { id String @id @default(cuid()) userId String videoId String content String createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) video Video @relation(fields: [videoId], references: [id], onDelete: Cascade) replies CommentReply[] @@index([videoId]) @@index([userId]) } model CommentReply { id String @id @default(cuid()) userId String commentId String content String createdAt DateTime @default(now()) comment Comment @relation(fields: [commentId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([commentId]) @@index([userId]) } model AllowedStudent { id String @id @default(cuid()) email String @unique levels String // comma-separated course codes: "3D100,3D200,3D300" active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }