feat(final-docs): finalist document review service + procedure with finale-access gate

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt
2026-06-09 15:36:59 +02:00
parent b0a0a71cfe
commit e9e072dda7
3 changed files with 128 additions and 1 deletions

View File

@@ -1,4 +1,5 @@
import { describe, it, expect, afterAll } from 'vitest'
import { TRPCError } from '@trpc/server'
import { prisma } from '../setup'
import {
createTestProgram,
@@ -15,6 +16,7 @@ import {
sendManualFinalDocReminders,
} from '@/server/services/final-documents'
import * as applicantRouter from '@/server/routers/applicant'
import * as finalistRouter from '@/server/routers/finalist'
import { createCaller } from '../setup'
const programIds: string[] = []
@@ -163,3 +165,47 @@ describe('sendManualFinalDocReminders', () => {
expect(notif).not.toBeNull()
})
})
describe('finalist.listReviewDocuments', () => {
const localPrograms: string[] = []
const localUsers: string[] = []
afterAll(async () => { for (const id of localPrograms) await cleanupTestData(id, localUsers) })
async function setup() {
const program = await createTestProgram()
localPrograms.push(program.id)
const comp = await createTestCompetition(program.id, { status: 'ACTIVE' })
const jg = await prisma.juryGroup.create({ data: { id: uid('jg'), competitionId: comp.id, name: 'Finals Jury', slug: uid('jg') } })
const round = await createTestRound(comp.id, { roundType: 'LIVE_FINAL', status: 'ROUND_ACTIVE', sortOrder: 6, windowCloseAt: new Date(Date.now() + 86_400_000) })
await prisma.round.update({ where: { id: round.id }, data: { juryGroupId: jg.id } })
await prisma.fileRequirement.create({ data: { id: uid('req'), roundId: round.id, name: 'Executive Summary', acceptedMimeTypes: ['application/pdf'], isRequired: true, sortOrder: 1 } })
const project = await createTestProject(program.id, { competitionCategory: 'STARTUP' })
await createTestProjectRoundState(project.id, round.id)
return { program, comp, jg, round, project }
}
it('admin sees all finalist teams', async () => {
const { program } = await setup()
const admin = await createTestUser('PROGRAM_ADMIN'); localUsers.push(admin.id)
const caller = createCaller(finalistRouter.finalistRouter, admin)
const result = await caller.listReviewDocuments({ programId: program.id })
expect(result.teams).toHaveLength(1)
expect(result.totalCount).toBe(1)
})
it('a finals jury-group member is allowed', async () => {
const { program, jg } = await setup()
const juror = await createTestUser('JURY_MEMBER'); localUsers.push(juror.id)
await prisma.juryGroupMember.create({ data: { juryGroupId: jg.id, userId: juror.id, role: 'MEMBER' } })
const caller = createCaller(finalistRouter.finalistRouter, juror)
const result = await caller.listReviewDocuments({ programId: program.id })
expect(result.teams).toHaveLength(1)
})
it('a non-finals jury member is forbidden', async () => {
const { program } = await setup()
const juror = await createTestUser('JURY_MEMBER'); localUsers.push(juror.id)
const caller = createCaller(finalistRouter.finalistRouter, juror)
await expect(caller.listReviewDocuments({ programId: program.id })).rejects.toThrow(TRPCError)
})
})