generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum UserRole { admin seller buyer } enum ProjectStatus { draft pending approved rejected suspended } enum OrderStatus { pending paid cancelled refunded } enum PaymentGateway { toss stripe } model User { id String @id @default(uuid()) email String @unique passwordHash String nickname String @unique role UserRole @default(buyer) profileImageUrl String? isEmailVerified Boolean @default(false) isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt lastLoginAt DateTime? lastLoginIp String? projects Project[] orders Order[] reviews Review[] auditLogs AuditLog[] } model Project { id String @id @default(uuid()) userId String user User @relation(fields: [userId], references: [id]) title String description String @db.Text difficultyLevel Int @default(3) requiredParts Json? status ProjectStatus @default(draft) adminNote String? commissionRate Float @default(0.1) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt files ProjectFile[] product Product? } model ProjectFile { id String @id @default(uuid()) projectId String project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) fileType String url String thumbnailUrl String? fileSize Int mimeType String originalName String? displayOrder Int @default(0) createdAt DateTime @default(now()) } model Product { id String @id @default(uuid()) projectId String @unique project Project @relation(fields: [projectId], references: [id]) price Int isOnSale Boolean @default(true) totalSales Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt orders Order[] reviews Review[] } model Order { id String @id @default(uuid()) buyerId String buyer User @relation(fields: [buyerId], references: [id]) productId String product Product @relation(fields: [productId], references: [id]) amount Int commissionAmount Int sellerAmount Int paymentGateway PaymentGateway @default(toss) paymentKey String? tossOrderId String? @unique status OrderStatus @default(pending) buyerInfo Json deviceInfo Json? orderedAt DateTime @default(now()) paidAt DateTime? refundedAt DateTime? refundReason String? flashToken FlashToken? review Review? } model FlashToken { id String @id @default(uuid()) token String @unique @default(uuid()) orderId String @unique order Order @relation(fields: [orderId], references: [id]) isUsed Boolean @default(false) usedAt DateTime? macAddress String? chipFamily String? expiresAt DateTime createdAt DateTime @default(now()) flashLog FlashLog? } model FlashLog { id String @id @default(uuid()) flashTokenId String @unique flashToken FlashToken @relation(fields: [flashTokenId], references: [id]) macAddress String chipFamily String firmwareName String firmwareId String success Boolean errorMessage String? clientIp String userAgent String? flashedAt DateTime @default(now()) } model Review { id String @id @default(uuid()) orderId String @unique order Order @relation(fields: [orderId], references: [id]) userId String user User @relation(fields: [userId], references: [id]) productId String product Product @relation(fields: [productId], references: [id]) rating Int title String content String @db.Text isVisible Boolean @default(true) createdAt DateTime @default(now()) media ReviewMedia[] } model ReviewMedia { id String @id @default(uuid()) reviewId String review Review @relation(fields: [reviewId], references: [id], onDelete: Cascade) mediaType String url String thumbnailUrl String? createdAt DateTime @default(now()) } model AuditLog { id String @id @default(uuid()) userId String? user User? @relation(fields: [userId], references: [id]) action String targetType String? targetId String? ipAddress String userAgent String? requestMethod String? requestPath String? requestBody Json? responseStatus Int? metadata Json? createdAt DateTime @default(now()) @@index([userId]) @@index([action]) @@index([createdAt]) }