Add schedule data model and migration

This commit is contained in:
NeilClack
2026-09-11 18:15:57 -05:00
parent 960673bbc6
commit e6b492a335
13 changed files with 5228 additions and 8 deletions
+48 -1
View File
@@ -28,6 +28,7 @@ model User {
profiles Profile[]
licenseKeys LicenseKey[]
userProclamations UserProclamations[]
schedule Schedule?
@@unique([email])
@@map("user")
@@ -130,6 +131,7 @@ model Proclamation {
groupId Int
group ProclamationGroup @relation(fields: [groupId], references: [id])
userProclamations UserProclamations[]
blockProclamations BlockProclamations[]
// Legacy subscription-level FK. Retained in the database but unmanaged; the
// FK constraint is dropped and the value is left NULL. Hidden from the client.
subscriptionLevelId Int? @ignore
@@ -186,7 +188,7 @@ model ProclamationCategoryLegacy {
// `@@ignore` so Prisma remains aware of the table but it is excluded from the
// generated client and Prisma's own migrations.
model ProclamationCategorySubscriptionLevelLegacy {
categoryId Int
categoryId Int
subscriptionLevelId Int
@@id([categoryId, subscriptionLevelId])
@@ -253,3 +255,48 @@ model AuditLog {
@@index([page])
@@map("AuditLog")
}
// A user's daily listening schedule. Exactly one per user (enforced by the
// unique userId); contains 0-4 time Blocks. Times are wall-clock minutes from
// midnight (0-1440), interpreted by the kiosk in the user's configured
// timezone. The portal never stores a timezone.
model Schedule {
id String @id @default(uuid())
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
blocks Block[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// A single non-overlapping time range within a Schedule, plus the ordered set
// of selected Proclamations to play during it. Overnight ranges are disallowed
// in v1, so startMinutes is always less than endMinutes.
model Block {
id String @id @default(uuid())
scheduleId String
schedule Schedule @relation(fields: [scheduleId], references: [id], onDelete: Cascade)
startMinutes Int
endMinutes Int
proclamations BlockProclamations[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([scheduleId])
}
// Join table: the Proclamations selected for a Block. Carries the Proclamation
// content for playback via the API; the portal UI only ever reads
// title/category/group.
model BlockProclamations {
blockId String
block Block @relation(fields: [blockId], references: [id], onDelete: Cascade)
proclamationId String
proclamation Proclamation @relation(fields: [proclamationId], references: [id])
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@id([blockId, proclamationId])
@@index([proclamationId])
}