Forums-Anträge erfassen und von Hand entscheiden

Der GExtension-Abgleich liefert die Käufe, der Verbrauch steht im Forum. Die
App liest jetzt die drei CC-Boards und sammelt die Anträge.

Gelesen wird nur die Board-Übersicht: sie führt bereits den Ersteller, nicht
nur den letzten Antwortenden. Damit bleibt ein Lauf bei wenigen Anfragen statt
einer je Thread. Unterforen und globale Kästen tragen ebenfalls Thread-Links,
deshalb liest der Parser strikt entlang der Listeneinträge - sonst landen
Changelogs und Bewerbungen in der Antragsliste.

Klassifiziert wird ausschließlich von Hand. Weder Titel noch Board sind
verlässlich genug: Threads werden nicht immer verschoben, ein genehmigter
Antrag kann weiter im Antrags-Board liegen. Das Board steht deshalb nur als
Hinweis an der Zeile.

Angenommene Anträge rufen dieselben Aktionen wie die Knöpfe auf der
Spielerseite, es gibt keinen zweiten Buchungsweg mit eigenen Regeln. Wandert
ein bereits entschiedener Thread später in ein anderes Board, erscheint das
als Hinweis zum Abhaken - der CC-Status ändert sich nie von allein.

Die Thread-ID bleibt beim Verschieben stabil und traegt deshalb die
Wiedererkennung; die Board-Historie wird mitgeschrieben. Zurückgelassene
Verweise erkennt der Parser und zählt sie nicht als eigenen Antrag.
This commit is contained in:
2026-09-18 17:32:58 +02:00
parent 6b49b34eef
commit 664a0fd5ee
17 changed files with 1291 additions and 4 deletions
@@ -19,6 +19,12 @@ CREATE TYPE "InactiveReason" AS ENUM ('PLAYER_INACTIVITY', 'REWORKED', 'OTHER');
-- CreateEnum
CREATE TYPE "ProductTarget" AS ENUM ('CC_PACKAGE', 'REDESIGN_PACKAGE', 'IGNORE');
-- CreateEnum
CREATE TYPE "ForumBoard" AS ENUM ('CUSTOM_CHARACTERS', 'AKTIVE_CCS', 'CC_ARCHIV');
-- CreateEnum
CREATE TYPE "ForumClassification" AS ENUM ('NEW_CC', 'REDESIGN', 'REJECTED', 'IGNORE');
-- CreateEnum
CREATE TYPE "ImportStatus" AS ENUM ('PENDING', 'COMMITTED', 'DISCARDED');
@@ -198,6 +204,38 @@ CREATE TABLE "AuditLog" (
CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ForumThread" (
"threadId" INTEGER NOT NULL,
"title" TEXT NOT NULL,
"url" TEXT NOT NULL,
"authorName" TEXT,
"authorForumId" INTEGER,
"playerId" INTEGER,
"currentBoard" "ForumBoard" NOT NULL,
"firstSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"lastSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"lastBoardChangeAt" TIMESTAMP(3),
"classification" "ForumClassification",
"needsClassification" BOOLEAN NOT NULL DEFAULT true,
"classifiedById" INTEGER,
"classifiedAt" TIMESTAMP(3),
"linkedCharacterId" INTEGER,
"boardChangeNotice" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "ForumThread_pkey" PRIMARY KEY ("threadId")
);
-- CreateTable
CREATE TABLE "ForumThreadBoard" (
"id" SERIAL NOT NULL,
"threadId" INTEGER NOT NULL,
"board" "ForumBoard" NOT NULL,
"observedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "ForumThreadBoard_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
@@ -273,6 +311,18 @@ CREATE INDEX "AuditLog_targetType_targetId_idx" ON "AuditLog"("targetType", "tar
-- CreateIndex
CREATE INDEX "AuditLog_actorUserId_idx" ON "AuditLog"("actorUserId");
-- CreateIndex
CREATE INDEX "ForumThread_needsClassification_idx" ON "ForumThread"("needsClassification");
-- CreateIndex
CREATE INDEX "ForumThread_playerId_idx" ON "ForumThread"("playerId");
-- CreateIndex
CREATE INDEX "ForumThread_currentBoard_idx" ON "ForumThread"("currentBoard");
-- CreateIndex
CREATE INDEX "ForumThreadBoard_threadId_idx" ON "ForumThreadBoard"("threadId");
-- AddForeignKey
ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -318,3 +368,12 @@ ALTER TABLE "ImportedOrder" ADD CONSTRAINT "ImportedOrder_playerId_fkey" FOREIGN
-- AddForeignKey
ALTER TABLE "AuditLog" ADD CONSTRAINT "AuditLog_actorUserId_fkey" FOREIGN KEY ("actorUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ForumThread" ADD CONSTRAINT "ForumThread_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ForumThread" ADD CONSTRAINT "ForumThread_linkedCharacterId_fkey" FOREIGN KEY ("linkedCharacterId") REFERENCES "Character"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ForumThreadBoard" ADD CONSTRAINT "ForumThreadBoard_threadId_fkey" FOREIGN KEY ("threadId") REFERENCES "ForumThread"("threadId") ON DELETE CASCADE ON UPDATE CASCADE;