After every pick, recalculate draft eligibility for all teams and remove any queued participants whose sport is no longer eligible (e.g. a team queued a snooker player but just filled their last flex slot). Previously this was only caught lazily when autodraft fired, which could pause the draft or pick an unwanted player. - Add getAllQueuesForSeason to draft-queue.ts — fetches all queue rows for a season in one query (Map<teamId, QueueItem[]>) instead of N+1 per-team queries - Add pruneIneligibleQueueItems to draft-utils.ts — uses Promise.all for the four required data fetches, collects ineligible items in a single loop pass, warns on orphaned participant references - Call from both pick paths: executeAutoPick and draft.make-pick.ts - Emit queue-eligibility-pruned socket event per affected team so the client updates the queue UI in real time - Add 5 tests covering: single ineligible removal, all eligible (no-op), empty queues (no delete called, getTeamQueue never called), mixed queue (only ineligible item removed), and unknown participant (warn) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
117 lines
3.2 KiB
TypeScript
117 lines
3.2 KiB
TypeScript
import { database } from "~/database/context";
|
|
import * as schema from "~/database/schema";
|
|
import { eq, and, asc } from "drizzle-orm";
|
|
|
|
export async function addToQueue(data: {
|
|
seasonId: string;
|
|
teamId: string;
|
|
participantId: string;
|
|
queuePosition: number;
|
|
}) {
|
|
const db = database();
|
|
const [item] = await db.insert(schema.draftQueue).values(data).returning();
|
|
return item;
|
|
}
|
|
|
|
export async function removeFromQueue(queueId: string) {
|
|
const db = database();
|
|
await db.delete(schema.draftQueue).where(eq(schema.draftQueue.id, queueId));
|
|
}
|
|
|
|
export async function getTeamQueue(teamId: string, providedDb?: ReturnType<typeof database>) {
|
|
const db = providedDb || database();
|
|
return await db
|
|
.select()
|
|
.from(schema.draftQueue)
|
|
.where(eq(schema.draftQueue.teamId, teamId))
|
|
.orderBy(asc(schema.draftQueue.queuePosition));
|
|
}
|
|
|
|
export async function isParticipantInQueue(teamId: string, participantId: string): Promise<boolean> {
|
|
const db = database();
|
|
const existing = await db.query.draftQueue.findFirst({
|
|
where: and(
|
|
eq(schema.draftQueue.teamId, teamId),
|
|
eq(schema.draftQueue.participantId, participantId)
|
|
),
|
|
});
|
|
return !!existing;
|
|
}
|
|
|
|
export async function clearTeamQueue(teamId: string) {
|
|
const db = database();
|
|
await db.delete(schema.draftQueue).where(eq(schema.draftQueue.teamId, teamId));
|
|
}
|
|
|
|
export async function reorderQueue(teamId: string, participantIds: string[]) {
|
|
// Delete existing queue
|
|
await clearTeamQueue(teamId);
|
|
|
|
// Get season ID from first queue item (or we need to pass it)
|
|
// For now, we'll need to pass seasonId
|
|
return participantIds;
|
|
}
|
|
|
|
export async function reorderQueueWithSeason(
|
|
seasonId: string,
|
|
teamId: string,
|
|
participantIds: string[]
|
|
) {
|
|
// Delete existing queue
|
|
await clearTeamQueue(teamId);
|
|
|
|
// Insert new queue in order
|
|
const items = participantIds.map((participantId, index) => ({
|
|
seasonId,
|
|
teamId,
|
|
participantId,
|
|
queuePosition: index + 1,
|
|
}));
|
|
|
|
if (items.length > 0) {
|
|
const db = database();
|
|
await db.insert(schema.draftQueue).values(items);
|
|
}
|
|
}
|
|
|
|
export async function removeParticipantFromQueue(teamId: string, participantId: string) {
|
|
const db = database();
|
|
await db
|
|
.delete(schema.draftQueue)
|
|
.where(
|
|
and(
|
|
eq(schema.draftQueue.teamId, teamId),
|
|
eq(schema.draftQueue.participantId, participantId)
|
|
)
|
|
);
|
|
}
|
|
|
|
export async function getAllQueuesForSeason(
|
|
seasonId: string,
|
|
providedDb?: ReturnType<typeof database>
|
|
): Promise<Map<string, typeof schema.draftQueue.$inferSelect[]>> {
|
|
const db = providedDb || database();
|
|
const rows = await db
|
|
.select()
|
|
.from(schema.draftQueue)
|
|
.where(eq(schema.draftQueue.seasonId, seasonId))
|
|
.orderBy(asc(schema.draftQueue.queuePosition));
|
|
|
|
const byTeam = new Map<string, typeof schema.draftQueue.$inferSelect[]>();
|
|
for (const row of rows) {
|
|
const existing = byTeam.get(row.teamId);
|
|
if (existing) {
|
|
existing.push(row);
|
|
} else {
|
|
byTeam.set(row.teamId, [row]);
|
|
}
|
|
}
|
|
return byTeam;
|
|
}
|
|
|
|
export async function clearAllQueuesForSeason(seasonId: string) {
|
|
const db = database();
|
|
await db
|
|
.delete(schema.draftQueue)
|
|
.where(eq(schema.draftQueue.seasonId, seasonId));
|
|
}
|