feat: finalist.editAttendees with cutoff and diff-based update

Team-lead-only mutation that replaces the AttendingMember roster on a
CONFIRMED finalist confirmation. Diffs the requested user list against
existing rows: kept rows are updated in place (preserving FlightDetail),
removed rows are deleted, added rows are created. Enforces:
  - team-lead role
  - CONFIRMED status
  - defaultAttendeeCap
  - team-membership of every supplied userId
  - cutoff = LIVE_FINAL.windowOpenAt − attendeeEditCutoffHours (default 48)

Audit-logged as FINALIST_EDIT_ATTENDEES with the diff payload.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt
2026-04-28 18:50:52 +02:00
parent 3d8aab46f1
commit 5b642c3d50
3 changed files with 465 additions and 2 deletions

View File

@@ -53,7 +53,7 @@ export async function createTestUser(
// ─── Program Factory ───────────────────────────────────────────────────────
export async function createTestProgram(
overrides: Partial<{ name: string; year: number }> = {},
overrides: Partial<{ name: string; year: number; defaultAttendeeCap: number }> = {},
) {
const id = uid('prog')
return prisma.program.create({
@@ -62,6 +62,9 @@ export async function createTestProgram(
name: overrides.name ?? `Test Program ${id}`,
year: overrides.year ?? 2026,
status: 'ACTIVE',
...(overrides.defaultAttendeeCap !== undefined
? { defaultAttendeeCap: overrides.defaultAttendeeCap }
: {}),
},
})
}