Apply full refactor updates plus pipeline/email UX confirmations
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m33s
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m33s
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,91 +1,91 @@
|
||||
-- Universal Apply Page: Make Project.roundId nullable and add programId FK
|
||||
-- This migration enables projects to be submitted to a program/edition without being assigned to a specific round
|
||||
-- NOTE: Written to be idempotent (safe to re-run if partially applied)
|
||||
|
||||
-- Step 1: Add Program.slug for edition-wide apply URLs (nullable for existing programs)
|
||||
ALTER TABLE "Program" ADD COLUMN IF NOT EXISTS "slug" TEXT;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "Program_slug_key" ON "Program"("slug");
|
||||
|
||||
-- Step 2: Add programId column (nullable initially to handle existing data)
|
||||
ALTER TABLE "Project" ADD COLUMN IF NOT EXISTS "programId" TEXT;
|
||||
|
||||
-- Step 3: Backfill programId from existing round relationships
|
||||
-- Only update rows where programId is still NULL (idempotent)
|
||||
UPDATE "Project" p
|
||||
SET "programId" = r."programId"
|
||||
FROM "Round" r
|
||||
WHERE p."roundId" = r.id
|
||||
AND p."programId" IS NULL;
|
||||
|
||||
-- Step 4: Handle orphaned projects (no roundId = no way to derive programId)
|
||||
-- Assign them to the first available program, or delete them if no program exists
|
||||
DO $$
|
||||
DECLARE
|
||||
null_count INTEGER;
|
||||
fallback_program_id TEXT;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO null_count FROM "Project" WHERE "programId" IS NULL;
|
||||
IF null_count > 0 THEN
|
||||
SELECT id INTO fallback_program_id FROM "Program" ORDER BY "createdAt" ASC LIMIT 1;
|
||||
IF fallback_program_id IS NOT NULL THEN
|
||||
UPDATE "Project" SET "programId" = fallback_program_id WHERE "programId" IS NULL;
|
||||
RAISE NOTICE 'Assigned % orphaned projects to fallback program %', null_count, fallback_program_id;
|
||||
ELSE
|
||||
DELETE FROM "Project" WHERE "programId" IS NULL;
|
||||
RAISE NOTICE 'Deleted % orphaned projects (no program exists to assign them to)', null_count;
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Step 5: Make programId required (NOT NULL constraint) - safe if already NOT NULL
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'Project' AND column_name = 'programId' AND is_nullable = 'YES'
|
||||
) THEN
|
||||
ALTER TABLE "Project" ALTER COLUMN "programId" SET NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Step 6: Add foreign key constraint for programId (skip if already exists)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE constraint_name = 'Project_programId_fkey' AND table_name = 'Project'
|
||||
) THEN
|
||||
ALTER TABLE "Project" ADD CONSTRAINT "Project_programId_fkey"
|
||||
FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Step 7: Make roundId nullable (allow projects without round assignment)
|
||||
-- Safe: DROP NOT NULL is idempotent if already nullable
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'Project' AND column_name = 'roundId' AND is_nullable = 'NO'
|
||||
) THEN
|
||||
ALTER TABLE "Project" ALTER COLUMN "roundId" DROP NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Step 8: Update round FK to SET NULL on delete (instead of CASCADE)
|
||||
-- Projects should remain in the database if their round is deleted
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE constraint_name = 'Project_roundId_fkey' AND table_name = 'Project'
|
||||
) THEN
|
||||
ALTER TABLE "Project" DROP CONSTRAINT "Project_roundId_fkey";
|
||||
END IF;
|
||||
ALTER TABLE "Project" ADD CONSTRAINT "Project_roundId_fkey"
|
||||
FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL;
|
||||
END $$;
|
||||
|
||||
-- Step 9: Add performance indexes
|
||||
CREATE INDEX IF NOT EXISTS "Project_programId_idx" ON "Project"("programId");
|
||||
CREATE INDEX IF NOT EXISTS "Project_programId_roundId_idx" ON "Project"("programId", "roundId");
|
||||
-- Universal Apply Page: Make Project.roundId nullable and add programId FK
|
||||
-- This migration enables projects to be submitted to a program/edition without being assigned to a specific round
|
||||
-- NOTE: Written to be idempotent (safe to re-run if partially applied)
|
||||
|
||||
-- Step 1: Add Program.slug for edition-wide apply URLs (nullable for existing programs)
|
||||
ALTER TABLE "Program" ADD COLUMN IF NOT EXISTS "slug" TEXT;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "Program_slug_key" ON "Program"("slug");
|
||||
|
||||
-- Step 2: Add programId column (nullable initially to handle existing data)
|
||||
ALTER TABLE "Project" ADD COLUMN IF NOT EXISTS "programId" TEXT;
|
||||
|
||||
-- Step 3: Backfill programId from existing round relationships
|
||||
-- Only update rows where programId is still NULL (idempotent)
|
||||
UPDATE "Project" p
|
||||
SET "programId" = r."programId"
|
||||
FROM "Round" r
|
||||
WHERE p."roundId" = r.id
|
||||
AND p."programId" IS NULL;
|
||||
|
||||
-- Step 4: Handle orphaned projects (no roundId = no way to derive programId)
|
||||
-- Assign them to the first available program, or delete them if no program exists
|
||||
DO $$
|
||||
DECLARE
|
||||
null_count INTEGER;
|
||||
fallback_program_id TEXT;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO null_count FROM "Project" WHERE "programId" IS NULL;
|
||||
IF null_count > 0 THEN
|
||||
SELECT id INTO fallback_program_id FROM "Program" ORDER BY "createdAt" ASC LIMIT 1;
|
||||
IF fallback_program_id IS NOT NULL THEN
|
||||
UPDATE "Project" SET "programId" = fallback_program_id WHERE "programId" IS NULL;
|
||||
RAISE NOTICE 'Assigned % orphaned projects to fallback program %', null_count, fallback_program_id;
|
||||
ELSE
|
||||
DELETE FROM "Project" WHERE "programId" IS NULL;
|
||||
RAISE NOTICE 'Deleted % orphaned projects (no program exists to assign them to)', null_count;
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Step 5: Make programId required (NOT NULL constraint) - safe if already NOT NULL
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'Project' AND column_name = 'programId' AND is_nullable = 'YES'
|
||||
) THEN
|
||||
ALTER TABLE "Project" ALTER COLUMN "programId" SET NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Step 6: Add foreign key constraint for programId (skip if already exists)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE constraint_name = 'Project_programId_fkey' AND table_name = 'Project'
|
||||
) THEN
|
||||
ALTER TABLE "Project" ADD CONSTRAINT "Project_programId_fkey"
|
||||
FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Step 7: Make roundId nullable (allow projects without round assignment)
|
||||
-- Safe: DROP NOT NULL is idempotent if already nullable
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'Project' AND column_name = 'roundId' AND is_nullable = 'NO'
|
||||
) THEN
|
||||
ALTER TABLE "Project" ALTER COLUMN "roundId" DROP NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Step 8: Update round FK to SET NULL on delete (instead of CASCADE)
|
||||
-- Projects should remain in the database if their round is deleted
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE constraint_name = 'Project_roundId_fkey' AND table_name = 'Project'
|
||||
) THEN
|
||||
ALTER TABLE "Project" DROP CONSTRAINT "Project_roundId_fkey";
|
||||
END IF;
|
||||
ALTER TABLE "Project" ADD CONSTRAINT "Project_roundId_fkey"
|
||||
FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL;
|
||||
END $$;
|
||||
|
||||
-- Step 9: Add performance indexes
|
||||
CREATE INDEX IF NOT EXISTS "Project_programId_idx" ON "Project"("programId");
|
||||
CREATE INDEX IF NOT EXISTS "Project_programId_roundId_idx" ON "Project"("programId", "roundId");
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
-- Reconciliation migration: Add missing foreign keys and indexes
|
||||
-- The add_15_features migration omitted some FKs and indexes that the schema expects
|
||||
-- This migration brings the database in line with the Prisma schema
|
||||
|
||||
-- =====================================================
|
||||
-- Missing Foreign Keys
|
||||
-- =====================================================
|
||||
|
||||
-- RoundTemplate → Program
|
||||
ALTER TABLE "RoundTemplate" ADD CONSTRAINT "RoundTemplate_programId_fkey"
|
||||
FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- RoundTemplate → User (creator)
|
||||
ALTER TABLE "RoundTemplate" ADD CONSTRAINT "RoundTemplate_createdBy_fkey"
|
||||
FOREIGN KEY ("createdBy") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- Message → Round
|
||||
ALTER TABLE "Message" ADD CONSTRAINT "Message_roundId_fkey"
|
||||
FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- EvaluationDiscussion → Round
|
||||
ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_roundId_fkey"
|
||||
FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- ProjectFile → ProjectFile (self-relation for file versioning)
|
||||
ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_replacedById_fkey"
|
||||
FOREIGN KEY ("replacedById") REFERENCES "ProjectFile"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- =====================================================
|
||||
-- Missing Indexes
|
||||
-- =====================================================
|
||||
|
||||
CREATE INDEX "RoundTemplate_roundType_idx" ON "RoundTemplate"("roundType");
|
||||
CREATE INDEX "MentorNote_authorId_idx" ON "MentorNote"("authorId");
|
||||
CREATE INDEX "MentorMilestoneCompletion_completedById_idx" ON "MentorMilestoneCompletion"("completedById");
|
||||
CREATE INDEX "Webhook_createdById_idx" ON "Webhook"("createdById");
|
||||
CREATE INDEX "WebhookDelivery_event_idx" ON "WebhookDelivery"("event");
|
||||
CREATE INDEX "Message_roundId_idx" ON "Message"("roundId");
|
||||
CREATE INDEX "EvaluationDiscussion_closedById_idx" ON "EvaluationDiscussion"("closedById");
|
||||
CREATE INDEX "DiscussionComment_discussionId_idx" ON "DiscussionComment"("discussionId");
|
||||
CREATE INDEX "DiscussionComment_userId_idx" ON "DiscussionComment"("userId");
|
||||
-- Reconciliation migration: Add missing foreign keys and indexes
|
||||
-- The add_15_features migration omitted some FKs and indexes that the schema expects
|
||||
-- This migration brings the database in line with the Prisma schema
|
||||
|
||||
-- =====================================================
|
||||
-- Missing Foreign Keys
|
||||
-- =====================================================
|
||||
|
||||
-- RoundTemplate → Program
|
||||
ALTER TABLE "RoundTemplate" ADD CONSTRAINT "RoundTemplate_programId_fkey"
|
||||
FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- RoundTemplate → User (creator)
|
||||
ALTER TABLE "RoundTemplate" ADD CONSTRAINT "RoundTemplate_createdBy_fkey"
|
||||
FOREIGN KEY ("createdBy") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- Message → Round
|
||||
ALTER TABLE "Message" ADD CONSTRAINT "Message_roundId_fkey"
|
||||
FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- EvaluationDiscussion → Round
|
||||
ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_roundId_fkey"
|
||||
FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- ProjectFile → ProjectFile (self-relation for file versioning)
|
||||
ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_replacedById_fkey"
|
||||
FOREIGN KEY ("replacedById") REFERENCES "ProjectFile"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- =====================================================
|
||||
-- Missing Indexes
|
||||
-- =====================================================
|
||||
|
||||
CREATE INDEX "RoundTemplate_roundType_idx" ON "RoundTemplate"("roundType");
|
||||
CREATE INDEX "MentorNote_authorId_idx" ON "MentorNote"("authorId");
|
||||
CREATE INDEX "MentorMilestoneCompletion_completedById_idx" ON "MentorMilestoneCompletion"("completedById");
|
||||
CREATE INDEX "Webhook_createdById_idx" ON "Webhook"("createdById");
|
||||
CREATE INDEX "WebhookDelivery_event_idx" ON "WebhookDelivery"("event");
|
||||
CREATE INDEX "Message_roundId_idx" ON "Message"("roundId");
|
||||
CREATE INDEX "EvaluationDiscussion_closedById_idx" ON "EvaluationDiscussion"("closedById");
|
||||
CREATE INDEX "DiscussionComment_discussionId_idx" ON "DiscussionComment"("discussionId");
|
||||
CREATE INDEX "DiscussionComment_userId_idx" ON "DiscussionComment"("userId");
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
-- Fix round deletion FK constraint errors
|
||||
-- Add CASCADE on Evaluation.formId so deleting EvaluationForm cascades to Evaluations
|
||||
-- Add SET NULL on ProjectFile.roundId so deleting Round nullifies the reference
|
||||
|
||||
-- AlterTable: Evaluation.formId -> onDelete CASCADE
|
||||
ALTER TABLE "Evaluation" DROP CONSTRAINT "Evaluation_formId_fkey";
|
||||
ALTER TABLE "Evaluation" ADD CONSTRAINT "Evaluation_formId_fkey"
|
||||
FOREIGN KEY ("formId") REFERENCES "EvaluationForm"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AlterTable: ProjectFile.roundId -> onDelete SET NULL
|
||||
ALTER TABLE "ProjectFile" DROP CONSTRAINT "ProjectFile_roundId_fkey";
|
||||
ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_roundId_fkey"
|
||||
FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
-- Fix round deletion FK constraint errors
|
||||
-- Add CASCADE on Evaluation.formId so deleting EvaluationForm cascades to Evaluations
|
||||
-- Add SET NULL on ProjectFile.roundId so deleting Round nullifies the reference
|
||||
|
||||
-- AlterTable: Evaluation.formId -> onDelete CASCADE
|
||||
ALTER TABLE "Evaluation" DROP CONSTRAINT "Evaluation_formId_fkey";
|
||||
ALTER TABLE "Evaluation" ADD CONSTRAINT "Evaluation_formId_fkey"
|
||||
FOREIGN KEY ("formId") REFERENCES "EvaluationForm"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AlterTable: ProjectFile.roundId -> onDelete SET NULL
|
||||
ALTER TABLE "ProjectFile" DROP CONSTRAINT "ProjectFile_roundId_fkey";
|
||||
ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_roundId_fkey"
|
||||
FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "FileRequirement" (
|
||||
"id" TEXT NOT NULL,
|
||||
"roundId" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"acceptedMimeTypes" TEXT[],
|
||||
"maxSizeMB" INTEGER,
|
||||
"isRequired" BOOLEAN NOT NULL DEFAULT true,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "FileRequirement_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "FileRequirement_roundId_idx" ON "FileRequirement"("roundId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FileRequirement" ADD CONSTRAINT "FileRequirement_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AlterTable: add requirementId to ProjectFile
|
||||
ALTER TABLE "ProjectFile" ADD COLUMN "requirementId" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ProjectFile_requirementId_idx" ON "ProjectFile"("requirementId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_requirementId_fkey" FOREIGN KEY ("requirementId") REFERENCES "FileRequirement"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
-- CreateTable
|
||||
CREATE TABLE "FileRequirement" (
|
||||
"id" TEXT NOT NULL,
|
||||
"roundId" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"acceptedMimeTypes" TEXT[],
|
||||
"maxSizeMB" INTEGER,
|
||||
"isRequired" BOOLEAN NOT NULL DEFAULT true,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "FileRequirement_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "FileRequirement_roundId_idx" ON "FileRequirement"("roundId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FileRequirement" ADD CONSTRAINT "FileRequirement_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AlterTable: add requirementId to ProjectFile
|
||||
ALTER TABLE "ProjectFile" ADD COLUMN "requirementId" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ProjectFile_requirementId_idx" ON "ProjectFile"("requirementId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_requirementId_fkey" FOREIGN KEY ("requirementId") REFERENCES "FileRequirement"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
@@ -1,129 +1,129 @@
|
||||
-- Migration: Add all missing schema elements not covered by previous migrations
|
||||
-- This brings the database fully in line with prisma/schema.prisma
|
||||
-- Uses IF NOT EXISTS / DO $$ guards for idempotent execution
|
||||
|
||||
-- =============================================================================
|
||||
-- 1. MISSING TABLE: WizardTemplate
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "WizardTemplate" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"config" JSONB NOT NULL,
|
||||
"isGlobal" BOOLEAN NOT NULL DEFAULT false,
|
||||
"programId" TEXT,
|
||||
"createdBy" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "WizardTemplate_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "WizardTemplate_programId_idx" ON "WizardTemplate"("programId");
|
||||
CREATE INDEX IF NOT EXISTS "WizardTemplate_isGlobal_idx" ON "WizardTemplate"("isGlobal");
|
||||
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "WizardTemplate" ADD CONSTRAINT "WizardTemplate_programId_fkey"
|
||||
FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "WizardTemplate" ADD CONSTRAINT "WizardTemplate_createdBy_fkey"
|
||||
FOREIGN KEY ("createdBy") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- 2. MISSING COLUMNS ON SpecialAward: eligibility job tracking fields
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobStatus" TEXT;
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobTotal" INTEGER;
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobDone" INTEGER;
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobError" TEXT;
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobStarted" TIMESTAMP(3);
|
||||
|
||||
-- =============================================================================
|
||||
-- 3. Project.referralSource: Already in init migration. No action needed.
|
||||
-- Round.slug: Already in init migration. No action needed.
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- 5. MISSING INDEXES
|
||||
-- =============================================================================
|
||||
|
||||
-- 5a. Assignment: @@index([projectId, userId])
|
||||
CREATE INDEX IF NOT EXISTS "Assignment_projectId_userId_idx" ON "Assignment"("projectId", "userId");
|
||||
|
||||
-- 5b. AuditLog: @@index([sessionId])
|
||||
CREATE INDEX IF NOT EXISTS "AuditLog_sessionId_idx" ON "AuditLog"("sessionId");
|
||||
|
||||
-- 5c. ProjectFile: @@index([projectId, roundId])
|
||||
CREATE INDEX IF NOT EXISTS "ProjectFile_projectId_roundId_idx" ON "ProjectFile"("projectId", "roundId");
|
||||
|
||||
-- 5d. MessageRecipient: @@index([userId])
|
||||
CREATE INDEX IF NOT EXISTS "MessageRecipient_userId_idx" ON "MessageRecipient"("userId");
|
||||
|
||||
-- 5e. MessageRecipient: @@unique([messageId, userId, channel])
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "MessageRecipient_messageId_userId_channel_key" ON "MessageRecipient"("messageId", "userId", "channel");
|
||||
|
||||
-- 5f. AwardEligibility: @@index([awardId, eligible]) - composite index
|
||||
CREATE INDEX IF NOT EXISTS "AwardEligibility_awardId_eligible_idx" ON "AwardEligibility"("awardId", "eligible");
|
||||
|
||||
-- =============================================================================
|
||||
-- 6. REMOVE STALE INDEX: Message_scheduledAt_idx
|
||||
-- The schema does NOT have @@index([scheduledAt]) on Message.
|
||||
-- The add_15_features migration created it, but the schema doesn't list it.
|
||||
-- Leaving it as-is since it's harmless and could be useful.
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- 7. VERIFY: All models from add_15_features are present
|
||||
-- DigestLog, RoundTemplate, MentorNote, MentorMilestone,
|
||||
-- MentorMilestoneCompletion, Message, MessageTemplate, MessageRecipient,
|
||||
-- Webhook, WebhookDelivery, EvaluationDiscussion, DiscussionComment
|
||||
-- -> All confirmed created in 20260205223133_add_15_features migration.
|
||||
-- -> All FKs confirmed in add_15_features + 20260208000000_add_missing_fks_indexes.
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- 8. VERIFY: Existing tables from init and subsequent migrations
|
||||
-- All core tables (User, Account, Session, VerificationToken, Program, Round,
|
||||
-- EvaluationForm, Project, ProjectFile, Assignment, Evaluation, GracePeriod,
|
||||
-- SystemSettings, AuditLog, AIUsageLog, NotificationLog, InAppNotification,
|
||||
-- NotificationEmailSetting, LearningResource, ResourceAccess, Partner,
|
||||
-- ExpertiseTag, ProjectTag, LiveVotingSession, LiveVote, TeamMember,
|
||||
-- MentorAssignment, FilteringRule, FilteringResult, FilteringJob,
|
||||
-- AssignmentJob, TaggingJob, SpecialAward, AwardEligibility, AwardJuror,
|
||||
-- AwardVote, ReminderLog, ConflictOfInterest, EvaluationSummary,
|
||||
-- ProjectStatusHistory, MentorMessage, FileRequirement)
|
||||
-- -> All confirmed present in migrations.
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- SUMMARY OF CHANGES IN THIS MIGRATION:
|
||||
--
|
||||
-- NEW TABLE:
|
||||
-- - WizardTemplate (with programId FK, createdBy FK, indexes)
|
||||
--
|
||||
-- NEW COLUMNS:
|
||||
-- - SpecialAward.eligibilityJobStatus (TEXT, nullable)
|
||||
-- - SpecialAward.eligibilityJobTotal (INTEGER, nullable)
|
||||
-- - SpecialAward.eligibilityJobDone (INTEGER, nullable)
|
||||
-- - SpecialAward.eligibilityJobError (TEXT, nullable)
|
||||
-- - SpecialAward.eligibilityJobStarted (TIMESTAMP, nullable)
|
||||
--
|
||||
-- NEW INDEXES:
|
||||
-- - Assignment_projectId_userId_idx
|
||||
-- - AuditLog_sessionId_idx
|
||||
-- - ProjectFile_projectId_roundId_idx
|
||||
-- - MessageRecipient_userId_idx
|
||||
-- - MessageRecipient_messageId_userId_channel_key (UNIQUE)
|
||||
-- - AwardEligibility_awardId_eligible_idx
|
||||
-- - WizardTemplate_programId_idx
|
||||
-- - WizardTemplate_isGlobal_idx
|
||||
--
|
||||
-- NEW FOREIGN KEYS:
|
||||
-- - WizardTemplate_programId_fkey -> Program(id) ON DELETE CASCADE
|
||||
-- - WizardTemplate_createdBy_fkey -> User(id) ON DELETE RESTRICT
|
||||
-- =============================================================================
|
||||
-- Migration: Add all missing schema elements not covered by previous migrations
|
||||
-- This brings the database fully in line with prisma/schema.prisma
|
||||
-- Uses IF NOT EXISTS / DO $$ guards for idempotent execution
|
||||
|
||||
-- =============================================================================
|
||||
-- 1. MISSING TABLE: WizardTemplate
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "WizardTemplate" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"config" JSONB NOT NULL,
|
||||
"isGlobal" BOOLEAN NOT NULL DEFAULT false,
|
||||
"programId" TEXT,
|
||||
"createdBy" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "WizardTemplate_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "WizardTemplate_programId_idx" ON "WizardTemplate"("programId");
|
||||
CREATE INDEX IF NOT EXISTS "WizardTemplate_isGlobal_idx" ON "WizardTemplate"("isGlobal");
|
||||
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "WizardTemplate" ADD CONSTRAINT "WizardTemplate_programId_fkey"
|
||||
FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "WizardTemplate" ADD CONSTRAINT "WizardTemplate_createdBy_fkey"
|
||||
FOREIGN KEY ("createdBy") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- 2. MISSING COLUMNS ON SpecialAward: eligibility job tracking fields
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobStatus" TEXT;
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobTotal" INTEGER;
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobDone" INTEGER;
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobError" TEXT;
|
||||
ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobStarted" TIMESTAMP(3);
|
||||
|
||||
-- =============================================================================
|
||||
-- 3. Project.referralSource: Already in init migration. No action needed.
|
||||
-- Round.slug: Already in init migration. No action needed.
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- 5. MISSING INDEXES
|
||||
-- =============================================================================
|
||||
|
||||
-- 5a. Assignment: @@index([projectId, userId])
|
||||
CREATE INDEX IF NOT EXISTS "Assignment_projectId_userId_idx" ON "Assignment"("projectId", "userId");
|
||||
|
||||
-- 5b. AuditLog: @@index([sessionId])
|
||||
CREATE INDEX IF NOT EXISTS "AuditLog_sessionId_idx" ON "AuditLog"("sessionId");
|
||||
|
||||
-- 5c. ProjectFile: @@index([projectId, roundId])
|
||||
CREATE INDEX IF NOT EXISTS "ProjectFile_projectId_roundId_idx" ON "ProjectFile"("projectId", "roundId");
|
||||
|
||||
-- 5d. MessageRecipient: @@index([userId])
|
||||
CREATE INDEX IF NOT EXISTS "MessageRecipient_userId_idx" ON "MessageRecipient"("userId");
|
||||
|
||||
-- 5e. MessageRecipient: @@unique([messageId, userId, channel])
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "MessageRecipient_messageId_userId_channel_key" ON "MessageRecipient"("messageId", "userId", "channel");
|
||||
|
||||
-- 5f. AwardEligibility: @@index([awardId, eligible]) - composite index
|
||||
CREATE INDEX IF NOT EXISTS "AwardEligibility_awardId_eligible_idx" ON "AwardEligibility"("awardId", "eligible");
|
||||
|
||||
-- =============================================================================
|
||||
-- 6. REMOVE STALE INDEX: Message_scheduledAt_idx
|
||||
-- The schema does NOT have @@index([scheduledAt]) on Message.
|
||||
-- The add_15_features migration created it, but the schema doesn't list it.
|
||||
-- Leaving it as-is since it's harmless and could be useful.
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- 7. VERIFY: All models from add_15_features are present
|
||||
-- DigestLog, RoundTemplate, MentorNote, MentorMilestone,
|
||||
-- MentorMilestoneCompletion, Message, MessageTemplate, MessageRecipient,
|
||||
-- Webhook, WebhookDelivery, EvaluationDiscussion, DiscussionComment
|
||||
-- -> All confirmed created in 20260205223133_add_15_features migration.
|
||||
-- -> All FKs confirmed in add_15_features + 20260208000000_add_missing_fks_indexes.
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- 8. VERIFY: Existing tables from init and subsequent migrations
|
||||
-- All core tables (User, Account, Session, VerificationToken, Program, Round,
|
||||
-- EvaluationForm, Project, ProjectFile, Assignment, Evaluation, GracePeriod,
|
||||
-- SystemSettings, AuditLog, AIUsageLog, NotificationLog, InAppNotification,
|
||||
-- NotificationEmailSetting, LearningResource, ResourceAccess, Partner,
|
||||
-- ExpertiseTag, ProjectTag, LiveVotingSession, LiveVote, TeamMember,
|
||||
-- MentorAssignment, FilteringRule, FilteringResult, FilteringJob,
|
||||
-- AssignmentJob, TaggingJob, SpecialAward, AwardEligibility, AwardJuror,
|
||||
-- AwardVote, ReminderLog, ConflictOfInterest, EvaluationSummary,
|
||||
-- ProjectStatusHistory, MentorMessage, FileRequirement)
|
||||
-- -> All confirmed present in migrations.
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- SUMMARY OF CHANGES IN THIS MIGRATION:
|
||||
--
|
||||
-- NEW TABLE:
|
||||
-- - WizardTemplate (with programId FK, createdBy FK, indexes)
|
||||
--
|
||||
-- NEW COLUMNS:
|
||||
-- - SpecialAward.eligibilityJobStatus (TEXT, nullable)
|
||||
-- - SpecialAward.eligibilityJobTotal (INTEGER, nullable)
|
||||
-- - SpecialAward.eligibilityJobDone (INTEGER, nullable)
|
||||
-- - SpecialAward.eligibilityJobError (TEXT, nullable)
|
||||
-- - SpecialAward.eligibilityJobStarted (TIMESTAMP, nullable)
|
||||
--
|
||||
-- NEW INDEXES:
|
||||
-- - Assignment_projectId_userId_idx
|
||||
-- - AuditLog_sessionId_idx
|
||||
-- - ProjectFile_projectId_roundId_idx
|
||||
-- - MessageRecipient_userId_idx
|
||||
-- - MessageRecipient_messageId_userId_channel_key (UNIQUE)
|
||||
-- - AwardEligibility_awardId_eligible_idx
|
||||
-- - WizardTemplate_programId_idx
|
||||
-- - WizardTemplate_isGlobal_idx
|
||||
--
|
||||
-- NEW FOREIGN KEYS:
|
||||
-- - WizardTemplate_programId_fkey -> Program(id) ON DELETE CASCADE
|
||||
-- - WizardTemplate_createdBy_fkey -> User(id) ON DELETE RESTRICT
|
||||
-- =============================================================================
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AwardVote_awardId_userId_idx" ON "AwardVote"("awardId", "userId");
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AwardVote_awardId_userId_idx" ON "AwardVote"("awardId", "userId");
|
||||
|
||||
@@ -1,99 +1,99 @@
|
||||
-- Migration: Add live voting enhancements (criteria voting, audience voting, AudienceVoter)
|
||||
-- Brings LiveVotingSession, LiveVote, and new AudienceVoter model in sync with schema.prisma
|
||||
-- Uses IF NOT EXISTS / DO $$ guards for idempotent execution
|
||||
|
||||
-- =============================================================================
|
||||
-- 1. LiveVotingSession: Add criteria-based & audience voting columns
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "votingMode" TEXT NOT NULL DEFAULT 'simple';
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "criteriaJson" JSONB;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingMode" TEXT NOT NULL DEFAULT 'disabled';
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceMaxFavorites" INTEGER NOT NULL DEFAULT 3;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceRequireId" BOOLEAN NOT NULL DEFAULT false;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingDuration" INTEGER;
|
||||
|
||||
-- =============================================================================
|
||||
-- 2. LiveVote: Add criteria scores, audience voter link, make userId nullable
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "criterionScoresJson" JSONB;
|
||||
ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "audienceVoterId" TEXT;
|
||||
|
||||
-- Make userId nullable (was NOT NULL in init migration)
|
||||
ALTER TABLE "LiveVote" ALTER COLUMN "userId" DROP NOT NULL;
|
||||
|
||||
-- =============================================================================
|
||||
-- 3. AudienceVoter: New table for audience participation
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "AudienceVoter" (
|
||||
"id" TEXT NOT NULL,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"identifier" TEXT,
|
||||
"identifierType" TEXT,
|
||||
"ipAddress" TEXT,
|
||||
"userAgent" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "AudienceVoter_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- Unique constraint on token
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_token_key" UNIQUE ("token");
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS "AudienceVoter_sessionId_idx" ON "AudienceVoter"("sessionId");
|
||||
CREATE INDEX IF NOT EXISTS "AudienceVoter_token_idx" ON "AudienceVoter"("token");
|
||||
|
||||
-- Foreign key: AudienceVoter.sessionId -> LiveVotingSession.id
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_sessionId_fkey"
|
||||
FOREIGN KEY ("sessionId") REFERENCES "LiveVotingSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- 4. LiveVote: Foreign key and indexes for audienceVoterId
|
||||
-- =============================================================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "LiveVote_audienceVoterId_idx" ON "LiveVote"("audienceVoterId");
|
||||
|
||||
-- Foreign key: LiveVote.audienceVoterId -> AudienceVoter.id
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_audienceVoterId_fkey"
|
||||
FOREIGN KEY ("audienceVoterId") REFERENCES "AudienceVoter"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Unique constraint: sessionId + projectId + audienceVoterId
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_sessionId_projectId_audienceVoterId_key"
|
||||
UNIQUE ("sessionId", "projectId", "audienceVoterId");
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- SUMMARY:
|
||||
--
|
||||
-- LiveVotingSession new columns:
|
||||
-- - votingMode (TEXT, default 'simple')
|
||||
-- - criteriaJson (JSONB, nullable)
|
||||
-- - audienceVotingMode (TEXT, default 'disabled')
|
||||
-- - audienceMaxFavorites (INTEGER, default 3)
|
||||
-- - audienceRequireId (BOOLEAN, default false)
|
||||
-- - audienceVotingDuration (INTEGER, nullable)
|
||||
--
|
||||
-- LiveVote changes:
|
||||
-- - criterionScoresJson (JSONB, nullable) - new column
|
||||
-- - audienceVoterId (TEXT, nullable) - new column
|
||||
-- - userId changed from NOT NULL to nullable
|
||||
-- - New unique: (sessionId, projectId, audienceVoterId)
|
||||
-- - New index: audienceVoterId
|
||||
-- - New FK: audienceVoterId -> AudienceVoter(id)
|
||||
--
|
||||
-- New table: AudienceVoter
|
||||
-- - id, sessionId, token (unique), identifier, identifierType,
|
||||
-- ipAddress, userAgent, createdAt
|
||||
-- - FK: sessionId -> LiveVotingSession(id) CASCADE
|
||||
-- =============================================================================
|
||||
-- Migration: Add live voting enhancements (criteria voting, audience voting, AudienceVoter)
|
||||
-- Brings LiveVotingSession, LiveVote, and new AudienceVoter model in sync with schema.prisma
|
||||
-- Uses IF NOT EXISTS / DO $$ guards for idempotent execution
|
||||
|
||||
-- =============================================================================
|
||||
-- 1. LiveVotingSession: Add criteria-based & audience voting columns
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "votingMode" TEXT NOT NULL DEFAULT 'simple';
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "criteriaJson" JSONB;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingMode" TEXT NOT NULL DEFAULT 'disabled';
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceMaxFavorites" INTEGER NOT NULL DEFAULT 3;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceRequireId" BOOLEAN NOT NULL DEFAULT false;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingDuration" INTEGER;
|
||||
|
||||
-- =============================================================================
|
||||
-- 2. LiveVote: Add criteria scores, audience voter link, make userId nullable
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "criterionScoresJson" JSONB;
|
||||
ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "audienceVoterId" TEXT;
|
||||
|
||||
-- Make userId nullable (was NOT NULL in init migration)
|
||||
ALTER TABLE "LiveVote" ALTER COLUMN "userId" DROP NOT NULL;
|
||||
|
||||
-- =============================================================================
|
||||
-- 3. AudienceVoter: New table for audience participation
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "AudienceVoter" (
|
||||
"id" TEXT NOT NULL,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"identifier" TEXT,
|
||||
"identifierType" TEXT,
|
||||
"ipAddress" TEXT,
|
||||
"userAgent" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "AudienceVoter_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- Unique constraint on token
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_token_key" UNIQUE ("token");
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS "AudienceVoter_sessionId_idx" ON "AudienceVoter"("sessionId");
|
||||
CREATE INDEX IF NOT EXISTS "AudienceVoter_token_idx" ON "AudienceVoter"("token");
|
||||
|
||||
-- Foreign key: AudienceVoter.sessionId -> LiveVotingSession.id
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_sessionId_fkey"
|
||||
FOREIGN KEY ("sessionId") REFERENCES "LiveVotingSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- 4. LiveVote: Foreign key and indexes for audienceVoterId
|
||||
-- =============================================================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "LiveVote_audienceVoterId_idx" ON "LiveVote"("audienceVoterId");
|
||||
|
||||
-- Foreign key: LiveVote.audienceVoterId -> AudienceVoter.id
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_audienceVoterId_fkey"
|
||||
FOREIGN KEY ("audienceVoterId") REFERENCES "AudienceVoter"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Unique constraint: sessionId + projectId + audienceVoterId
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_sessionId_projectId_audienceVoterId_key"
|
||||
UNIQUE ("sessionId", "projectId", "audienceVoterId");
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- SUMMARY:
|
||||
--
|
||||
-- LiveVotingSession new columns:
|
||||
-- - votingMode (TEXT, default 'simple')
|
||||
-- - criteriaJson (JSONB, nullable)
|
||||
-- - audienceVotingMode (TEXT, default 'disabled')
|
||||
-- - audienceMaxFavorites (INTEGER, default 3)
|
||||
-- - audienceRequireId (BOOLEAN, default false)
|
||||
-- - audienceVotingDuration (INTEGER, nullable)
|
||||
--
|
||||
-- LiveVote changes:
|
||||
-- - criterionScoresJson (JSONB, nullable) - new column
|
||||
-- - audienceVoterId (TEXT, nullable) - new column
|
||||
-- - userId changed from NOT NULL to nullable
|
||||
-- - New unique: (sessionId, projectId, audienceVoterId)
|
||||
-- - New index: audienceVoterId
|
||||
-- - New FK: audienceVoterId -> AudienceVoter(id)
|
||||
--
|
||||
-- New table: AudienceVoter
|
||||
-- - id, sessionId, token (unique), identifier, identifierType,
|
||||
-- ipAddress, userAgent, createdAt
|
||||
-- - FK: sessionId -> LiveVotingSession(id) CASCADE
|
||||
-- =============================================================================
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
|
||||
Reference in New Issue
Block a user