diff --git a/app/routes/admin.sports-seasons.$id.events.$eventId.server.ts b/app/routes/admin.sports-seasons.$id.events.$eventId.server.ts index 523877c..d05de6f 100644 --- a/app/routes/admin.sports-seasons.$id.events.$eventId.server.ts +++ b/app/routes/admin.sports-seasons.$id.events.$eventId.server.ts @@ -384,52 +384,39 @@ export async function action({ request, params }: Route.ActionArgs) { return { error: "Scoring event not found" }; } - if (scoringEvent.tournamentId) { - // Canonical path: translate season_participant.id → canonical participant.id - const spRows = allSeasonParticipants.filter((sp) => - incoming.some((r) => r.participantId === sp.id), - ); - const missingCanonical = spRows.filter((sp) => !sp.participantId); - if (missingCanonical.length > 0) { - return { - error: `Some season participants are not linked to canonical participants: ${missingCanonical.map((sp) => sp.name).join(", ")}`, - }; - } - - for (const row of incoming) { - const sp = spRows.find((s) => s.id === row.participantId); - if (!sp?.participantId) continue; - await upsertTournamentResult({ - tournamentId: scoringEvent.tournamentId, - participantId: sp.participantId, - placement: row.placement, - }); - } - - const syncReport = await syncTournamentResults(scoringEvent.tournamentId); + // Qualifying events always have a canonical tournament link (check + // constraint). Write results canonically and fan out. + if (!scoringEvent.tournamentId) { return { - success: `${incoming.length} result${incoming.length === 1 ? "" : "s"} saved canonically. Synced to ${syncReport.windowsSynced} window${syncReport.windowsSynced === 1 ? "" : "s"}${syncReport.windowsFailed > 0 ? ` (${syncReport.windowsFailed} failed)` : ""}.`, - syncReport, + error: + "This scoring event has no canonical tournament link — cannot save batch results. Contact a developer.", }; } - // Legacy direct-write path for non-canonical events (team sports, etc.). - const existingResults = await getEventResults(params.eventId); - const existingIds = new Set(existingResults.map((r) => r.seasonParticipantId)); - const newResults = filterNewResults(incoming, existingIds); - - if (newResults.length > 0) { - await createEventResultsBulk( - newResults.map((r) => ({ - scoringEventId: params.eventId, - participantId: r.participantId, - placement: r.placement, - })) - ); + const spRows = allSeasonParticipants.filter((sp) => + incoming.some((r) => r.participantId === sp.id), + ); + const missingCanonical = spRows.filter((sp) => !sp.participantId); + if (missingCanonical.length > 0) { + return { + error: `Some season participants are not linked to canonical participants: ${missingCanonical.map((sp) => sp.name).join(", ")}`, + }; } + for (const row of incoming) { + const sp = spRows.find((s) => s.id === row.participantId); + if (!sp?.participantId) continue; + await upsertTournamentResult({ + tournamentId: scoringEvent.tournamentId, + participantId: sp.participantId, + placement: row.placement, + }); + } + + const syncReport = await syncTournamentResults(scoringEvent.tournamentId); return { - success: `${newResults.length} result${newResults.length === 1 ? "" : "s"} saved${incoming.length - newResults.length > 0 ? ` (${incoming.length - newResults.length} duplicate${incoming.length - newResults.length === 1 ? "" : "s"} skipped)` : ""}.`, + success: `${incoming.length} result${incoming.length === 1 ? "" : "s"} saved canonically. Synced to ${syncReport.windowsSynced} window${syncReport.windowsSynced === 1 ? "" : "s"}${syncReport.windowsFailed > 0 ? ` (${syncReport.windowsFailed} failed)` : ""}.`, + syncReport, }; } catch (error) { logger.error("Error saving batch results:", error);