diff --git a/prisma/migrations/20260225122717_add_performance_indexes/migration.sql b/prisma/migrations/20260225122717_add_performance_indexes/migration.sql new file mode 100644 index 0000000..b9a5759 --- /dev/null +++ b/prisma/migrations/20260225122717_add_performance_indexes/migration.sql @@ -0,0 +1,11 @@ +-- CreateIndex +CREATE INDEX "AuditLog_evaluationId_idx" ON "AuditLog"("evaluationId"); + +-- CreateIndex +CREATE INDEX "Evaluation_evaluatorId_idx" ON "Evaluation"("evaluatorId"); + +-- CreateIndex +CREATE INDEX "Evaluation_templateId_idx" ON "Evaluation"("templateId"); + +-- CreateIndex +CREATE INDEX "EvaluationShare_userId_idx" ON "EvaluationShare"("userId"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 837c1fe..03b92ca 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -66,6 +66,9 @@ model Evaluation { isPublic Boolean @default(false) // visible par tous (ex. démo) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + + @@index([evaluatorId]) + @@index([templateId]) } model EvaluationShare { @@ -77,6 +80,7 @@ model EvaluationShare { createdAt DateTime @default(now()) @@unique([evaluationId, userId]) + @@index([userId]) } model DimensionScore { @@ -106,4 +110,6 @@ model AuditLog { newValue String? userId String? createdAt DateTime @default(now()) + + @@index([evaluationId]) } diff --git a/src/actions/evaluations.ts b/src/actions/evaluations.ts index 67dfac4..e67e974 100644 --- a/src/actions/evaluations.ts +++ b/src/actions/evaluations.ts @@ -72,11 +72,12 @@ export async function createEvaluation(data: { }, }); - for (const dim of template.dimensions) { - await prisma.dimensionScore.create({ - data: { evaluationId: evaluation.id, dimensionId: dim.id }, - }); - } + await prisma.dimensionScore.createMany({ + data: template.dimensions.map((dim) => ({ + evaluationId: evaluation.id, + dimensionId: dim.id, + })), + }); revalidatePath("/dashboard"); return { success: true, data: { id: evaluation.id } }; @@ -177,30 +178,33 @@ export async function updateEvaluation(id: string, data: UpdateEvaluationInput): } if (dimensionScores && Array.isArray(dimensionScores)) { - for (const ds of dimensionScores) { - if (ds.dimensionId) { - await prisma.dimensionScore.upsert({ - where: { - evaluationId_dimensionId: { evaluationId: id, dimensionId: ds.dimensionId }, - }, - update: { - score: ds.score, - justification: ds.justification, - examplesObserved: ds.examplesObserved, - confidence: ds.confidence, - candidateNotes: ds.candidateNotes, - }, - create: { - evaluationId: id, - dimensionId: ds.dimensionId, - score: ds.score, - justification: ds.justification, - examplesObserved: ds.examplesObserved, - confidence: ds.confidence, - candidateNotes: ds.candidateNotes, - }, - }); - } + const validScores = dimensionScores.filter((ds) => ds.dimensionId); + if (validScores.length > 0) { + await prisma.$transaction( + validScores.map((ds) => + prisma.dimensionScore.upsert({ + where: { + evaluationId_dimensionId: { evaluationId: id, dimensionId: ds.dimensionId }, + }, + update: { + score: ds.score, + justification: ds.justification, + examplesObserved: ds.examplesObserved, + confidence: ds.confidence, + candidateNotes: ds.candidateNotes, + }, + create: { + evaluationId: id, + dimensionId: ds.dimensionId, + score: ds.score, + justification: ds.justification, + examplesObserved: ds.examplesObserved, + confidence: ds.confidence, + candidateNotes: ds.candidateNotes, + }, + }) + ) + ); } }