feat(01-01): add RankingSnapshot model + enums to schema.prisma
- Add RankingTriggerType enum (MANUAL, AUTO, RETROACTIVE, QUICK) - Add RankingMode enum (PREVIEW, CONFIRMED, QUICK) - Add RankingSnapshotStatus enum (PENDING, RUNNING, COMPLETED, FAILED) - Add RankingSnapshot model with roundId/triggeredById FKs, criteria/results JSON fields, AI metadata - Add Round.rankingSnapshots back-relation (RoundRankingSnapshots) - Add User.rankingSnapshots back-relation (TriggeredRankingSnapshots) - Create migration 20260227000000_add_ranking_snapshot - Regenerate Prisma client (prisma.rankingSnapshot accessible)
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "RankingTriggerType" AS ENUM ('MANUAL', 'AUTO', 'RETROACTIVE', 'QUICK');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "RankingMode" AS ENUM ('PREVIEW', 'CONFIRMED', 'QUICK');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "RankingSnapshotStatus" AS ENUM ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "RankingSnapshot" (
|
||||
"id" TEXT NOT NULL,
|
||||
"roundId" TEXT NOT NULL,
|
||||
"triggeredById" TEXT,
|
||||
"triggerType" "RankingTriggerType" NOT NULL DEFAULT 'MANUAL',
|
||||
"criteriaText" TEXT NOT NULL,
|
||||
"parsedRulesJson" JSONB NOT NULL,
|
||||
"startupRankingJson" JSONB,
|
||||
"conceptRankingJson" JSONB,
|
||||
"evaluationDataJson" JSONB,
|
||||
"mode" "RankingMode" NOT NULL DEFAULT 'PREVIEW',
|
||||
"status" "RankingSnapshotStatus" NOT NULL DEFAULT 'COMPLETED',
|
||||
"reordersJson" JSONB,
|
||||
"model" TEXT,
|
||||
"tokensUsed" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "RankingSnapshot_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RankingSnapshot_roundId_idx" ON "RankingSnapshot"("roundId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RankingSnapshot_triggeredById_idx" ON "RankingSnapshot"("triggeredById");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RankingSnapshot_createdAt_idx" ON "RankingSnapshot"("createdAt");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RankingSnapshot" ADD CONSTRAINT "RankingSnapshot_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RankingSnapshot" ADD CONSTRAINT "RankingSnapshot_triggeredById_fkey" FOREIGN KEY ("triggeredById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -425,6 +425,9 @@ model User {
|
||||
submissionPromotions SubmissionPromotionEvent[] @relation("SubmissionPromoter")
|
||||
deliberationReplacements DeliberationParticipant[] @relation("DeliberationReplacement")
|
||||
|
||||
// AI Ranking
|
||||
rankingSnapshots RankingSnapshot[] @relation("TriggeredRankingSnapshots")
|
||||
|
||||
@@index([role])
|
||||
@@index([status])
|
||||
}
|
||||
@@ -1405,6 +1408,74 @@ enum AssignmentJobStatus {
|
||||
FAILED
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// AI RANKING MODELS
|
||||
// =============================================================================
|
||||
|
||||
enum RankingTriggerType {
|
||||
MANUAL // Admin clicked "Run ranking"
|
||||
AUTO // Auto-triggered by assignment completion
|
||||
RETROACTIVE // Retroactive scan on deployment
|
||||
QUICK // Quick-rank mode (no preview)
|
||||
}
|
||||
|
||||
enum RankingMode {
|
||||
PREVIEW // Parsed rules shown to admin (not yet applied)
|
||||
CONFIRMED // Admin confirmed rules, ranking applied
|
||||
QUICK // Quick-rank: parse + apply without preview
|
||||
}
|
||||
|
||||
enum RankingSnapshotStatus {
|
||||
PENDING
|
||||
RUNNING
|
||||
COMPLETED
|
||||
FAILED
|
||||
}
|
||||
|
||||
// Captures a point-in-time AI ranking run for a round
|
||||
model RankingSnapshot {
|
||||
id String @id @default(cuid())
|
||||
|
||||
roundId String
|
||||
|
||||
// Trigger metadata
|
||||
triggeredById String? // null = auto-triggered
|
||||
triggerType RankingTriggerType @default(MANUAL)
|
||||
|
||||
// Criteria used
|
||||
criteriaText String @db.Text
|
||||
parsedRulesJson Json @db.JsonB
|
||||
|
||||
// Results per category (either can be null/empty if no projects in that category)
|
||||
startupRankingJson Json? @db.JsonB
|
||||
conceptRankingJson Json? @db.JsonB
|
||||
|
||||
// Evaluation data freeze (raw scores at time of ranking)
|
||||
evaluationDataJson Json? @db.JsonB
|
||||
|
||||
// Mode and status
|
||||
mode RankingMode @default(PREVIEW)
|
||||
status RankingSnapshotStatus @default(COMPLETED)
|
||||
|
||||
// Post-drag-and-drop reorders (Phase 2 will populate this)
|
||||
reordersJson Json? @db.JsonB
|
||||
|
||||
// AI metadata
|
||||
model String?
|
||||
tokensUsed Int @default(0)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
round Round @relation("RoundRankingSnapshots", fields: [roundId], references: [id], onDelete: Cascade)
|
||||
triggeredBy User? @relation("TriggeredRankingSnapshots", fields: [triggeredById], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([roundId])
|
||||
@@index([triggeredById])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
// Tracks progress of long-running AI tagging jobs
|
||||
model TaggingJob {
|
||||
id String @id @default(cuid())
|
||||
@@ -2146,6 +2217,7 @@ model Round {
|
||||
filteringResults FilteringResult[]
|
||||
filteringJobs FilteringJob[]
|
||||
assignmentJobs AssignmentJob[]
|
||||
rankingSnapshots RankingSnapshot[] @relation("RoundRankingSnapshots")
|
||||
reminderLogs ReminderLog[]
|
||||
evaluationSummaries EvaluationSummary[]
|
||||
evaluationDiscussions EvaluationDiscussion[]
|
||||
|
||||
Reference in New Issue
Block a user