217 lines
5.6 KiB
Plaintext
217 lines
5.6 KiB
Plaintext
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
model Venue {
|
|
id String @id @default(uuid())
|
|
name String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
devices Device[]
|
|
clientUsers ClientUser[]
|
|
tabOwnerships TabOwnership[]
|
|
remoteCommands RemoteCommand[]
|
|
auditLogs AuditLog[]
|
|
regCodes RegistrationCode[]
|
|
plannedTabs PlannedTab[]
|
|
tabReminders TabReminder[]
|
|
tabEvents TabEvent[]
|
|
}
|
|
|
|
model Device {
|
|
id String @id @default(uuid())
|
|
venueId String @unique
|
|
name String
|
|
tokenHash String @unique
|
|
tokenPrefix String
|
|
tokenExpiresAt DateTime
|
|
lastSeenAt DateTime @default(now())
|
|
revokedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
tabSnapshots OpenTabSnapshot[]
|
|
tabOwnerships TabOwnership[]
|
|
remoteCommands RemoteCommand[]
|
|
tabEvents TabEvent[]
|
|
|
|
@@index([venueId, revokedAt])
|
|
}
|
|
|
|
model ClientUser {
|
|
id String @id @default(uuid())
|
|
venueId String
|
|
email String @unique
|
|
passwordHash String
|
|
name String
|
|
role String @default("viewer")
|
|
createdAt DateTime @default(now())
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
|
|
@@index([venueId])
|
|
}
|
|
|
|
model RegistrationCode {
|
|
id String @id @default(uuid())
|
|
venueId String
|
|
code String @unique
|
|
expiresAt DateTime
|
|
usedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
|
|
@@index([venueId])
|
|
}
|
|
|
|
model OpenTabSnapshot {
|
|
id String @id @default(uuid())
|
|
deviceId String
|
|
tabId String
|
|
customerName String
|
|
version Int
|
|
totalInCents Int
|
|
itemCount Int
|
|
// The tab's lines as reported by the terminal: [{ productName, quantity, unitPriceInCents }].
|
|
// Null for terminals running an app version that doesn't report them.
|
|
items Json?
|
|
reportedAt DateTime
|
|
|
|
device Device @relation(fields: [deviceId], references: [id])
|
|
|
|
@@unique([deviceId, tabId])
|
|
@@index([deviceId])
|
|
@@index([tabId, reportedAt])
|
|
}
|
|
|
|
model TabOwnership {
|
|
tabId String
|
|
venueId String
|
|
deviceId String
|
|
lastReportedAt DateTime
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
device Device @relation(fields: [deviceId], references: [id])
|
|
|
|
@@id([venueId, tabId])
|
|
}
|
|
|
|
model RemoteCommand {
|
|
id String @id @default(uuid())
|
|
venueId String
|
|
deviceId String
|
|
targetTabId String
|
|
customerName String?
|
|
amountInCents Int?
|
|
type String @default("close_tab")
|
|
expectedVersion Int
|
|
paymentMethod String
|
|
requestedBy String
|
|
status String @default("pending")
|
|
result String?
|
|
acknowledgedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
expiresAt DateTime
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
device Device @relation(fields: [deviceId], references: [id])
|
|
|
|
@@index([deviceId, status, createdAt])
|
|
@@index([venueId, status, createdAt])
|
|
}
|
|
|
|
model AuditLog {
|
|
id String @id @default(uuid())
|
|
venueId String
|
|
actorType String
|
|
actorId String
|
|
action String
|
|
details String?
|
|
createdAt DateTime @default(now())
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
|
|
@@index([venueId, createdAt])
|
|
}
|
|
|
|
model RefreshToken {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
tokenHash String @unique
|
|
expiresAt DateTime
|
|
revokedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([userId])
|
|
}
|
|
|
|
model PlannedTab {
|
|
id String @id @default(uuid())
|
|
venueId String
|
|
customerName String
|
|
// Lowercased, whitespace-collapsed name: customers are matched on this everywhere
|
|
customerNameKey String
|
|
email String?
|
|
position Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
// Set once the terminal reports an open tab with this name; it is then no longer sent to devices
|
|
deliveredAt DateTime?
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
|
|
@@unique([venueId, customerNameKey])
|
|
@@index([venueId])
|
|
}
|
|
|
|
model TabReminder {
|
|
id String @id @default(uuid())
|
|
venueId String
|
|
tabId String
|
|
customerName String
|
|
email String
|
|
amountInCents Int
|
|
sentAt DateTime @default(now())
|
|
status String @default("sent")
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
|
|
@@index([venueId, sentAt])
|
|
@@index([venueId, tabId])
|
|
}
|
|
|
|
// What happened on a tab, as reported by the terminal: lines added or removed, and settlements.
|
|
// The id is generated by the terminal so a re-sent event is stored only once.
|
|
model TabEvent {
|
|
id String @id
|
|
venueId String
|
|
deviceId String
|
|
tabId String
|
|
customerName String
|
|
// line_added | line_removed | settled
|
|
type String
|
|
productName String?
|
|
unitPriceInCents Int?
|
|
// Signed: positive for line_added, negative for line_removed
|
|
quantityDelta Int?
|
|
// settled only
|
|
amountInCents Int?
|
|
paymentMethod String?
|
|
commandId String?
|
|
items Json?
|
|
occurredAt DateTime
|
|
receivedAt DateTime @default(now())
|
|
|
|
venue Venue @relation(fields: [venueId], references: [id])
|
|
device Device @relation(fields: [deviceId], references: [id])
|
|
|
|
@@index([venueId, occurredAt])
|
|
@@index([venueId, type, occurredAt])
|
|
}
|