refactor: tech debt batch 2 — drop dead models, stale columns, schema cleanup
Schema: - Drop 4 dead models: OverrideAction, NotificationPolicy, AssignmentException, AdvancementRule - Drop 2 dead enums: OverrideReasonCode, AdvancementRuleType - Drop 3 stale columns: Project.roundId, ConflictOfInterest.roundId, Evaluation.version - Remove 3 back-relation fields from User, Assignment, Round Code: - Fix 6 COI queries in assignment.ts + 1 in juror-reassignment.ts (roundId filter → assignment.roundId after column drop) - Remove orphaned Project.roundId write in project.ts createProject - Remove advancementRules include from round.ts getById - Remove AdvancementRule from RoundWithRelations type - Clean up seed.ts (remove advancement rule seeding) - Clean up tests/helpers.ts (remove dead model cleanup) - Add TODO comments on user delete mutations (FK violation risk) Migration: 20260308000000_drop_dead_models_and_stale_columns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "AdvancementRule" DROP CONSTRAINT "AdvancementRule_roundId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "AssignmentException" DROP CONSTRAINT "AssignmentException_approvedById_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "AssignmentException" DROP CONSTRAINT "AssignmentException_assignmentId_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ConflictOfInterest" DROP COLUMN "roundId";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Evaluation" DROP COLUMN "version";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Project" DROP COLUMN "roundId";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "AdvancementRule";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "AssignmentException";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "NotificationPolicy";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "OverrideAction";
|
||||
|
||||
-- DropEnum
|
||||
DROP TYPE "AdvancementRuleType";
|
||||
|
||||
-- DropEnum
|
||||
DROP TYPE "OverrideReasonCode";
|
||||
@@ -134,13 +134,6 @@ enum PartnerType {
|
||||
OTHER
|
||||
}
|
||||
|
||||
enum OverrideReasonCode {
|
||||
DATA_CORRECTION
|
||||
POLICY_EXCEPTION
|
||||
JURY_CONFLICT
|
||||
SPONSOR_DECISION
|
||||
ADMIN_DISCRETION
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COMPETITION / ROUND ENGINE ENUMS
|
||||
@@ -179,13 +172,6 @@ enum ProjectRoundStateValue {
|
||||
WITHDRAWN
|
||||
}
|
||||
|
||||
enum AdvancementRuleType {
|
||||
AUTO_ADVANCE
|
||||
SCORE_THRESHOLD
|
||||
TOP_N
|
||||
ADMIN_SELECTION
|
||||
AI_RECOMMENDED
|
||||
}
|
||||
|
||||
enum CapMode {
|
||||
HARD
|
||||
@@ -431,7 +417,6 @@ model User {
|
||||
mentorFileComments MentorFileComment[] @relation("MentorFileCommentAuthor")
|
||||
resultLocksCreated ResultLock[] @relation("ResultLockCreator")
|
||||
resultUnlockEvents ResultUnlockEvent[] @relation("ResultUnlocker")
|
||||
assignmentExceptionsApproved AssignmentException[] @relation("AssignmentExceptionApprover")
|
||||
submissionPromotions SubmissionPromotionEvent[] @relation("SubmissionPromoter")
|
||||
deliberationReplacements DeliberationParticipant[] @relation("DeliberationReplacement")
|
||||
|
||||
@@ -563,7 +548,6 @@ model EvaluationForm {
|
||||
model Project {
|
||||
id String @id @default(cuid())
|
||||
programId String
|
||||
roundId String?
|
||||
status ProjectStatus @default(SUBMITTED)
|
||||
|
||||
// Core fields
|
||||
@@ -763,7 +747,6 @@ model Assignment {
|
||||
juryGroup JuryGroup? @relation(fields: [juryGroupId], references: [id], onDelete: SetNull)
|
||||
evaluation Evaluation?
|
||||
conflictOfInterest ConflictOfInterest?
|
||||
exceptions AssignmentException[]
|
||||
|
||||
@@unique([userId, projectId, roundId])
|
||||
@@index([roundId])
|
||||
@@ -790,11 +773,6 @@ model Evaluation {
|
||||
binaryDecision Boolean? // Yes/No for semi-finalist
|
||||
feedbackText String? @db.Text
|
||||
|
||||
// Versioning (currently unused - evaluations are updated in-place.
|
||||
// TODO: Implement proper versioning by creating new rows on re-submission
|
||||
// if version history is needed for audit purposes)
|
||||
version Int @default(1)
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -1729,7 +1707,6 @@ model ConflictOfInterest {
|
||||
assignmentId String @unique
|
||||
userId String
|
||||
projectId String
|
||||
roundId String? // Legacy — kept for historical data
|
||||
hasConflict Boolean @default(false)
|
||||
conflictType String? // "financial", "personal", "organizational", "other"
|
||||
description String? @db.Text
|
||||
@@ -2111,24 +2088,6 @@ model LiveProgressCursor {
|
||||
@@index([sessionId])
|
||||
}
|
||||
|
||||
model OverrideAction {
|
||||
id String @id @default(cuid())
|
||||
entityType String // ProjectRoundState, FilteringResult, AwardEligibility, etc.
|
||||
entityId String
|
||||
previousValue Json? @db.JsonB
|
||||
newValueJson Json @db.JsonB
|
||||
reasonCode OverrideReasonCode
|
||||
reasonText String? @db.Text
|
||||
actorId String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([entityType, entityId])
|
||||
@@index([actorId])
|
||||
@@index([reasonCode])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model DecisionAuditLog {
|
||||
id String @id @default(cuid())
|
||||
eventType String // stage.transitioned, routing.executed, filtering.completed, etc.
|
||||
@@ -2146,21 +2105,6 @@ model DecisionAuditLog {
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model NotificationPolicy {
|
||||
id String @id @default(cuid())
|
||||
eventType String @unique // stage.transitioned, filtering.completed, etc.
|
||||
channel String @default("EMAIL") // EMAIL, IN_APP, BOTH, NONE
|
||||
templateId String? // Optional reference to MessageTemplate
|
||||
isActive Boolean @default(true)
|
||||
configJson Json? @db.JsonB // Additional config (delay, batch, etc.)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([eventType])
|
||||
@@index([isActive])
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COMPETITION / ROUND ENGINE MODELS (NEW — coexists with Pipeline/Track/Stage)
|
||||
// =============================================================================
|
||||
@@ -2236,7 +2180,6 @@ model Round {
|
||||
juryGroup JuryGroup? @relation(fields: [juryGroupId], references: [id], onDelete: SetNull)
|
||||
submissionWindow SubmissionWindow? @relation(fields: [submissionWindowId], references: [id], onDelete: SetNull)
|
||||
projectRoundStates ProjectRoundState[]
|
||||
advancementRules AdvancementRule[]
|
||||
visibleSubmissionWindows RoundSubmissionVisibility[]
|
||||
assignmentIntents AssignmentIntent[]
|
||||
deliberationSessions DeliberationSession[]
|
||||
@@ -2295,24 +2238,6 @@ model ProjectRoundState {
|
||||
@@index([roundId, state])
|
||||
}
|
||||
|
||||
model AdvancementRule {
|
||||
id String @id @default(cuid())
|
||||
roundId String
|
||||
targetRoundId String?
|
||||
ruleType AdvancementRuleType
|
||||
configJson Json @db.JsonB
|
||||
isDefault Boolean @default(true)
|
||||
sortOrder Int @default(0)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
round Round @relation(fields: [roundId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([roundId, sortOrder])
|
||||
@@index([roundId])
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// JURY GROUP MODELS (NEW)
|
||||
// =============================================================================
|
||||
@@ -2489,22 +2414,6 @@ model AssignmentIntent {
|
||||
@@index([status])
|
||||
}
|
||||
|
||||
model AssignmentException {
|
||||
id String @id @default(cuid())
|
||||
assignmentId String
|
||||
reason String @db.Text
|
||||
overCapBy Int
|
||||
approvedById String
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
assignment Assignment @relation(fields: [assignmentId], references: [id], onDelete: Cascade)
|
||||
approvedBy User @relation("AssignmentExceptionApprover", fields: [approvedById], references: [id])
|
||||
|
||||
@@index([assignmentId])
|
||||
@@index([approvedById])
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// MENTORING WORKSPACE MODELS (NEW)
|
||||
// =============================================================================
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
RoundStatus,
|
||||
CapMode,
|
||||
JuryGroupMemberRole,
|
||||
AdvancementRuleType,
|
||||
} from '@prisma/client'
|
||||
import bcrypt from 'bcryptjs'
|
||||
// Inline default configs so seed has ZERO dependency on src/ (not available in Docker prod image)
|
||||
@@ -858,24 +857,6 @@ async function main() {
|
||||
}
|
||||
console.log(` ✓ ${rounds.length} rounds created (R1-R8)`)
|
||||
|
||||
// --- Advancement Rules (auto-advance between rounds) ---
|
||||
for (let i = 0; i < rounds.length - 1; i++) {
|
||||
await prisma.advancementRule.upsert({
|
||||
where: {
|
||||
roundId_sortOrder: { roundId: rounds[i].id, sortOrder: 0 },
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
roundId: rounds[i].id,
|
||||
ruleType: AdvancementRuleType.AUTO_ADVANCE,
|
||||
sortOrder: 0,
|
||||
targetRoundId: rounds[i + 1].id,
|
||||
configJson: {},
|
||||
},
|
||||
})
|
||||
}
|
||||
console.log(` ✓ ${rounds.length - 1} advancement rules created`)
|
||||
|
||||
// --- Assign all projects to intake round (COMPLETED, since intake is closed) ---
|
||||
const intakeRound = rounds[0]
|
||||
const allProjects = await prisma.project.findMany({
|
||||
|
||||
Reference in New Issue
Block a user