Guthaben werden als Kontobuch gefuehrt: jede Bewegung ist eine Zeile, der Stand eines Topfes ist deren Summe. Zusammengehoerige Zeilen teilen sich eine groupId, damit ein CC-Paket als Ganzes storniert werden kann; ein unique Constraint auf reversalOfId verhindert doppelte Stornos. CCs bilden ueber lineageId und predecessorId eine Redesign-Kette. Der Grund einer Deaktivierung entscheidet spaeter ueber die Reaktivierungskosten.
287 lines
9.1 KiB
SQL
287 lines
9.1 KiB
SQL
-- CreateSchema
|
|
CREATE SCHEMA IF NOT EXISTS "public";
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "Role" AS ENUM ('ADMIN', 'EDITOR', 'VIEWER');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "CreditKind" AS ENUM ('CC', 'REDESIGN_PAID', 'REDESIGN_KULANZ');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "CreditSource" AS ENUM ('CC_PACKAGE', 'REDESIGN_PACKAGE', 'KULANZ', 'ADJUSTMENT', 'CONSUME', 'REVERSAL');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "CharacterStatus" AS ENUM ('ACTIVE', 'INACTIVE');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "InactiveReason" AS ENUM ('PLAYER_INACTIVITY', 'REWORKED', 'OTHER');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "ProductTarget" AS ENUM ('CC_PACKAGE', 'REDESIGN_PACKAGE', 'IGNORE');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "ImportStatus" AS ENUM ('PENDING', 'COMMITTED', 'DISCARDED');
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "User" (
|
|
"id" SERIAL NOT NULL,
|
|
"username" TEXT NOT NULL,
|
|
"passwordHash" TEXT NOT NULL,
|
|
"role" "Role" NOT NULL DEFAULT 'EDITOR',
|
|
"totpSecret" TEXT,
|
|
"totpEnabled" BOOLEAN NOT NULL DEFAULT false,
|
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
|
"mustChangePassword" BOOLEAN NOT NULL DEFAULT false,
|
|
"lastLoginAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Session" (
|
|
"id" TEXT NOT NULL,
|
|
"tokenHash" TEXT NOT NULL,
|
|
"userId" INTEGER NOT NULL,
|
|
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"lastSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"ip" TEXT,
|
|
"userAgent" TEXT,
|
|
|
|
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Player" (
|
|
"id" SERIAL NOT NULL,
|
|
"displayName" TEXT NOT NULL,
|
|
"steamId" TEXT,
|
|
"forumName" TEXT,
|
|
"notes" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Player_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "CreditLedger" (
|
|
"id" SERIAL NOT NULL,
|
|
"playerId" INTEGER NOT NULL,
|
|
"kind" "CreditKind" NOT NULL,
|
|
"amount" INTEGER NOT NULL,
|
|
"source" "CreditSource" NOT NULL,
|
|
"groupId" TEXT NOT NULL,
|
|
"characterId" INTEGER,
|
|
"importId" INTEGER,
|
|
"note" TEXT,
|
|
"reversalOfId" INTEGER,
|
|
"createdById" INTEGER,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "CreditLedger_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Character" (
|
|
"id" SERIAL NOT NULL,
|
|
"playerId" INTEGER NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"loreText" TEXT,
|
|
"status" "CharacterStatus" NOT NULL DEFAULT 'ACTIVE',
|
|
"inactiveReason" "InactiveReason",
|
|
"lineageId" TEXT NOT NULL,
|
|
"predecessorId" INTEGER,
|
|
"createdById" INTEGER,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Character_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Import" (
|
|
"id" SERIAL NOT NULL,
|
|
"filename" TEXT NOT NULL,
|
|
"status" "ImportStatus" NOT NULL DEFAULT 'PENDING',
|
|
"rowCount" INTEGER NOT NULL DEFAULT 0,
|
|
"bookedCount" INTEGER NOT NULL DEFAULT 0,
|
|
"mapping" JSONB,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"committedAt" TIMESTAMP(3),
|
|
"importedById" INTEGER,
|
|
|
|
CONSTRAINT "Import_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "ImportRow" (
|
|
"id" SERIAL NOT NULL,
|
|
"importId" INTEGER NOT NULL,
|
|
"lineNo" INTEGER NOT NULL,
|
|
"externalId" TEXT,
|
|
"playerKey" TEXT,
|
|
"playerName" TEXT,
|
|
"productName" TEXT,
|
|
"purchasedAt" TIMESTAMP(3),
|
|
"target" "ProductTarget",
|
|
"resolvedPlayerId" INTEGER,
|
|
"plan" TEXT NOT NULL,
|
|
"raw" JSONB NOT NULL,
|
|
|
|
CONSTRAINT "ImportRow_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "ImportedOrder" (
|
|
"id" SERIAL NOT NULL,
|
|
"externalId" TEXT NOT NULL,
|
|
"importId" INTEGER NOT NULL,
|
|
"playerId" INTEGER NOT NULL,
|
|
"target" "ProductTarget" NOT NULL,
|
|
"groupId" TEXT NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "ImportedOrder_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "ProductMapping" (
|
|
"id" SERIAL NOT NULL,
|
|
"matchPattern" TEXT NOT NULL,
|
|
"target" "ProductTarget" NOT NULL,
|
|
"priority" INTEGER NOT NULL DEFAULT 100,
|
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
|
"note" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "ProductMapping_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "AuditLog" (
|
|
"id" SERIAL NOT NULL,
|
|
"actorUserId" INTEGER,
|
|
"actorName" TEXT,
|
|
"action" TEXT NOT NULL,
|
|
"targetType" TEXT NOT NULL,
|
|
"targetId" TEXT,
|
|
"details" JSONB,
|
|
"ip" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Session_tokenHash_key" ON "Session"("tokenHash");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Session_userId_idx" ON "Session"("userId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Session_expiresAt_idx" ON "Session"("expiresAt");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Player_steamId_key" ON "Player"("steamId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Player_displayName_idx" ON "Player"("displayName");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "CreditLedger_reversalOfId_key" ON "CreditLedger"("reversalOfId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "CreditLedger_playerId_idx" ON "CreditLedger"("playerId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "CreditLedger_playerId_kind_idx" ON "CreditLedger"("playerId", "kind");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "CreditLedger_groupId_idx" ON "CreditLedger"("groupId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "CreditLedger_createdAt_idx" ON "CreditLedger"("createdAt");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Character_playerId_idx" ON "Character"("playerId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Character_playerId_status_idx" ON "Character"("playerId", "status");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Character_lineageId_idx" ON "Character"("lineageId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Import_status_idx" ON "Import"("status");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "ImportRow_importId_idx" ON "ImportRow"("importId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "ImportedOrder_externalId_key" ON "ImportedOrder"("externalId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "ImportedOrder_playerId_idx" ON "ImportedOrder"("playerId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "ProductMapping_priority_idx" ON "ProductMapping"("priority");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AuditLog_createdAt_idx" ON "AuditLog"("createdAt");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AuditLog_targetType_targetId_idx" ON "AuditLog"("targetType", "targetId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AuditLog_actorUserId_idx" ON "AuditLog"("actorUserId");
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "CreditLedger" ADD CONSTRAINT "CreditLedger_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "CreditLedger" ADD CONSTRAINT "CreditLedger_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "Character"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "CreditLedger" ADD CONSTRAINT "CreditLedger_importId_fkey" FOREIGN KEY ("importId") REFERENCES "Import"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "CreditLedger" ADD CONSTRAINT "CreditLedger_reversalOfId_fkey" FOREIGN KEY ("reversalOfId") REFERENCES "CreditLedger"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "CreditLedger" ADD CONSTRAINT "CreditLedger_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Character" ADD CONSTRAINT "Character_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Character" ADD CONSTRAINT "Character_predecessorId_fkey" FOREIGN KEY ("predecessorId") REFERENCES "Character"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Character" ADD CONSTRAINT "Character_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Import" ADD CONSTRAINT "Import_importedById_fkey" FOREIGN KEY ("importedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "ImportRow" ADD CONSTRAINT "ImportRow_importId_fkey" FOREIGN KEY ("importId") REFERENCES "Import"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "ImportedOrder" ADD CONSTRAINT "ImportedOrder_importId_fkey" FOREIGN KEY ("importId") REFERENCES "Import"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "ImportedOrder" ADD CONSTRAINT "ImportedOrder_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "AuditLog" ADD CONSTRAINT "AuditLog_actorUserId_fkey" FOREIGN KEY ("actorUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|