2026-02-14 15:26:42 +01:00
|
|
|
import { prisma } from '@/lib/prisma'
|
2026-02-17 19:53:20 +01:00
|
|
|
import { aiInterpretCriteria } from './ai-award-eligibility'
|
2026-02-14 15:26:42 +01:00
|
|
|
|
|
|
|
|
const BATCH_SIZE = 20
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Process eligibility for an award in the background.
|
|
|
|
|
* Updates progress in the database as it goes so the frontend can poll.
|
|
|
|
|
*/
|
|
|
|
|
export async function processEligibilityJob(
|
|
|
|
|
awardId: string,
|
|
|
|
|
includeSubmitted: boolean,
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
userId: string,
|
|
|
|
|
filteringRoundId?: string
|
2026-02-14 15:26:42 +01:00
|
|
|
): Promise<void> {
|
|
|
|
|
try {
|
|
|
|
|
// Mark job as PROCESSING
|
|
|
|
|
const award = await prisma.specialAward.findUniqueOrThrow({
|
|
|
|
|
where: { id: awardId },
|
|
|
|
|
include: { program: true },
|
|
|
|
|
})
|
|
|
|
|
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
// Get projects — scoped to filtering round PASSED projects if provided
|
|
|
|
|
let projects: Array<{
|
|
|
|
|
id: string
|
|
|
|
|
title: string
|
|
|
|
|
description: string | null
|
|
|
|
|
competitionCategory: string | null
|
|
|
|
|
country: string | null
|
|
|
|
|
geographicZone: string | null
|
|
|
|
|
tags: string[]
|
|
|
|
|
oceanIssue: string | null
|
|
|
|
|
}>
|
2026-02-14 15:26:42 +01:00
|
|
|
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
if (filteringRoundId) {
|
|
|
|
|
// Scope to projects that PASSED filtering in the specified round
|
|
|
|
|
const passedResults = await prisma.filteringResult.findMany({
|
|
|
|
|
where: { roundId: filteringRoundId, outcome: 'PASSED' },
|
|
|
|
|
select: { projectId: true },
|
|
|
|
|
})
|
|
|
|
|
const passedIds = passedResults.map((r) => r.projectId)
|
|
|
|
|
|
|
|
|
|
if (passedIds.length === 0) {
|
|
|
|
|
await prisma.specialAward.update({
|
|
|
|
|
where: { id: awardId },
|
|
|
|
|
data: {
|
|
|
|
|
eligibilityJobStatus: 'COMPLETED',
|
|
|
|
|
eligibilityJobTotal: 0,
|
|
|
|
|
eligibilityJobDone: 0,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
projects = await prisma.project.findMany({
|
|
|
|
|
where: {
|
|
|
|
|
id: { in: passedIds },
|
|
|
|
|
programId: award.programId,
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
title: true,
|
|
|
|
|
description: true,
|
|
|
|
|
competitionCategory: true,
|
|
|
|
|
country: true,
|
|
|
|
|
geographicZone: true,
|
|
|
|
|
tags: true,
|
|
|
|
|
oceanIssue: true,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
const statusFilter = includeSubmitted
|
|
|
|
|
? (['SUBMITTED', 'ELIGIBLE', 'ASSIGNED', 'SEMIFINALIST', 'FINALIST'] as const)
|
|
|
|
|
: (['ELIGIBLE', 'ASSIGNED', 'SEMIFINALIST', 'FINALIST'] as const)
|
|
|
|
|
|
|
|
|
|
projects = await prisma.project.findMany({
|
|
|
|
|
where: {
|
|
|
|
|
programId: award.programId,
|
|
|
|
|
status: { in: [...statusFilter] },
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
title: true,
|
|
|
|
|
description: true,
|
|
|
|
|
competitionCategory: true,
|
|
|
|
|
country: true,
|
|
|
|
|
geographicZone: true,
|
|
|
|
|
tags: true,
|
|
|
|
|
oceanIssue: true,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
2026-02-14 15:26:42 +01:00
|
|
|
|
|
|
|
|
if (projects.length === 0) {
|
|
|
|
|
await prisma.specialAward.update({
|
|
|
|
|
where: { id: awardId },
|
|
|
|
|
data: {
|
|
|
|
|
eligibilityJobStatus: 'COMPLETED',
|
|
|
|
|
eligibilityJobTotal: 0,
|
|
|
|
|
eligibilityJobDone: 0,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await prisma.specialAward.update({
|
|
|
|
|
where: { id: awardId },
|
|
|
|
|
data: {
|
|
|
|
|
eligibilityJobStatus: 'PROCESSING',
|
|
|
|
|
eligibilityJobTotal: projects.length,
|
|
|
|
|
eligibilityJobDone: 0,
|
|
|
|
|
eligibilityJobError: null,
|
|
|
|
|
eligibilityJobStarted: new Date(),
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
2026-02-17 19:53:20 +01:00
|
|
|
// AI interpretation (if criteria text exists AND AI eligibility is enabled)
|
2026-02-14 15:26:42 +01:00
|
|
|
// Process in batches to avoid timeouts
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
let aiResults: Map<string, { eligible: boolean; confidence: number; qualityScore: number; reasoning: string }> | undefined
|
2026-02-14 15:26:42 +01:00
|
|
|
|
|
|
|
|
if (award.criteriaText && award.useAiEligibility) {
|
|
|
|
|
aiResults = new Map()
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < projects.length; i += BATCH_SIZE) {
|
|
|
|
|
const batch = projects.slice(i, i + BATCH_SIZE)
|
|
|
|
|
const aiEvals = await aiInterpretCriteria(award.criteriaText, batch)
|
|
|
|
|
|
|
|
|
|
for (const e of aiEvals) {
|
|
|
|
|
aiResults.set(e.projectId, {
|
|
|
|
|
eligible: e.eligible,
|
|
|
|
|
confidence: e.confidence,
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
qualityScore: e.qualityScore,
|
2026-02-14 15:26:42 +01:00
|
|
|
reasoning: e.reasoning,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update progress
|
|
|
|
|
await prisma.specialAward.update({
|
|
|
|
|
where: { id: awardId },
|
|
|
|
|
data: {
|
|
|
|
|
eligibilityJobDone: Math.min(i + BATCH_SIZE, projects.length),
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// No AI needed, mark all as done
|
|
|
|
|
await prisma.specialAward.update({
|
|
|
|
|
where: { id: awardId },
|
|
|
|
|
data: { eligibilityJobDone: projects.length },
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 19:53:20 +01:00
|
|
|
// Combine results
|
2026-02-14 15:26:42 +01:00
|
|
|
const eligibilities = projects.map((project) => {
|
|
|
|
|
const aiEval = aiResults?.get(project.id)
|
2026-02-17 19:53:20 +01:00
|
|
|
const eligible = aiEval?.eligible ?? true
|
|
|
|
|
const method = aiResults ? 'AUTO' : 'MANUAL'
|
2026-02-14 15:26:42 +01:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
projectId: project.id,
|
|
|
|
|
eligible,
|
|
|
|
|
method,
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
qualityScore: aiEval?.qualityScore ?? null,
|
2026-02-14 15:26:42 +01:00
|
|
|
aiReasoningJson: aiEval
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
? { confidence: aiEval.confidence, qualityScore: aiEval.qualityScore, reasoning: aiEval.reasoning }
|
2026-02-14 15:26:42 +01:00
|
|
|
: null,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Upsert eligibilities
|
|
|
|
|
await prisma.$transaction(
|
|
|
|
|
eligibilities.map((e) =>
|
|
|
|
|
prisma.awardEligibility.upsert({
|
|
|
|
|
where: {
|
|
|
|
|
awardId_projectId: {
|
|
|
|
|
awardId,
|
|
|
|
|
projectId: e.projectId,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
create: {
|
|
|
|
|
awardId,
|
|
|
|
|
projectId: e.projectId,
|
|
|
|
|
eligible: e.eligible,
|
|
|
|
|
method: e.method as 'AUTO' | 'MANUAL',
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
qualityScore: e.qualityScore,
|
2026-02-14 15:26:42 +01:00
|
|
|
aiReasoningJson: e.aiReasoningJson ?? undefined,
|
|
|
|
|
},
|
|
|
|
|
update: {
|
|
|
|
|
eligible: e.eligible,
|
|
|
|
|
method: e.method as 'AUTO' | 'MANUAL',
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
qualityScore: e.qualityScore,
|
2026-02-14 15:26:42 +01:00
|
|
|
aiReasoningJson: e.aiReasoningJson ?? undefined,
|
|
|
|
|
overriddenBy: null,
|
|
|
|
|
overriddenAt: null,
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
shortlisted: false,
|
|
|
|
|
confirmedAt: null,
|
|
|
|
|
confirmedBy: null,
|
2026-02-14 15:26:42 +01:00
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
Fix AI filtering bugs, add special award shortlist integration
Part 1 - Bug Fixes:
- Fix toProjectWithRelations() stripping file fields needed by AI (detectedLang, textContent, etc.)
- Fix parseAIData() reading flat when aiScreeningJson is nested under rule ID
- Fix getAIConfidenceScore() with same nesting issue (always returned 0)
Part 2 - Special Award Track Integration:
- Add shortlistSize to SpecialAward, qualityScore/shortlisted/confirmed fields to AwardEligibility
- Add specialAwardId to Round for award-owned rounds
- Update AI eligibility service to return qualityScore (0-100) for ranking
- Update eligibility job with filteringRoundId scoping and auto-shortlist top N
- Add 8 new specialAward router procedures (listForRound, runEligibilityForRound,
listShortlist, toggleShortlisted, confirmShortlist, listRounds, createRound, deleteRound)
- Create award-shortlist.tsx component with ranked table, shortlist checkboxes, confirm dialog
- Add "Special Award Tracks" section to filtering dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:38:31 +01:00
|
|
|
// Auto-shortlist top N eligible projects by qualityScore
|
|
|
|
|
const shortlistSize = award.shortlistSize ?? 10
|
|
|
|
|
const topEligible = eligibilities
|
|
|
|
|
.filter((e) => e.eligible && e.qualityScore != null)
|
|
|
|
|
.sort((a, b) => (b.qualityScore ?? 0) - (a.qualityScore ?? 0))
|
|
|
|
|
.slice(0, shortlistSize)
|
|
|
|
|
|
|
|
|
|
if (topEligible.length > 0) {
|
|
|
|
|
await prisma.$transaction(
|
|
|
|
|
topEligible.map((e) =>
|
|
|
|
|
prisma.awardEligibility.update({
|
|
|
|
|
where: {
|
|
|
|
|
awardId_projectId: {
|
|
|
|
|
awardId,
|
|
|
|
|
projectId: e.projectId,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
data: { shortlisted: true },
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 15:26:42 +01:00
|
|
|
// Mark as completed
|
|
|
|
|
await prisma.specialAward.update({
|
|
|
|
|
where: { id: awardId },
|
|
|
|
|
data: {
|
|
|
|
|
eligibilityJobStatus: 'COMPLETED',
|
|
|
|
|
eligibilityJobDone: projects.length,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// Mark as failed
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
|
|
|
try {
|
|
|
|
|
await prisma.specialAward.update({
|
|
|
|
|
where: { id: awardId },
|
|
|
|
|
data: {
|
|
|
|
|
eligibilityJobStatus: 'FAILED',
|
|
|
|
|
eligibilityJobError: errorMessage,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
} catch {
|
|
|
|
|
// If we can't even update the status, log and give up
|
|
|
|
|
console.error('Failed to update eligibility job status:', error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|