diff --git a/server/prisma/migrations/20260427122603_add_level_up_sessions_and_class_progression/migration.sql b/server/prisma/migrations/20260427122603_add_level_up_sessions_and_class_progression/migration.sql new file mode 100644 index 0000000..adc52c4 --- /dev/null +++ b/server/prisma/migrations/20260427122603_add_level_up_sessions_and_class_progression/migration.sql @@ -0,0 +1,90 @@ +-- AlterTable +ALTER TABLE "Character" ADD COLUMN "freeArchetype" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "prereqViolations" JSONB; + +-- CreateTable +CREATE TABLE "LevelUpSession" ( + "id" TEXT NOT NULL, + "characterId" TEXT NOT NULL, + "targetLevel" INTEGER NOT NULL, + "state" JSONB NOT NULL DEFAULT '{}', + "committedAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "LevelUpSession_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "LevelUpHistory" ( + "id" TEXT NOT NULL, + "characterId" TEXT NOT NULL, + "levelFrom" INTEGER NOT NULL, + "levelTo" INTEGER NOT NULL, + "snapshotBefore" JSONB NOT NULL, + "choices" JSONB NOT NULL, + "committedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "LevelUpHistory_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ClassProgression" ( + "id" TEXT NOT NULL, + "className" TEXT NOT NULL, + "level" INTEGER NOT NULL, + "grants" TEXT[], + "proficiencyChanges" JSONB NOT NULL, + "spellSlotIncrement" JSONB, + "cantripIncrement" INTEGER, + "repertoireIncrement" INTEGER, + "choiceType" TEXT, + "choiceOptionsRef" TEXT, + + CONSTRAINT "ClassProgression_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ClassFeatureOption" ( + "id" TEXT NOT NULL, + "optionsRef" TEXT NOT NULL, + "optionKey" TEXT NOT NULL, + "name" TEXT NOT NULL, + "nameGerman" TEXT, + "description" TEXT NOT NULL, + "grants" TEXT[], + "proficiencyChanges" JSONB, + + CONSTRAINT "ClassFeatureOption_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "LevelUpSession_characterId_idx" ON "LevelUpSession"("characterId"); + +-- CreateIndex +CREATE INDEX "LevelUpHistory_characterId_committedAt_idx" ON "LevelUpHistory"("characterId", "committedAt" DESC); + +-- CreateIndex +CREATE INDEX "ClassProgression_className_idx" ON "ClassProgression"("className"); + +-- CreateIndex +CREATE UNIQUE INDEX "ClassProgression_className_level_key" ON "ClassProgression"("className", "level"); + +-- CreateIndex +CREATE INDEX "ClassFeatureOption_optionsRef_idx" ON "ClassFeatureOption"("optionsRef"); + +-- CreateIndex +CREATE UNIQUE INDEX "ClassFeatureOption_optionsRef_optionKey_key" ON "ClassFeatureOption"("optionsRef", "optionKey"); + +-- AddForeignKey +ALTER TABLE "LevelUpSession" ADD CONSTRAINT "LevelUpSession_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "Character"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LevelUpHistory" ADD CONSTRAINT "LevelUpHistory_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "Character"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- Partial unique index: enforce at most one open DRAFT per character. +-- Prisma 7 cannot express partial indexes via @@unique; this raw SQL is required. +-- See: .planning/phases/01-level-up-pf2e-regelkonform/01-RESEARCH.md §Don't Hand-Roll. +CREATE UNIQUE INDEX "LevelUpSession_characterId_open_unique" + ON "LevelUpSession"("characterId") + WHERE "committedAt" IS NULL;