TreasureTrails/backend/prisma/schema.prisma

177 lines
5 KiB
Text

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
email String @unique
passwordHash String
name String
screenName String?
avatarUrl String?
unitPreference UnitPreference @default(METRIC)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
games Game[] @relation("GameMaster")
teams TeamMember[]
captainOf Team? @relation("TeamCaptain")
chatMessages ChatMessage[]
locationHistory LocationHistory[]
}
enum UnitPreference {
METRIC
IMPERIAL
}
model Game {
id String @id @default(uuid())
name String
description String?
prizeDetails String?
visibility Visibility @default(PUBLIC)
startDate DateTime?
locationLat Float?
locationLng Float?
searchRadius Float?
rules String?
randomizeRoutes Boolean @default(false)
status GameStatus @default(DRAFT)
inviteCode String? @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
gameMasterId String
gameMaster User @relation("GameMaster", fields: [gameMasterId], references: [id])
routes Route[]
teams Team[]
chatMessages ChatMessage[]
locationHistory LocationHistory[]
}
model Route {
id String @id @default(uuid())
gameId String
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
name String
description String?
color String @default("#3498db")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
routeLegs RouteLeg[]
teamRoutes TeamRoute[]
}
model RouteLeg {
id String @id @default(uuid())
routeId String
route Route @relation(fields: [routeId], references: [id], onDelete: Cascade)
sequenceNumber Int
description String
conditionType String @default("photo")
conditionDetails String?
locationLat Float?
locationLng Float?
timeLimit Int?
}
model Team {
id String @id @default(uuid())
gameId String
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
name String
captainId String? @unique
captain User? @relation("TeamCaptain", fields: [captainId], references: [id])
currentLegIndex Int @default(0)
status TeamStatus @default(ACTIVE)
totalTimeDeduction Int @default(0)
lat Float?
lng Float?
rank Int?
createdAt DateTime @default(now())
members TeamMember[]
photoSubmissions PhotoSubmission[]
chatMessages ChatMessage[]
teamRoutes TeamRoute[]
}
model TeamRoute {
id String @id @default(uuid())
teamId String
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
routeId String
route Route @relation(fields: [routeId], references: [id])
assignedAt DateTime @default(now())
@@unique([teamId])
}
model TeamMember {
id String @id @default(uuid())
teamId String
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id])
joinedAt DateTime @default(now())
@@unique([teamId, userId])
}
model PhotoSubmission {
id String @id @default(uuid())
teamId String
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
routeId String
routeLegId String
photoUrl String
approved Boolean @default(false)
submittedAt DateTime @default(now())
}
model ChatMessage {
id String @id @default(uuid())
gameId String
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
teamId String?
team Team? @relation(fields: [teamId], references: [id])
userId String
user User @relation(fields: [userId], references: [id])
message String
isDirect Boolean @default(false)
sentAt DateTime @default(now())
}
model LocationHistory {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
gameId String
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
teamId String
lat Float
lng Float
accuracy Float?
recordedAt DateTime @default(now())
}
enum Visibility {
PUBLIC
PRIVATE
}
enum GameStatus {
DRAFT
LIVE
ENDED
ARCHIVED
}
enum TeamStatus {
ACTIVE
DISQUALIFIED
FINISHED
}