Files
travelplanning/schema.prisma
T

155 lines
3.9 KiB
Plaintext

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
}
// --- Enums ---
enum MemberRole {
OWNER
EDITOR
MEMBER_PLAN_ONLY
MEMBER_PHOTO_ONLY
VIEWER_EXTERNAL
}
enum ExpenseCategory {
LODGING
DINING
TRANSPORT
OTHER
}
enum TriggerType {
AUTO_BY_TIME
MANUAL_BY_USER
}
enum PrivacyLevel {
PUBLIC_IN_TOUR
PRIVATE_OWNER
}
// --- Models ---
model User {
id Int @id @default(autoincrement())
email String @unique
passwordHash String
name String?
avatar String?
createdAt DateTime @default(now())
isAdmin Boolean @default(false)
createdTours Tour[] @relation("TourCreator")
tourMemberships TourMember[]
uploadedPhotos Photo[]
}
model Tour {
id Int @id @default(autoincrement())
title String
startDate DateTime?
endDate DateTime?
createdAt DateTime @default(now())
creatorId Int
creator User @relation("TourCreator", fields: [creatorId], references: [id])
members TourMember[]
legs Leg[]
tasks Task[]
photos Photo[]
}
model TourMember {
tourId Int
userId Int
role MemberRole @default(MEMBER_PLAN_ONLY)
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@id([tourId, userId])
}
model Leg {
id Int @id @default(autoincrement())
tourId Int
sequenceNumber Int
notes String? @db.Text
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
places Place[]
expenses Expense[]
tasks Task[]
}
model Place {
id Int @id @default(autoincrement())
legId Int
name String
address String?
// Sử dụng Float cho Lat/Lng để dễ thao tác ở Frontend.
// Nếu bạn muốn dùng PostGIS chuyên sâu, có thể dùng Unsupported("geography(Point, 4326)")
latitude Float
longitude Float
sequenceInLeg Int
arrivalTime DateTime?
departureTime DateTime?
leg Leg @relation(fields: [legId], references: [id], onDelete: Cascade)
expenses Expense[]
photos Photo[]
}
model Expense {
id Int @id @default(autoincrement())
legId Int
placeId Int?
category ExpenseCategory
amount Decimal @db.Decimal(15, 2)
currency String @default("VND")
description String? @db.Text
leg Leg @relation(fields: [legId], references: [id], onDelete: Cascade)
place Place? @relation(fields: [placeId], references: [id], onDelete: Cascade)
}
model Task {
id Int @id @default(autoincrement())
tourId Int
legId Int?
title String
plannedTimestamp DateTime
isCompleted Boolean @default(false)
completedAt DateTime?
triggerType TriggerType @default(MANUAL_BY_USER)
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
leg Leg? @relation(fields: [legId], references: [id])
}
model Photo {
id Int @id @default(autoincrement())
tourId Int
placeId Int?
uploaderId Int
imageUrl String
capturedAt DateTime @default(now())
privacyLevel PrivacyLevel @default(PUBLIC_IN_TOUR)
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
place Place? @relation(fields: [placeId], references: [id], onDelete: SetNull)
uploader User @relation(fields: [uploaderId], references: [id])
}