generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique password String @default("") name String role UserRole @default(USER) emailConfirmedAt DateTime? @db.Timestamptz(3) deactivated Boolean @default(false) createdAt DateTime @default(now()) @db.Timestamptz(3) updatedAt DateTime @updatedAt @db.Timestamptz(3) deletedAt DateTime? @db.Timestamptz(3) huntsCreated Hunt[] huntsMember HuntMember[] teamsOwner HuntTeam[] teamsMember TeamMember[] answers QuestAnswer[] @relation("AnswerMember") reviews Review[] uploadedFiles File[] } enum UserRole { USER CREATOR ADMIN } model File { id Int @id @default(autoincrement()) uuid String url String creator User @relation(fields: [creatorId], references: [id], onUpdate: Cascade, onDelete: Cascade) creatorId Int hunt Hunt? @relation(name: "OldHuntFiles", fields: [huntId], references: [id], onUpdate: Cascade, onDelete: Cascade) huntId Int? quest HuntQuest? @relation(name: "OldQuestFiles", fields: [questId], references: [id], onUpdate: Cascade, onDelete: Cascade) questId Int? answer QuestAnswer? @relation(name: "OldAnswerFiles", fields: [answerId], references: [id], onUpdate: Cascade, onDelete: Cascade) answerId Int? createdAt DateTime @default(now()) @db.Timestamptz(3) answers QuestAnswer[] quests HuntQuest[] hunts Hunt[] } model Hunt { id Int @id @default(autoincrement()) name String description String virtual Boolean @default(false) start DateTime? @db.Timestamptz(3) end DateTime? @db.Timestamptz(3) allowJoin Boolean @default(false) revealQuests Boolean @default(false) revealAnswers Boolean @default(false) creator User @relation(fields: [creatorId], references: [id], onUpdate: Cascade, onDelete: Cascade) creatorId Int picture File? @relation(fields: [pictureId], references: [id], onUpdate: Cascade, onDelete: Cascade) pictureId Int? createdAt DateTime @default(now()) @db.Timestamptz(3) updatedAt DateTime @updatedAt @db.Timestamptz(3) deletedAt DateTime? @db.Timestamptz(3) teams HuntTeam[] members HuntMember[] quests HuntQuest[] oldFiles File[] @relation("OldHuntFiles") @@index([creatorId]) } model HuntMember { hunt Hunt @relation(fields: [huntId], references: [id], onUpdate: Cascade, onDelete: Cascade) huntId Int member User @relation(fields: [memberId], references: [id], onUpdate: Cascade, onDelete: Cascade) memberId Int createdAt DateTime @default(now()) @db.Timestamptz(3) @@unique([memberId, huntId]) @@index([memberId, huntId]) @@index([memberId]) @@index([huntId]) } model HuntTeam { id Int @id @default(autoincrement()) name String description String @default("") password String @default("") hunt Hunt @relation(fields: [huntId], references: [id], onUpdate: Cascade, onDelete: Cascade) huntId Int owner User @relation(fields: [ownerId], references: [id], onUpdate: Cascade, onDelete: Cascade) ownerId Int createdAt DateTime @default(now()) @db.Timestamptz(3) members TeamMember[] answers QuestAnswer[] @@index([ownerId]) @@index([huntId]) } model TeamMember { team HuntTeam @relation(fields: [teamId], references: [id], onUpdate: Cascade, onDelete: Cascade) teamId Int member User @relation(fields: [memberId], references: [id], onUpdate: Cascade, onDelete: Cascade) memberId Int createdAt DateTime @default(now()) @db.Timestamptz(3) @@unique([memberId, teamId]) @@index([teamId]) @@index([memberId]) @@index([memberId, teamId]) } enum TextType { TEXT WORD NUMBER INTEGER } model HuntQuest { id Int @id @default(autoincrement()) title String description String @default("") question String? location String? locationLink String? picture File? @relation(fields: [pictureId], references: [id], onUpdate: Cascade, onDelete: Cascade) pictureId Int? order Int @default(0) optional Boolean @default(true) pictureRequired Boolean @default(false) textRequired Boolean @default(false) textType TextType @default(TEXT) textUnit String? textSolution String? points Int @default(10) @db.SmallInt extraPoints Int? @db.SmallInt extraText String? hunt Hunt @relation(fields: [huntId], references: [id], onUpdate: Cascade, onDelete: Cascade) huntId Int answers QuestAnswer[] oldFiles File[] @relation("OldQuestFiles") @@index([huntId]) } model QuestAnswer { id Int @id @default(autoincrement()) text String? location String? lat Decimal? @db.Decimal(10, 8) lon Decimal? @db.Decimal(10, 8) final Boolean @default(false) team HuntTeam @relation(fields: [teamId], references: [id], onUpdate: Cascade, onDelete: Cascade) teamId Int member User @relation("AnswerMember", fields: [memberId], references: [id], onUpdate: Cascade, onDelete: Cascade) memberId Int quest HuntQuest @relation(fields: [questId], references: [id], onUpdate: Cascade, onDelete: Cascade) questId Int picture File? @relation(fields: [pictureId], references: [id], onUpdate: Cascade, onDelete: Cascade) pictureId Int? createdAt DateTime @default(now()) @db.Timestamptz(3) updatedAt DateTime @updatedAt @db.Timestamptz(3) review Review? oldFiles File[] @relation("OldAnswerFiles") @@index([teamId]) @@index([memberId]) @@index([questId]) } model Review { id Int @id @default(autoincrement()) /// Final score for this answer including bonus score Int? @db.SmallInt /// Will be shown public once "revealAnswers" is true, otherwise its only visible for the team members review String? /// Will only be shown to hunt members internalNote String? /// Can be used for sorting answers based on a custom metric (e.g. distance, time) rankingValue Int? /// If true, this answer will be featured in the end showcase showcase Boolean @default(false) answer QuestAnswer @relation(fields: [answerId], references: [id], onUpdate: Cascade, onDelete: Cascade) answerId Int @unique reviewer User @relation(fields: [reviewerId], references: [id], onUpdate: Cascade, onDelete: Cascade) reviewerId Int createdAt DateTime @default(now()) @db.Timestamptz(3) updatedAt DateTime @updatedAt @db.Timestamptz(3) }