feat: schema for finalist confirmation flow + per-category quotas
Adds 4 new models for grand-finale logistics PR 1: - FinalistSlotQuota: per-category mutable quotas - WaitlistEntry: ranked per-category waitlist - FinalistConfirmation: token-gated confirmation lifecycle (PENDING / CONFIRMED / DECLINED / EXPIRED / SUPERSEDED) with optional decline reason - AttendingMember: who from each team is attending, with visa flag Plus Program.defaultAttendeeCap (default 3) for the per-edition team attendance cap. Migration is purely additive: no DROP/ALTER COLUMN/RENAME on existing schema. All FKs ON DELETE CASCADE only fire on parent deletion.
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "WaitlistEntryStatus" AS ENUM ('WAITING', 'PROMOTED', 'USED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "FinalistConfirmationStatus" AS ENUM ('PENDING', 'CONFIRMED', 'DECLINED', 'EXPIRED', 'SUPERSEDED');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Program" ADD COLUMN "defaultAttendeeCap" INTEGER NOT NULL DEFAULT 3;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "FinalistSlotQuota" (
|
||||
"id" TEXT NOT NULL,
|
||||
"programId" TEXT NOT NULL,
|
||||
"category" "CompetitionCategory" NOT NULL,
|
||||
"quota" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "FinalistSlotQuota_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "WaitlistEntry" (
|
||||
"id" TEXT NOT NULL,
|
||||
"programId" TEXT NOT NULL,
|
||||
"projectId" TEXT NOT NULL,
|
||||
"category" "CompetitionCategory" NOT NULL,
|
||||
"rank" INTEGER NOT NULL,
|
||||
"status" "WaitlistEntryStatus" NOT NULL DEFAULT 'WAITING',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "WaitlistEntry_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "FinalistConfirmation" (
|
||||
"id" TEXT NOT NULL,
|
||||
"projectId" TEXT NOT NULL,
|
||||
"category" "CompetitionCategory" NOT NULL,
|
||||
"status" "FinalistConfirmationStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"deadline" TIMESTAMP(3) NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"confirmedAt" TIMESTAMP(3),
|
||||
"declinedAt" TIMESTAMP(3),
|
||||
"declineReason" TEXT,
|
||||
"expiredAt" TIMESTAMP(3),
|
||||
"promotedFromWaitlistEntryId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "FinalistConfirmation_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AttendingMember" (
|
||||
"id" TEXT NOT NULL,
|
||||
"confirmationId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"needsVisa" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "AttendingMember_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "FinalistSlotQuota_programId_idx" ON "FinalistSlotQuota"("programId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "FinalistSlotQuota_programId_category_key" ON "FinalistSlotQuota"("programId", "category");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "WaitlistEntry_projectId_key" ON "WaitlistEntry"("projectId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "WaitlistEntry_programId_category_status_idx" ON "WaitlistEntry"("programId", "category", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "WaitlistEntry_programId_category_rank_key" ON "WaitlistEntry"("programId", "category", "rank");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "FinalistConfirmation_projectId_key" ON "FinalistConfirmation"("projectId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "FinalistConfirmation_token_key" ON "FinalistConfirmation"("token");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "FinalistConfirmation_promotedFromWaitlistEntryId_key" ON "FinalistConfirmation"("promotedFromWaitlistEntryId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "FinalistConfirmation_status_deadline_idx" ON "FinalistConfirmation"("status", "deadline");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "FinalistConfirmation_category_status_idx" ON "FinalistConfirmation"("category", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AttendingMember_userId_idx" ON "AttendingMember"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "AttendingMember_confirmationId_userId_key" ON "AttendingMember"("confirmationId", "userId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FinalistSlotQuota" ADD CONSTRAINT "FinalistSlotQuota_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "WaitlistEntry" ADD CONSTRAINT "WaitlistEntry_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "WaitlistEntry" ADD CONSTRAINT "WaitlistEntry_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FinalistConfirmation" ADD CONSTRAINT "FinalistConfirmation_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "AttendingMember" ADD CONSTRAINT "AttendingMember_confirmationId_fkey" FOREIGN KEY ("confirmationId") REFERENCES "FinalistConfirmation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "AttendingMember" ADD CONSTRAINT "AttendingMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
Reference in New Issue
Block a user