Add migration for pipeline/stage system, new enums, and Round retirement
Build and Push Docker Image / build (push) Successful in 12m7s Details

The Round system redesign commit added Pipeline, Track, Stage models
and converted roundId to legacy fields but was missing the SQL migration.
This caused seed failure (AWARD_MASTER enum not found in DB).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt 2026-02-13 16:19:56 +01:00
parent 331b67dae0
commit 68d3dde1aa
1 changed files with 445 additions and 0 deletions

View File

@ -0,0 +1,445 @@
-- =============================================================================
-- Migration: Pipeline & Stage System + Legacy roundId → stageId transition
-- =============================================================================
-- =====================================================
-- 1. NEW ENUM TYPES
-- =====================================================
CREATE TYPE "StageType" AS ENUM ('INTAKE', 'FILTER', 'EVALUATION', 'SELECTION', 'LIVE_FINAL', 'RESULTS');
CREATE TYPE "TrackKind" AS ENUM ('MAIN', 'AWARD', 'SHOWCASE');
CREATE TYPE "RoutingMode" AS ENUM ('PARALLEL', 'EXCLUSIVE', 'POST_MAIN');
CREATE TYPE "StageStatus" AS ENUM ('STAGE_DRAFT', 'STAGE_ACTIVE', 'STAGE_CLOSED', 'STAGE_ARCHIVED');
CREATE TYPE "ProjectStageStateValue" AS ENUM ('PENDING', 'IN_PROGRESS', 'PASSED', 'REJECTED', 'ROUTED', 'COMPLETED', 'WITHDRAWN');
CREATE TYPE "DecisionMode" AS ENUM ('JURY_VOTE', 'AWARD_MASTER_DECISION', 'ADMIN_DECISION');
CREATE TYPE "OverrideReasonCode" AS ENUM ('DATA_CORRECTION', 'POLICY_EXCEPTION', 'JURY_CONFLICT', 'SPONSOR_DECISION', 'ADMIN_DISCRETION');
-- Add new values to existing UserRole enum
ALTER TYPE "UserRole" ADD VALUE 'AWARD_MASTER';
ALTER TYPE "UserRole" ADD VALUE 'AUDIENCE';
-- =====================================================
-- 2. NEW TABLES: Pipeline infrastructure
-- =====================================================
-- Pipeline
CREATE TABLE "Pipeline" (
"id" TEXT NOT NULL,
"programId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"slug" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'DRAFT',
"settingsJson" JSONB,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Pipeline_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "Pipeline_slug_key" ON "Pipeline"("slug");
CREATE INDEX "Pipeline_programId_idx" ON "Pipeline"("programId");
CREATE INDEX "Pipeline_status_idx" ON "Pipeline"("status");
-- Track
CREATE TABLE "Track" (
"id" TEXT NOT NULL,
"pipelineId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"slug" TEXT NOT NULL,
"kind" "TrackKind" NOT NULL DEFAULT 'MAIN',
"routingMode" "RoutingMode",
"decisionMode" "DecisionMode",
"sortOrder" INTEGER NOT NULL DEFAULT 0,
"settingsJson" JSONB,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Track_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "Track_pipelineId_slug_key" ON "Track"("pipelineId", "slug");
CREATE UNIQUE INDEX "Track_pipelineId_sortOrder_key" ON "Track"("pipelineId", "sortOrder");
CREATE INDEX "Track_pipelineId_idx" ON "Track"("pipelineId");
CREATE INDEX "Track_kind_idx" ON "Track"("kind");
-- Stage
CREATE TABLE "Stage" (
"id" TEXT NOT NULL,
"trackId" TEXT NOT NULL,
"stageType" "StageType" NOT NULL,
"name" TEXT NOT NULL,
"slug" TEXT NOT NULL,
"status" "StageStatus" NOT NULL DEFAULT 'STAGE_DRAFT',
"sortOrder" INTEGER NOT NULL DEFAULT 0,
"configJson" JSONB,
"windowOpenAt" TIMESTAMP(3),
"windowCloseAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Stage_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "Stage_trackId_slug_key" ON "Stage"("trackId", "slug");
CREATE UNIQUE INDEX "Stage_trackId_sortOrder_key" ON "Stage"("trackId", "sortOrder");
CREATE INDEX "Stage_trackId_idx" ON "Stage"("trackId");
CREATE INDEX "Stage_stageType_idx" ON "Stage"("stageType");
CREATE INDEX "Stage_status_idx" ON "Stage"("status");
-- StageTransition
CREATE TABLE "StageTransition" (
"id" TEXT NOT NULL,
"fromStageId" TEXT NOT NULL,
"toStageId" TEXT NOT NULL,
"isDefault" BOOLEAN NOT NULL DEFAULT false,
"guardJson" JSONB,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "StageTransition_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "StageTransition_fromStageId_toStageId_key" ON "StageTransition"("fromStageId", "toStageId");
CREATE INDEX "StageTransition_fromStageId_idx" ON "StageTransition"("fromStageId");
CREATE INDEX "StageTransition_toStageId_idx" ON "StageTransition"("toStageId");
-- ProjectStageState
CREATE TABLE "ProjectStageState" (
"id" TEXT NOT NULL,
"projectId" TEXT NOT NULL,
"trackId" TEXT NOT NULL,
"stageId" TEXT NOT NULL,
"state" "ProjectStageStateValue" NOT NULL DEFAULT 'PENDING',
"enteredAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"exitedAt" TIMESTAMP(3),
"metadataJson" JSONB,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "ProjectStageState_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "ProjectStageState_projectId_trackId_stageId_key" ON "ProjectStageState"("projectId", "trackId", "stageId");
CREATE INDEX "ProjectStageState_projectId_idx" ON "ProjectStageState"("projectId");
CREATE INDEX "ProjectStageState_trackId_idx" ON "ProjectStageState"("trackId");
CREATE INDEX "ProjectStageState_stageId_idx" ON "ProjectStageState"("stageId");
CREATE INDEX "ProjectStageState_state_idx" ON "ProjectStageState"("state");
CREATE INDEX "ProjectStageState_projectId_trackId_idx" ON "ProjectStageState"("projectId", "trackId");
-- RoutingRule
CREATE TABLE "RoutingRule" (
"id" TEXT NOT NULL,
"pipelineId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"scope" TEXT NOT NULL DEFAULT 'global',
"sourceTrackId" TEXT,
"destinationTrackId" TEXT NOT NULL,
"destinationStageId" TEXT,
"predicateJson" JSONB NOT NULL,
"priority" INTEGER NOT NULL DEFAULT 0,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "RoutingRule_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "RoutingRule_pipelineId_idx" ON "RoutingRule"("pipelineId");
CREATE INDEX "RoutingRule_priority_idx" ON "RoutingRule"("priority");
CREATE INDEX "RoutingRule_isActive_idx" ON "RoutingRule"("isActive");
-- Cohort
CREATE TABLE "Cohort" (
"id" TEXT NOT NULL,
"stageId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"votingMode" TEXT NOT NULL DEFAULT 'simple',
"isOpen" BOOLEAN NOT NULL DEFAULT false,
"windowOpenAt" TIMESTAMP(3),
"windowCloseAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Cohort_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "Cohort_stageId_idx" ON "Cohort"("stageId");
CREATE INDEX "Cohort_isOpen_idx" ON "Cohort"("isOpen");
-- CohortProject
CREATE TABLE "CohortProject" (
"id" TEXT NOT NULL,
"cohortId" TEXT NOT NULL,
"projectId" TEXT NOT NULL,
"sortOrder" INTEGER NOT NULL DEFAULT 0,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "CohortProject_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "CohortProject_cohortId_projectId_key" ON "CohortProject"("cohortId", "projectId");
CREATE INDEX "CohortProject_cohortId_idx" ON "CohortProject"("cohortId");
CREATE INDEX "CohortProject_projectId_idx" ON "CohortProject"("projectId");
CREATE INDEX "CohortProject_sortOrder_idx" ON "CohortProject"("sortOrder");
-- LiveProgressCursor
CREATE TABLE "LiveProgressCursor" (
"id" TEXT NOT NULL,
"stageId" TEXT NOT NULL,
"sessionId" TEXT NOT NULL,
"activeProjectId" TEXT,
"activeOrderIndex" INTEGER NOT NULL DEFAULT 0,
"isPaused" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "LiveProgressCursor_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "LiveProgressCursor_stageId_key" ON "LiveProgressCursor"("stageId");
CREATE UNIQUE INDEX "LiveProgressCursor_sessionId_key" ON "LiveProgressCursor"("sessionId");
CREATE INDEX "LiveProgressCursor_sessionId_idx" ON "LiveProgressCursor"("sessionId");
-- OverrideAction
CREATE TABLE "OverrideAction" (
"id" TEXT NOT NULL,
"entityType" TEXT NOT NULL,
"entityId" TEXT NOT NULL,
"previousValue" JSONB,
"newValueJson" JSONB NOT NULL,
"reasonCode" "OverrideReasonCode" NOT NULL,
"reasonText" TEXT,
"actorId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "OverrideAction_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "OverrideAction_entityType_entityId_idx" ON "OverrideAction"("entityType", "entityId");
CREATE INDEX "OverrideAction_actorId_idx" ON "OverrideAction"("actorId");
CREATE INDEX "OverrideAction_reasonCode_idx" ON "OverrideAction"("reasonCode");
CREATE INDEX "OverrideAction_createdAt_idx" ON "OverrideAction"("createdAt");
-- DecisionAuditLog
CREATE TABLE "DecisionAuditLog" (
"id" TEXT NOT NULL,
"eventType" TEXT NOT NULL,
"entityType" TEXT NOT NULL,
"entityId" TEXT NOT NULL,
"actorId" TEXT,
"detailsJson" JSONB,
"snapshotJson" JSONB,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "DecisionAuditLog_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "DecisionAuditLog_eventType_idx" ON "DecisionAuditLog"("eventType");
CREATE INDEX "DecisionAuditLog_entityType_entityId_idx" ON "DecisionAuditLog"("entityType", "entityId");
CREATE INDEX "DecisionAuditLog_actorId_idx" ON "DecisionAuditLog"("actorId");
CREATE INDEX "DecisionAuditLog_createdAt_idx" ON "DecisionAuditLog"("createdAt");
-- NotificationPolicy
CREATE TABLE "NotificationPolicy" (
"id" TEXT NOT NULL,
"eventType" TEXT NOT NULL,
"channel" TEXT NOT NULL DEFAULT 'EMAIL',
"templateId" TEXT,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"configJson" JSONB,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "NotificationPolicy_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "NotificationPolicy_eventType_key" ON "NotificationPolicy"("eventType");
CREATE INDEX "NotificationPolicy_eventType_idx" ON "NotificationPolicy"("eventType");
CREATE INDEX "NotificationPolicy_isActive_idx" ON "NotificationPolicy"("isActive");
-- =====================================================
-- 3. DROP roundId FK constraints (roundId is now a raw legacy field)
-- =====================================================
ALTER TABLE "EvaluationForm" DROP CONSTRAINT IF EXISTS "EvaluationForm_roundId_fkey";
ALTER TABLE "Assignment" DROP CONSTRAINT IF EXISTS "Assignment_roundId_fkey";
ALTER TABLE "GracePeriod" DROP CONSTRAINT IF EXISTS "GracePeriod_roundId_fkey";
ALTER TABLE "FileRequirement" DROP CONSTRAINT IF EXISTS "FileRequirement_roundId_fkey";
ALTER TABLE "FilteringRule" DROP CONSTRAINT IF EXISTS "FilteringRule_roundId_fkey";
ALTER TABLE "FilteringResult" DROP CONSTRAINT IF EXISTS "FilteringResult_roundId_fkey";
ALTER TABLE "FilteringJob" DROP CONSTRAINT IF EXISTS "FilteringJob_roundId_fkey";
ALTER TABLE "AssignmentJob" DROP CONSTRAINT IF EXISTS "AssignmentJob_roundId_fkey";
ALTER TABLE "ReminderLog" DROP CONSTRAINT IF EXISTS "ReminderLog_roundId_fkey";
ALTER TABLE "ConflictOfInterest" DROP CONSTRAINT IF EXISTS "ConflictOfInterest_roundId_fkey";
ALTER TABLE "EvaluationSummary" DROP CONSTRAINT IF EXISTS "EvaluationSummary_roundId_fkey";
ALTER TABLE "EvaluationDiscussion" DROP CONSTRAINT IF EXISTS "EvaluationDiscussion_roundId_fkey";
ALTER TABLE "LiveVotingSession" DROP CONSTRAINT IF EXISTS "LiveVotingSession_roundId_fkey";
ALTER TABLE "Project" DROP CONSTRAINT IF EXISTS "Project_roundId_fkey";
ALTER TABLE "ProjectFile" DROP CONSTRAINT IF EXISTS "ProjectFile_roundId_fkey";
ALTER TABLE "TaggingJob" DROP CONSTRAINT IF EXISTS "TaggingJob_roundId_fkey";
ALTER TABLE "Message" DROP CONSTRAINT IF EXISTS "Message_roundId_fkey";
-- Make remaining roundId columns nullable (those that were NOT NULL)
ALTER TABLE "TaggingJob" ALTER COLUMN "roundId" DROP NOT NULL;
-- Drop Round table and its enums (model retired in Phase 6)
DROP TABLE IF EXISTS "Round" CASCADE;
DROP TYPE IF EXISTS "RoundStatus";
DROP TYPE IF EXISTS "RoundType";
-- =====================================================
-- 4. ALTER EXISTING TABLES: Make roundId nullable, add stageId
-- =====================================================
-- EvaluationForm: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "EvaluationForm" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "EvaluationForm" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "EvaluationForm" ALTER COLUMN "stageId" DROP DEFAULT;
DROP INDEX "EvaluationForm_roundId_version_key";
CREATE UNIQUE INDEX "EvaluationForm_stageId_version_key" ON "EvaluationForm"("stageId", "version");
CREATE INDEX "EvaluationForm_stageId_isActive_idx" ON "EvaluationForm"("stageId", "isActive");
-- Assignment: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "Assignment" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "Assignment" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "Assignment" ALTER COLUMN "stageId" DROP DEFAULT;
DROP INDEX "Assignment_userId_projectId_roundId_key";
CREATE UNIQUE INDEX "Assignment_userId_projectId_stageId_key" ON "Assignment"("userId", "projectId", "stageId");
CREATE INDEX "Assignment_stageId_idx" ON "Assignment"("stageId");
-- GracePeriod: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "GracePeriod" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "GracePeriod" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "GracePeriod" ALTER COLUMN "stageId" DROP DEFAULT;
CREATE INDEX "GracePeriod_stageId_idx" ON "GracePeriod"("stageId");
CREATE INDEX "GracePeriod_stageId_userId_extendedUntil_idx" ON "GracePeriod"("stageId", "userId", "extendedUntil");
-- FileRequirement: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "FileRequirement" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "FileRequirement" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "FileRequirement" ALTER COLUMN "stageId" DROP DEFAULT;
CREATE INDEX "FileRequirement_stageId_idx" ON "FileRequirement"("stageId");
-- FilteringRule: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "FilteringRule" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "FilteringRule" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "FilteringRule" ALTER COLUMN "stageId" DROP DEFAULT;
CREATE INDEX "FilteringRule_stageId_idx" ON "FilteringRule"("stageId");
-- FilteringResult: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "FilteringResult" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "FilteringResult" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "FilteringResult" ALTER COLUMN "stageId" DROP DEFAULT;
DROP INDEX "FilteringResult_roundId_projectId_key";
CREATE UNIQUE INDEX "FilteringResult_stageId_projectId_key" ON "FilteringResult"("stageId", "projectId");
CREATE INDEX "FilteringResult_stageId_idx" ON "FilteringResult"("stageId");
-- FilteringJob: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "FilteringJob" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "FilteringJob" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "FilteringJob" ALTER COLUMN "stageId" DROP DEFAULT;
CREATE INDEX "FilteringJob_stageId_idx" ON "FilteringJob"("stageId");
-- AssignmentJob: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "AssignmentJob" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "AssignmentJob" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "AssignmentJob" ALTER COLUMN "stageId" DROP DEFAULT;
CREATE INDEX "AssignmentJob_stageId_idx" ON "AssignmentJob"("stageId");
-- ReminderLog: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "ReminderLog" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "ReminderLog" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "ReminderLog" ALTER COLUMN "stageId" DROP DEFAULT;
DROP INDEX "ReminderLog_roundId_userId_type_key";
CREATE UNIQUE INDEX "ReminderLog_stageId_userId_type_key" ON "ReminderLog"("stageId", "userId", "type");
CREATE INDEX "ReminderLog_stageId_idx" ON "ReminderLog"("stageId");
-- ConflictOfInterest: roundId NOT NULL → nullable (no stageId on this table)
ALTER TABLE "ConflictOfInterest" ALTER COLUMN "roundId" DROP NOT NULL;
-- EvaluationSummary: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "EvaluationSummary" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "EvaluationSummary" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "EvaluationSummary" ALTER COLUMN "stageId" DROP DEFAULT;
DROP INDEX "EvaluationSummary_projectId_roundId_key";
CREATE UNIQUE INDEX "EvaluationSummary_projectId_stageId_key" ON "EvaluationSummary"("projectId", "stageId");
CREATE INDEX "EvaluationSummary_stageId_idx" ON "EvaluationSummary"("stageId");
-- EvaluationDiscussion: roundId NOT NULL → nullable, add stageId NOT NULL
ALTER TABLE "EvaluationDiscussion" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "EvaluationDiscussion" ADD COLUMN "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
ALTER TABLE "EvaluationDiscussion" ALTER COLUMN "stageId" DROP DEFAULT;
DROP INDEX "EvaluationDiscussion_projectId_roundId_key";
CREATE UNIQUE INDEX "EvaluationDiscussion_projectId_stageId_key" ON "EvaluationDiscussion"("projectId", "stageId");
CREATE INDEX "EvaluationDiscussion_stageId_idx" ON "EvaluationDiscussion"("stageId");
-- Message: add stageId (nullable)
ALTER TABLE "Message" ADD COLUMN "stageId" TEXT;
CREATE INDEX "Message_stageId_idx" ON "Message"("stageId");
-- LiveVotingSession: roundId NOT NULL → nullable, add stageId (nullable, unique)
ALTER TABLE "LiveVotingSession" ALTER COLUMN "roundId" DROP NOT NULL;
ALTER TABLE "LiveVotingSession" ADD COLUMN "stageId" TEXT;
CREATE UNIQUE INDEX "LiveVotingSession_stageId_key" ON "LiveVotingSession"("stageId");
-- =====================================================
-- 4. FOREIGN KEY CONSTRAINTS: New tables
-- =====================================================
-- Pipeline
ALTER TABLE "Pipeline" ADD CONSTRAINT "Pipeline_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- Track
ALTER TABLE "Track" ADD CONSTRAINT "Track_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "Pipeline"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- Stage
ALTER TABLE "Stage" ADD CONSTRAINT "Stage_trackId_fkey" FOREIGN KEY ("trackId") REFERENCES "Track"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- StageTransition
ALTER TABLE "StageTransition" ADD CONSTRAINT "StageTransition_fromStageId_fkey" FOREIGN KEY ("fromStageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "StageTransition" ADD CONSTRAINT "StageTransition_toStageId_fkey" FOREIGN KEY ("toStageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- ProjectStageState
ALTER TABLE "ProjectStageState" ADD CONSTRAINT "ProjectStageState_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "ProjectStageState" ADD CONSTRAINT "ProjectStageState_trackId_fkey" FOREIGN KEY ("trackId") REFERENCES "Track"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "ProjectStageState" ADD CONSTRAINT "ProjectStageState_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- RoutingRule
ALTER TABLE "RoutingRule" ADD CONSTRAINT "RoutingRule_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "Pipeline"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "RoutingRule" ADD CONSTRAINT "RoutingRule_sourceTrackId_fkey" FOREIGN KEY ("sourceTrackId") REFERENCES "Track"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "RoutingRule" ADD CONSTRAINT "RoutingRule_destinationTrackId_fkey" FOREIGN KEY ("destinationTrackId") REFERENCES "Track"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- Cohort
ALTER TABLE "Cohort" ADD CONSTRAINT "Cohort_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- CohortProject
ALTER TABLE "CohortProject" ADD CONSTRAINT "CohortProject_cohortId_fkey" FOREIGN KEY ("cohortId") REFERENCES "Cohort"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "CohortProject" ADD CONSTRAINT "CohortProject_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- LiveProgressCursor
ALTER TABLE "LiveProgressCursor" ADD CONSTRAINT "LiveProgressCursor_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- =====================================================
-- 5. FOREIGN KEY CONSTRAINTS: stageId on altered tables
-- =====================================================
ALTER TABLE "EvaluationForm" ADD CONSTRAINT "EvaluationForm_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "GracePeriod" ADD CONSTRAINT "GracePeriod_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "FileRequirement" ADD CONSTRAINT "FileRequirement_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "FilteringRule" ADD CONSTRAINT "FilteringRule_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "FilteringResult" ADD CONSTRAINT "FilteringResult_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "FilteringJob" ADD CONSTRAINT "FilteringJob_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "AssignmentJob" ADD CONSTRAINT "AssignmentJob_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "ReminderLog" ADD CONSTRAINT "ReminderLog_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "EvaluationSummary" ADD CONSTRAINT "EvaluationSummary_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "Message" ADD CONSTRAINT "Message_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "LiveVotingSession" ADD CONSTRAINT "LiveVotingSession_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- =====================================================
-- 6. SpecialAward: add trackId (nullable, unique)
-- =====================================================
ALTER TABLE "SpecialAward" ADD COLUMN "trackId" TEXT;
CREATE UNIQUE INDEX "SpecialAward_trackId_key" ON "SpecialAward"("trackId");
ALTER TABLE "SpecialAward" ADD CONSTRAINT "SpecialAward_trackId_fkey" FOREIGN KEY ("trackId") REFERENCES "Track"("id") ON DELETE SET NULL ON UPDATE CASCADE;