Files
esp32DIY_web/backend/prisma/schema.prisma
root 182782f271 feat: ESP32 DIY platform Phase 1 — marketplace with mock payment & flash token flow
- React+Vite frontend (dark theme, role-based routing: admin/seller/buyer)
- Express+Prisma+PostgreSQL backend with JWT auth and audit logging
- MinIO object storage with backend proxy for CORS-free firmware delivery
- Mock payment flow (order → mock-pay → FlashToken) for pre-business testing
- FlashToken lifecycle: issue → validate → esp-web-tools manifest → consume
- Admin approval workflow for project/product submissions
- Toss Payments integration guide (TOSS_PAYMENT_GUIDE.md) for live keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 06:43:08 +09:00

205 lines
5.0 KiB
Plaintext

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)
chipFamily String @default("ESP32-S3")
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?
flashOffset String @default("0x0")
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])
}