macbook 에서 리눅스로 이동
This commit is contained in:
137
docs/database.md
Normal file
137
docs/database.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# DB 설계(1차)
|
||||
|
||||
## 핵심 엔티티
|
||||
- Campaign(종목), LandingPage, LandingRoute, RouteCondition, Lead, User
|
||||
- 역할: ADMIN / LEAD_MANAGER
|
||||
|
||||
## 엔티티 관계
|
||||
- Campaign 1:N LandingPage
|
||||
- Campaign 1:N LandingRoute
|
||||
- LandingRoute 1:N RouteCondition
|
||||
- LandingRoute N:1 LandingPage(기본 페이지)
|
||||
- RouteCondition N:1 LandingPage(조건 매칭 페이지)
|
||||
- LandingPage 1:N Lead
|
||||
- Campaign 1:N Lead
|
||||
|
||||
## 권한 정책
|
||||
- ADMIN: 모든 관리자 기능
|
||||
- LEAD_MANAGER: 리드 조회만 가능
|
||||
|
||||
## Prisma 스키마 (SQLite 기준)
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum UserRole {
|
||||
ADMIN
|
||||
LEAD_MANAGER
|
||||
}
|
||||
|
||||
model Campaign {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
description String?
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
landingPages LandingPage[]
|
||||
routes LandingRoute[]
|
||||
leads Lead[]
|
||||
}
|
||||
|
||||
model LandingPage {
|
||||
id String @id @default(cuid())
|
||||
campaignId String
|
||||
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
slug String?
|
||||
blocks Json
|
||||
isDefault Boolean @default(false)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
defaultRoutes LandingRoute[] @relation("RouteDefaultPage")
|
||||
conditions RouteCondition[]
|
||||
leads Lead[]
|
||||
|
||||
@@index([campaignId, isActive])
|
||||
}
|
||||
|
||||
model LandingRoute {
|
||||
id String @id @default(cuid())
|
||||
campaignId String
|
||||
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
|
||||
host String
|
||||
path String
|
||||
defaultPageId String
|
||||
defaultPage LandingPage @relation("RouteDefaultPage", fields: [defaultPageId], references: [id], onDelete: Restrict)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
conditions RouteCondition[]
|
||||
leads Lead[]
|
||||
|
||||
@@unique([host, path])
|
||||
}
|
||||
|
||||
model RouteCondition {
|
||||
id String @id @default(cuid())
|
||||
routeId String
|
||||
route LandingRoute @relation(fields: [routeId], references: [id], onDelete: Cascade)
|
||||
pageId String
|
||||
page LandingPage @relation(fields: [pageId], references: [id], onDelete: Restrict)
|
||||
label String
|
||||
priority Int @default(0)
|
||||
isActive Boolean @default(true)
|
||||
|
||||
startDate DateTime?
|
||||
endDate DateTime?
|
||||
timezone String @default("Asia/Seoul")
|
||||
weekMask String @default("0000000")
|
||||
startMinute Int?
|
||||
endMinute Int?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Lead {
|
||||
id String @id @default(cuid())
|
||||
campaignId String
|
||||
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
|
||||
pageId String
|
||||
page LandingPage @relation(fields: [pageId], references: [id], onDelete: Restrict)
|
||||
routeId String?
|
||||
route LandingRoute? @relation(fields: [routeId], references: [id], onDelete: SetNull)
|
||||
payload Json
|
||||
sourceMeta Json?
|
||||
submittedAt DateTime @default(now())
|
||||
|
||||
@@index([campaignId, submittedAt])
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
name String?
|
||||
password String
|
||||
role UserRole @default(ADMIN)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 참고
|
||||
- `defaultRoutes`는 `@relation("RouteDefaultPage")`로 라우트 기본 페이지 역참조입니다.
|
||||
- 동일 엔티티에서 기본 라우트를 찾을 때는 `LandingRoute.defaultPageId`가 FK입니다.
|
||||
- PostgreSQL 전환 시 datasource `provider`만 교체하지 않고 nullable/시간대 처리 포함 마이그레이션 검증이 필요하다.
|
||||
Reference in New Issue
Block a user