advance
This commit is contained in:
215
prisma/schema.prisma
Executable file
215
prisma/schema.prisma
Executable file
@@ -0,0 +1,215 @@
|
||||
// prisma/schema.prisma
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
// --- ENUMS ---
|
||||
|
||||
enum UserRole {
|
||||
SUPER_ADMIN // You (Full Access)
|
||||
ORG_ADMIN // Law Firm Manager (View Team Progress, Manage Seats)
|
||||
TEACHER // Content Creator (Create/Edit their own courses)
|
||||
LEARNER // Student (View content, take quizzes)
|
||||
}
|
||||
|
||||
enum ContentStatus {
|
||||
DRAFT
|
||||
PUBLISHED
|
||||
ARCHIVED
|
||||
}
|
||||
|
||||
enum ProficiencyLevel {
|
||||
BEGINNER // A1-A2
|
||||
INTERMEDIATE // B1-B2
|
||||
ADVANCED // C1-C2
|
||||
EXPERT // Legal Specific
|
||||
}
|
||||
|
||||
enum ExerciseType {
|
||||
MULTIPLE_CHOICE
|
||||
FILL_IN_BLANK
|
||||
TRANSLATION
|
||||
MATCHING
|
||||
}
|
||||
|
||||
// --- MODELS ---
|
||||
|
||||
model Profile {
|
||||
id String @id @default(uuid()) // Links to Supabase Auth.uid()
|
||||
email String @unique
|
||||
fullName String?
|
||||
avatarUrl String?
|
||||
role UserRole @default(LEARNER)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
memberships Membership[] // B2B Access
|
||||
enrollments Enrollment[] // B2C Purchases (Mercado Pago)
|
||||
progress UserProgress[]
|
||||
certificates Certificate[]
|
||||
authoredCourses Course[] @relation("CourseAuthor") // Teachers own courses
|
||||
}
|
||||
|
||||
model Company {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
logoUrl String?
|
||||
billingEmail String?
|
||||
maxSeats Int @default(5) // Limit for B2B plans
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
memberships Membership[]
|
||||
certificates Certificate[]
|
||||
}
|
||||
|
||||
model Membership {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
companyId String
|
||||
isActive Boolean @default(true)
|
||||
role String @default("MEMBER") // Internal org role (Member/Admin)
|
||||
|
||||
joinedAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
user Profile @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, companyId]) // Prevent duplicate memberships
|
||||
}
|
||||
|
||||
model Course {
|
||||
id String @id @default(uuid())
|
||||
title Json // { "en": "...", "es": "..." }
|
||||
slug String @unique // Required for SEO URLs (e.g. /course/contract-law)
|
||||
description Json // { "en": "...", "es": "..." }
|
||||
level ProficiencyLevel @default(INTERMEDIATE)
|
||||
tags String[]
|
||||
|
||||
status ContentStatus @default(DRAFT)
|
||||
price Decimal @default(0.00) // Price in MXN
|
||||
|
||||
authorId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Prerequisites
|
||||
prerequisiteId String?
|
||||
prerequisite Course? @relation("CoursePrerequisites", fields: [prerequisiteId], references: [id])
|
||||
dependents Course[] @relation("CoursePrerequisites")
|
||||
|
||||
author Profile @relation("CourseAuthor", fields: [authorId], references: [id])
|
||||
modules Module[]
|
||||
certificates Certificate[]
|
||||
enrollments Enrollment[]
|
||||
}
|
||||
|
||||
model Enrollment {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
courseId String
|
||||
|
||||
// Payment Proof (Mercado Pago)
|
||||
amountPaid Decimal // e.g. 500.00
|
||||
currency String @default("MXN")
|
||||
paymentMethod String @default("MERCADO_PAGO")
|
||||
externalId String? // The Mercado Pago "payment_id" or "preference_id"
|
||||
|
||||
purchasedAt DateTime @default(now())
|
||||
|
||||
user Profile @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, courseId]) // Prevent buying the same course twice
|
||||
}
|
||||
|
||||
model Module {
|
||||
id String @id @default(uuid())
|
||||
courseId String
|
||||
title Json
|
||||
orderIndex Int
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
|
||||
lessons Lesson[]
|
||||
}
|
||||
|
||||
model Lesson {
|
||||
id String @id @default(uuid())
|
||||
moduleId String
|
||||
title Json
|
||||
description Json?
|
||||
slug String? // Optional for direct linking
|
||||
orderIndex Int
|
||||
videoUrl String?
|
||||
estimatedDuration Int // Seconds
|
||||
version Int @default(1)
|
||||
isFreePreview Boolean @default(false) // Marketing hook
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
module Module @relation(fields: [moduleId], references: [id], onDelete: Cascade)
|
||||
exercises Exercise[]
|
||||
resources Resource[]
|
||||
userProgress UserProgress[]
|
||||
}
|
||||
|
||||
model Exercise {
|
||||
id String @id @default(uuid())
|
||||
lessonId String
|
||||
type ExerciseType
|
||||
content Json // { question: "...", options: [...], answer: "..." }
|
||||
orderIndex Int @default(0)
|
||||
|
||||
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model Resource {
|
||||
id String @id @default(uuid())
|
||||
lessonId String
|
||||
fileUrl String
|
||||
displayName Json
|
||||
fileType String
|
||||
|
||||
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model UserProgress {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
lessonId String
|
||||
isCompleted Boolean @default(false)
|
||||
score Int? // For quiz results
|
||||
startedAt DateTime @default(now())
|
||||
finishedAt DateTime?
|
||||
lastPlayedAt DateTime @default(now()) // For "Resume" feature
|
||||
|
||||
user Profile @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, lessonId]) // One progress record per lesson
|
||||
}
|
||||
|
||||
model Certificate {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
courseId String
|
||||
companyId String? // Captured for co-branding (Nullable for B2C)
|
||||
issuedAt DateTime @default(now())
|
||||
metadataSnapshot Json // Burn the course name/version here
|
||||
|
||||
user Profile @relation(fields: [userId], references: [id])
|
||||
course Course @relation(fields: [courseId], references: [id])
|
||||
company Company? @relation(fields: [companyId], references: [id])
|
||||
}
|
||||
Reference in New Issue
Block a user