299 lines
8.4 KiB
Plaintext
299 lines
8.4 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"
|
|
previewFeatures = ["driverAdapters"]
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// --- Enums ---
|
|
|
|
enum ParticipantRole {
|
|
OWNER
|
|
MANAGER
|
|
MEMBER
|
|
MEMBER_NO_FINANCE
|
|
VIEWER_ONLY
|
|
}
|
|
|
|
enum JoinRequestStatus {
|
|
PENDING
|
|
ACCEPTED
|
|
REJECTED
|
|
}
|
|
|
|
enum ExpenseCategory {
|
|
ACCOMMODATION
|
|
FOOD
|
|
TRANSPORT
|
|
TICKET
|
|
OTHER
|
|
}
|
|
|
|
enum LocationStatus {
|
|
PENDING
|
|
COMPLETED
|
|
}
|
|
|
|
enum LocationType {
|
|
MOVE
|
|
VISIT
|
|
REST
|
|
EAT
|
|
}
|
|
|
|
enum PrivacyLevel {
|
|
PUBLIC
|
|
TOUR_ONLY
|
|
PRIVATE
|
|
}
|
|
|
|
// --- Models ---
|
|
|
|
model User {
|
|
id String @id @default(uuid())
|
|
email String? @unique
|
|
passwordHash String?
|
|
name String?
|
|
phone String?
|
|
address String?
|
|
avatar String?
|
|
createdAt DateTime @default(now())
|
|
isAdmin Boolean @default(false)
|
|
isBlocked Boolean @default(false)
|
|
isAnonymous Boolean @default(false)
|
|
|
|
createdTours Tour[] @relation("TourCreator")
|
|
tourParticipations TourParticipant[]
|
|
requestedJoinRequests JoinRequest[] @relation("JoinRequestUser")
|
|
receivedJoinRequests JoinRequest[] @relation("JoinRequester")
|
|
uploadedPhotos Photo[]
|
|
paidExpenses Expense[] @relation("ExpensePaidBy")
|
|
comments Comment[]
|
|
sentConnections UserConnection[] @relation("ConnectionRequester")
|
|
receivedConnections UserConnection[] @relation("ConnectionReceiver")
|
|
sentMessages DirectMessage[] @relation("MessageSender")
|
|
receivedMessages DirectMessage[] @relation("MessageReceiver")
|
|
tourMessages TourMessage[]
|
|
}
|
|
|
|
model Tour {
|
|
id String @id @default(uuid())
|
|
title String
|
|
description String?
|
|
startDate DateTime?
|
|
endDate DateTime?
|
|
createdAt DateTime @default(now())
|
|
totalCost Decimal @default(0) @db.Decimal(15, 2)
|
|
|
|
adultCount Int @default(1)
|
|
childCount Int @default(0)
|
|
childDiscount Int @default(30)
|
|
|
|
tags String[]
|
|
createdById String
|
|
creator User @relation("TourCreator", fields: [createdById], references: [id])
|
|
|
|
participants TourParticipant[]
|
|
joinRequests JoinRequest[]
|
|
legs Leg[]
|
|
photos Photo[]
|
|
invitations TourInvitation[]
|
|
tourMessages TourMessage[]
|
|
}
|
|
|
|
model JoinRequest {
|
|
id String @id @default(uuid())
|
|
tourId String
|
|
userId String
|
|
requestedById String
|
|
status JoinRequestStatus @default(PENDING)
|
|
createdAt DateTime @default(now())
|
|
|
|
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
|
|
user User @relation("JoinRequestUser", fields: [userId], references: [id], onDelete: Cascade)
|
|
requestedBy User @relation("JoinRequester", fields: [requestedById], references: [id], onDelete: Cascade)
|
|
|
|
@@index([tourId, status])
|
|
@@index([userId])
|
|
}
|
|
|
|
model TourParticipant {
|
|
id String @id @default(uuid())
|
|
tourId String
|
|
userId String?
|
|
role ParticipantRole @default(MEMBER)
|
|
displayName String?
|
|
adultCount Int @default(1)
|
|
childCount Int @default(0)
|
|
|
|
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
|
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([tourId, userId])
|
|
}
|
|
|
|
model Leg {
|
|
id String @id @default(uuid())
|
|
tourId String
|
|
sequence Int
|
|
note String? @db.Text
|
|
startDate DateTime?
|
|
endDate DateTime?
|
|
description String? @db.Text
|
|
|
|
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
|
|
locations Location[]
|
|
expenses Expense[]
|
|
}
|
|
|
|
model Location {
|
|
id String @id @default(uuid())
|
|
legId String
|
|
name String
|
|
address String?
|
|
latitude Float
|
|
longitude Float
|
|
|
|
plannedStart DateTime?
|
|
plannedEnd DateTime?
|
|
actualStart DateTime?
|
|
actualEnd DateTime?
|
|
|
|
status LocationStatus @default(PENDING)
|
|
type LocationType @default(VISIT)
|
|
|
|
leg Leg @relation(fields: [legId], references: [id], onDelete: Cascade)
|
|
expenses Expense[]
|
|
photos Photo[]
|
|
comments Comment[]
|
|
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model Expense {
|
|
id String @id @default(uuid())
|
|
legId String @map("leg_id")
|
|
locationId String? @map("location_id")
|
|
category ExpenseCategory
|
|
amount Decimal @db.Decimal(15, 2)
|
|
description String? @db.Text
|
|
note String? @db.Text
|
|
paidById String? @map("paid_by_id")
|
|
|
|
leg Leg @relation(fields: [legId], references: [id], onDelete: Cascade)
|
|
location Location? @relation(fields: [locationId], references: [id], onDelete: Cascade)
|
|
paidBy User? @relation("ExpensePaidBy", fields: [paidById], references: [id], onDelete: SetNull)
|
|
}
|
|
|
|
model Photo {
|
|
id String @id @default(uuid())
|
|
tourId String?
|
|
locationId String?
|
|
uploaderId String
|
|
imageUrl String?
|
|
originalUrl String?
|
|
capturedAt DateTime @default(now())
|
|
metadata Json?
|
|
privacy PrivacyLevel @default(TOUR_ONLY)
|
|
|
|
tour Tour? @relation(fields: [tourId], references: [id], onDelete: SetNull)
|
|
location Location? @relation(fields: [locationId], references: [id], onDelete: SetNull)
|
|
uploader User @relation(fields: [uploaderId], references: [id])
|
|
comments Comment[]
|
|
}
|
|
|
|
model Comment {
|
|
id String @id @default(uuid())
|
|
content String
|
|
createdAt DateTime @default(now())
|
|
locationId String?
|
|
location Location? @relation(fields: [locationId], references: [id], onDelete: Cascade)
|
|
photoId String?
|
|
photo Photo? @relation(fields: [photoId], references: [id], onDelete: Cascade)
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model TourInvitation {
|
|
id String @id @default(uuid())
|
|
tourId String
|
|
email String
|
|
role ParticipantRole @default(MEMBER)
|
|
token String @unique
|
|
createdAt DateTime @default(now())
|
|
expiredAt DateTime
|
|
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([tourId, email])
|
|
}
|
|
|
|
enum ConnectionStatus {
|
|
PENDING
|
|
ACCEPTED
|
|
REJECTED
|
|
}
|
|
|
|
enum ConnectionType {
|
|
FRIEND
|
|
FAMILY
|
|
}
|
|
|
|
model UserConnection {
|
|
id String @id @default(uuid())
|
|
requesterId String
|
|
receiverId String
|
|
status ConnectionStatus @default(PENDING)
|
|
type ConnectionType @default(FRIEND)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
requester User @relation("ConnectionRequester", fields: [requesterId], references: [id], onDelete: Cascade)
|
|
receiver User @relation("ConnectionReceiver", fields: [receiverId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([requesterId, receiverId])
|
|
@@index([requesterId])
|
|
@@index([receiverId])
|
|
}
|
|
|
|
model DirectMessage {
|
|
id String @id @default(uuid())
|
|
senderId String
|
|
receiverId String
|
|
content String @db.Text
|
|
attachmentUrl String?
|
|
latitude Float?
|
|
longitude Float?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
sender User @relation("MessageSender", fields: [senderId], references: [id], onDelete: Cascade)
|
|
receiver User @relation("MessageReceiver", fields: [receiverId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([senderId])
|
|
@@index([receiverId])
|
|
}
|
|
|
|
model TourMessage {
|
|
id String @id @default(uuid())
|
|
tourId String
|
|
senderId String
|
|
content String @db.Text
|
|
attachmentUrl String?
|
|
latitude Float?
|
|
longitude Float?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
|
|
sender User @relation(fields: [senderId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([tourId])
|
|
@@index([senderId])
|
|
}
|