feat(finale): deliberation jury identity resolution, rankable projects, score-revision path, session sync

- submitVote resolves the caller's JuryGroupMember participant row server-side
  (was comparing JuryGroupMember id to User id — every juror got FORBIDDEN)
- getSessionWithVotes now includes category projects so the ranking form has
  data before finalize
- liveVoting.vote accepts any finale-ordered project (revision during
  deliberation); timed window still applies to the live project
- live.sendToScreens keeps LiveVotingSession.currentProjectId/status in sync

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt
2026-06-10 18:15:45 +02:00
parent 4e6904fa12
commit c9dc1bfabd
7 changed files with 229 additions and 18 deletions

View File

@@ -148,6 +148,20 @@ describe('phase transitions', () => {
})
})
describe('voting session sync', () => {
it('sendToScreens points the voting session at the project and activates it', async () => {
const session = await prisma.liveVotingSession.create({
data: { roundId: round.id, status: 'NOT_STARTED' },
})
await adminCaller.sendToScreens({ roundId: round.id, projectId: p1.id })
const updated = await prisma.liveVotingSession.findUniqueOrThrow({
where: { id: session.id },
})
expect(updated.currentProjectId).toBe(p1.id)
expect(updated.status).toBe('IN_PROGRESS')
})
})
describe('juror notes', () => {
it('saveNote upserts one note per (round, project, juror)', async () => {
await jurorCaller.saveNote({ roundId: round.id, projectId: p1.id, content: 'first draft' })