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:
@@ -39,6 +39,7 @@ export function formatAction(action: string, entityType: string | null): string
|
|||||||
DELETE_OWN_ACCOUNT: 'deleted their account',
|
DELETE_OWN_ACCOUNT: 'deleted their account',
|
||||||
EVALUATION_SUBMITTED: 'submitted an evaluation',
|
EVALUATION_SUBMITTED: 'submitted an evaluation',
|
||||||
COI_DECLARED: 'declared a conflict of interest',
|
COI_DECLARED: 'declared a conflict of interest',
|
||||||
|
COI_NO_CONFLICT: 'confirmed no conflict of interest',
|
||||||
COI_REVIEWED: 'reviewed a COI declaration',
|
COI_REVIEWED: 'reviewed a COI declaration',
|
||||||
REMINDERS_TRIGGERED: 'triggered evaluation reminders',
|
REMINDERS_TRIGGERED: 'triggered evaluation reminders',
|
||||||
DISCUSSION_COMMENT_ADDED: 'added a discussion comment',
|
DISCUSSION_COMMENT_ADDED: 'added a discussion comment',
|
||||||
|
|||||||
@@ -237,18 +237,22 @@ export const evaluationRouter = router({
|
|||||||
select: { criteriaJson: true },
|
select: { criteriaJson: true },
|
||||||
})
|
})
|
||||||
if (evalForm?.criteriaJson) {
|
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(
|
const scorableCriteria = criteria.filter(
|
||||||
(c) => c.type !== 'section_header' && c.type !== 'text' && c.required !== false
|
(c) => c.type !== 'section_header' && c.type !== 'text' && c.required !== false
|
||||||
)
|
)
|
||||||
const scores = data.criterionScoresJson as Record<string, unknown> | undefined
|
const scores = data.criterionScoresJson as Record<string, unknown> | undefined
|
||||||
const missingCriteria = scorableCriteria.filter(
|
const missingCriteria = scorableCriteria.filter((c) => {
|
||||||
(c) => !scores || typeof scores[c.id] !== 'number'
|
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) {
|
if (missingCriteria.length > 0) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: 'BAD_REQUEST',
|
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({
|
await logAudit({
|
||||||
prisma: ctx.prisma,
|
prisma: ctx.prisma,
|
||||||
userId: ctx.user.id,
|
userId: ctx.user.id,
|
||||||
action: 'COI_DECLARED',
|
action: input.hasConflict ? 'COI_DECLARED' : 'COI_NO_CONFLICT',
|
||||||
entityType: 'ConflictOfInterest',
|
entityType: 'ConflictOfInterest',
|
||||||
entityId: coi.id,
|
entityId: coi.id,
|
||||||
detailsJson: {
|
detailsJson: {
|
||||||
|
|||||||
Reference in New Issue
Block a user