Files
Calbook/prisma/schema.prisma

170 lines
4.6 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
enum Role {
ADMIN
STAFF
}
enum AppointmentStatus {
CONFIRMED
CANCELLED
}
enum DeliveryChannel {
SMTP
CALDAV
}
enum SyncRunStatus {
RUNNING
SUCCESS
FAILED
}
model User {
id String @id @default(cuid())
name String
email String @unique
hashedPassword String
role Role @default(STAFF)
slug String @unique
bio String?
avatarUrl String?
timezone String @default("Europe/Berlin")
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
calendars CalendarConn[]
appointments Appointment[] @relation("StaffAppointments")
@@index([isActive])
@@index([role])
}
model CalendarConn {
id String @id @default(cuid())
userId String
name String
bookingAllowedWeekdays String @default("0,1,2,3,4")
bookingDayStartTime String @default("09:00")
bookingDayEndTime String @default("17:00")
bookingDayRangesJson String?
url String
username String
notificationEmail String?
encryptedPassword String
color String?
syncEnabled Boolean @default(true)
lastSyncedAt DateTime?
syncError String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
busyBlocks BusyBlock[]
syncRuns CalendarSyncRun[]
@@index([userId])
@@index([syncEnabled])
}
model CalendarSyncRun {
id String @id @default(cuid())
calendarConnId String
status SyncRunStatus @default(RUNNING)
message String?
startedAt DateTime @default(now())
finishedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
calendarConn CalendarConn @relation(fields: [calendarConnId], references: [id], onDelete: Cascade)
entries CalendarSyncLogEntry[]
@@index([calendarConnId, startedAt])
@@index([status, startedAt])
}
model CalendarSyncLogEntry {
id String @id @default(cuid())
syncRunId String
level String @default("INFO")
message String
createdAt DateTime @default(now())
syncRun CalendarSyncRun @relation(fields: [syncRunId], references: [id], onDelete: Cascade)
@@index([syncRunId, createdAt])
}
model BusyBlock {
id String @id @default(cuid())
calendarConnId String
externalUid String
startAt DateTime
endAt DateTime
syncedAt DateTime @default(now())
calendarConn CalendarConn @relation(fields: [calendarConnId], references: [id], onDelete: Cascade)
@@unique([calendarConnId, externalUid])
@@index([startAt, endAt])
}
model Appointment {
id String @id @default(cuid())
bookingGroupId String?
staffId String
customerFirstName String
customerLastName String
customerEmail String
customerPhone String?
notes String?
startAt DateTime
endAt DateTime
durationMinutes Int
status AppointmentStatus @default(CONFIRMED)
cancellationToken String
calendarEventUid String?
cancelledAt DateTime?
noShowAt DateTime?
reminder24hSentAt DateTime?
reminder2hSentAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
staff User @relation("StaffAppointments", fields: [staffId], references: [id], onDelete: Cascade)
@@index([staffId, startAt])
@@index([status])
@@index([customerEmail])
@@index([bookingGroupId])
@@index([cancellationToken])
}
model DeliveryIssue {
id String @id @default(cuid())
channel DeliveryChannel
operation String
target String
lastError String
attemptCount Int @default(1)
firstSeenAt DateTime @default(now())
lastSeenAt DateTime @default(now())
resolvedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([channel, operation, target, resolvedAt])
@@index([resolvedAt, lastSeenAt])
}
model Setting {
key String @id
value String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}