Fix COI audit log always saying conflict + fix boolean criteria submission
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m19s
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m19s
1. COI audit log: The declareCOI mutation always logged action 'COI_DECLARED' regardless of whether the user clicked "No Conflict" or "Yes, I Have a Conflict". Now uses 'COI_NO_CONFLICT' when hasConflict is false, showing "confirmed no conflict of interest" in the audit trail. 2. Evaluation submission: The requireAllCriteriaScored validation only accepted numeric values (typeof === 'number'), but boolean criteria (yes/no questions) store true/false. This caused jurors to get "Missing scores for criteria: criterion-xxx" errors even after completing all fields. Now correctly validates boolean criteria with typeof === 'boolean'. Also improved the error message to show criterion labels instead of cryptic IDs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -237,18 +237,22 @@ export const evaluationRouter = router({
|
||||
select: { criteriaJson: true },
|
||||
})
|
||||
if (evalForm?.criteriaJson) {
|
||||
const criteria = evalForm.criteriaJson as Array<{ id: string; type?: string; required?: boolean }>
|
||||
const criteria = evalForm.criteriaJson as Array<{ id: string; label?: string; type?: string; required?: boolean }>
|
||||
const scorableCriteria = criteria.filter(
|
||||
(c) => c.type !== 'section_header' && c.type !== 'text' && c.required !== false
|
||||
)
|
||||
const scores = data.criterionScoresJson as Record<string, unknown> | undefined
|
||||
const missingCriteria = scorableCriteria.filter(
|
||||
(c) => !scores || typeof scores[c.id] !== 'number'
|
||||
)
|
||||
const missingCriteria = scorableCriteria.filter((c) => {
|
||||
if (!scores) return true
|
||||
const val = scores[c.id]
|
||||
// Boolean criteria store true/false, numeric criteria store numbers
|
||||
if (c.type === 'boolean') return typeof val !== 'boolean'
|
||||
return typeof val !== 'number'
|
||||
})
|
||||
if (missingCriteria.length > 0) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: `Missing scores for criteria: ${missingCriteria.map((c) => c.id).join(', ')}`,
|
||||
message: `Missing scores for criteria: ${missingCriteria.map((c) => c.label || c.id).join(', ')}`,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -523,7 +527,7 @@ export const evaluationRouter = router({
|
||||
await logAudit({
|
||||
prisma: ctx.prisma,
|
||||
userId: ctx.user.id,
|
||||
action: 'COI_DECLARED',
|
||||
action: input.hasConflict ? 'COI_DECLARED' : 'COI_NO_CONFLICT',
|
||||
entityType: 'ConflictOfInterest',
|
||||
entityId: coi.id,
|
||||
detailsJson: {
|
||||
|
||||
Reference in New Issue
Block a user