feat(hotel): many hotels per edition + HotelStay (room assignment)

- Hotel.programId no longer unique (many hotels per edition)
- New HotelStay 1:1 with AttendingMember (hotelId, room, check-in/out)
- Program.hotel -> hotels[]

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt
2026-06-04 19:13:52 +02:00
parent 200b5e0cb9
commit 75e63eb47f
2 changed files with 58 additions and 3 deletions

View File

@@ -0,0 +1,33 @@
-- DropIndex
DROP INDEX "Hotel_programId_key";
-- CreateTable
CREATE TABLE "HotelStay" (
"id" TEXT NOT NULL,
"attendingMemberId" TEXT NOT NULL,
"hotelId" TEXT NOT NULL,
"roomNumber" TEXT,
"checkInAt" TIMESTAMP(3),
"checkOutAt" TIMESTAMP(3),
"notes" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "HotelStay_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "HotelStay_attendingMemberId_key" ON "HotelStay"("attendingMemberId");
-- CreateIndex
CREATE INDEX "HotelStay_hotelId_idx" ON "HotelStay"("hotelId");
-- CreateIndex
CREATE INDEX "Hotel_programId_idx" ON "Hotel"("programId");
-- AddForeignKey
ALTER TABLE "HotelStay" ADD CONSTRAINT "HotelStay_attendingMemberId_fkey" FOREIGN KEY ("attendingMemberId") REFERENCES "AttendingMember"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "HotelStay" ADD CONSTRAINT "HotelStay_hotelId_fkey" FOREIGN KEY ("hotelId") REFERENCES "Hotel"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@@ -506,7 +506,7 @@ model Program {
// Grand-finale logistics
finalistSlotQuotas FinalistSlotQuota[]
waitlistEntries WaitlistEntry[]
hotel Hotel?
hotels Hotel[]
lunchEvent LunchEvent?
@@unique([name, year])
@@ -2786,6 +2786,7 @@ model AttendingMember {
flightDetail FlightDetail?
visaApplication VisaApplication?
lunchPick MemberLunchPick?
hotelStay HotelStay?
@@unique([confirmationId, userId])
@@index([userId])
@@ -2802,7 +2803,7 @@ enum FlightDetailStatus {
model Hotel {
id String @id @default(cuid())
programId String @unique // 1:1 — one hotel per edition
programId String // many hotels per edition
name String
address String? @db.Text
link String? // external URL to hotel page / booking confirmation
@@ -2810,7 +2811,28 @@ model Hotel {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
program Program @relation(fields: [programId], references: [id], onDelete: Cascade)
program Program @relation(fields: [programId], references: [id], onDelete: Cascade)
stays HotelStay[]
@@index([programId])
}
/// Per-attendee hotel/room assignment (1:1 with AttendingMember, mirrors FlightDetail).
model HotelStay {
id String @id @default(cuid())
attendingMemberId String @unique
hotelId String
roomNumber String?
checkInAt DateTime?
checkOutAt DateTime?
notes String? @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
attendingMember AttendingMember @relation(fields: [attendingMemberId], references: [id], onDelete: Cascade)
hotel Hotel @relation(fields: [hotelId], references: [id], onDelete: Restrict)
@@index([hotelId])
}
model FlightDetail {