// 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 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) createdTours Tour[] @relation("TourCreator") tourParticipations TourParticipant[] requestedJoinRequests JoinRequest[] @relation("JoinRequestUser") receivedJoinRequests JoinRequest[] @relation("JoinRequester") uploadedPhotos Photo[] paidExpenses Expense[] @relation("ExpensePaidBy") } model Tour { id String @id @default(uuid()) title String startDate DateTime? endDate DateTime? createdAt DateTime @default(now()) totalCost Decimal @default(0) @db.Decimal(15, 2) createdById String creator User @relation("TourCreator", fields: [createdById], references: [id]) participants TourParticipant[] joinRequests JoinRequest[] legs Leg[] photos Photo[] } 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 { tourId String userId String role ParticipantRole @default(MEMBER) tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@id([tourId, userId]) } model Leg { id String @id @default(uuid()) tourId String sequence Int note 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[] } 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 capturedAt DateTime @default(now()) metadata Json? privacy PrivacyLevel @default(TOUR_ONLY) tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade) location Location? @relation(fields: [locationId], references: [id], onDelete: SetNull) uploader User @relation(fields: [uploaderId], references: [id]) }