233 lines
7.3 KiB
TypeScript
233 lines
7.3 KiB
TypeScript
|
|
import { and, asc, eq, isNotNull, sql } from "drizzle-orm";
|
||
|
|
import { database } from "~/database/context";
|
||
|
|
import * as schema from "~/database/schema";
|
||
|
|
|
||
|
|
export type SeasonMatch = typeof schema.seasonMatches.$inferSelect;
|
||
|
|
export type MatchSubGame = typeof schema.matchSubGames.$inferSelect;
|
||
|
|
export type MatchStatus = (typeof schema.matchStatusEnum.enumValues)[number];
|
||
|
|
|
||
|
|
export interface UpsertSeasonMatchData {
|
||
|
|
sportsSeasonId: string;
|
||
|
|
scoringEventId?: string | null;
|
||
|
|
participant1Id?: string | null;
|
||
|
|
participant2Id?: string | null;
|
||
|
|
winnerId?: string | null;
|
||
|
|
participant1Score?: number | null;
|
||
|
|
participant2Score?: number | null;
|
||
|
|
matchStage?: number | null;
|
||
|
|
matchRound?: number | null;
|
||
|
|
matchday?: number | null;
|
||
|
|
isSeries?: boolean;
|
||
|
|
status: MatchStatus;
|
||
|
|
scheduledAt?: Date | null;
|
||
|
|
startedAt?: Date | null;
|
||
|
|
completedAt?: Date | null;
|
||
|
|
externalMatchId: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface UpsertMatchSubGameData {
|
||
|
|
seasonMatchId: string;
|
||
|
|
gameNumber: number;
|
||
|
|
gameLabel?: string | null;
|
||
|
|
participant1Score?: number | null;
|
||
|
|
participant2Score?: number | null;
|
||
|
|
winnerId?: string | null;
|
||
|
|
status: MatchStatus;
|
||
|
|
startedAt?: Date | null;
|
||
|
|
completedAt?: Date | null;
|
||
|
|
externalGameId?: string | null;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function upsertSeasonMatch(
|
||
|
|
data: UpsertSeasonMatchData
|
||
|
|
): Promise<SeasonMatch> {
|
||
|
|
const db = database();
|
||
|
|
const now = new Date();
|
||
|
|
const [result] = await db
|
||
|
|
.insert(schema.seasonMatches)
|
||
|
|
.values({
|
||
|
|
...data,
|
||
|
|
isSeries: data.isSeries ?? false,
|
||
|
|
updatedAt: now,
|
||
|
|
})
|
||
|
|
.onConflictDoUpdate({
|
||
|
|
target: schema.seasonMatches.externalMatchId,
|
||
|
|
targetWhere: isNotNull(schema.seasonMatches.externalMatchId),
|
||
|
|
set: {
|
||
|
|
participant1Id: sql`excluded.participant1_id`,
|
||
|
|
participant2Id: sql`excluded.participant2_id`,
|
||
|
|
winnerId: sql`excluded.winner_id`,
|
||
|
|
participant1Score: sql`excluded.participant1_score`,
|
||
|
|
participant2Score: sql`excluded.participant2_score`,
|
||
|
|
matchStage: sql`excluded.match_stage`,
|
||
|
|
matchRound: sql`excluded.match_round`,
|
||
|
|
matchday: sql`excluded.matchday`,
|
||
|
|
isSeries: sql`excluded.is_series`,
|
||
|
|
status: sql`excluded.status`,
|
||
|
|
scheduledAt: sql`excluded.scheduled_at`,
|
||
|
|
startedAt: sql`excluded.started_at`,
|
||
|
|
completedAt: sql`excluded.completed_at`,
|
||
|
|
updatedAt: now,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
.returning();
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function upsertSeasonMatchBulk(
|
||
|
|
records: UpsertSeasonMatchData[]
|
||
|
|
): Promise<SeasonMatch[]> {
|
||
|
|
if (records.length === 0) return [];
|
||
|
|
const db = database();
|
||
|
|
const now = new Date();
|
||
|
|
return await db
|
||
|
|
.insert(schema.seasonMatches)
|
||
|
|
.values(records.map((r) => ({ ...r, isSeries: r.isSeries ?? false, updatedAt: now })))
|
||
|
|
.onConflictDoUpdate({
|
||
|
|
target: schema.seasonMatches.externalMatchId,
|
||
|
|
targetWhere: isNotNull(schema.seasonMatches.externalMatchId),
|
||
|
|
set: {
|
||
|
|
participant1Id: sql`excluded.participant1_id`,
|
||
|
|
participant2Id: sql`excluded.participant2_id`,
|
||
|
|
winnerId: sql`excluded.winner_id`,
|
||
|
|
participant1Score: sql`excluded.participant1_score`,
|
||
|
|
participant2Score: sql`excluded.participant2_score`,
|
||
|
|
matchStage: sql`excluded.match_stage`,
|
||
|
|
matchRound: sql`excluded.match_round`,
|
||
|
|
matchday: sql`excluded.matchday`,
|
||
|
|
isSeries: sql`excluded.is_series`,
|
||
|
|
status: sql`excluded.status`,
|
||
|
|
scheduledAt: sql`excluded.scheduled_at`,
|
||
|
|
startedAt: sql`excluded.started_at`,
|
||
|
|
completedAt: sql`excluded.completed_at`,
|
||
|
|
updatedAt: now,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
.returning();
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function findSeasonMatchesBySportsSeasonId(
|
||
|
|
sportsSeasonId: string,
|
||
|
|
filters?: { status?: MatchStatus; matchStage?: number }
|
||
|
|
) {
|
||
|
|
const db = database();
|
||
|
|
return await db.query.seasonMatches.findMany({
|
||
|
|
where: and(
|
||
|
|
eq(schema.seasonMatches.sportsSeasonId, sportsSeasonId),
|
||
|
|
filters?.status ? eq(schema.seasonMatches.status, filters.status) : undefined,
|
||
|
|
filters?.matchStage !== undefined
|
||
|
|
? eq(schema.seasonMatches.matchStage, filters.matchStage)
|
||
|
|
: undefined
|
||
|
|
),
|
||
|
|
orderBy: [
|
||
|
|
asc(schema.seasonMatches.matchStage),
|
||
|
|
asc(schema.seasonMatches.matchRound),
|
||
|
|
asc(schema.seasonMatches.matchday),
|
||
|
|
asc(schema.seasonMatches.scheduledAt),
|
||
|
|
asc(schema.seasonMatches.createdAt),
|
||
|
|
],
|
||
|
|
with: {
|
||
|
|
participant1: true,
|
||
|
|
participant2: true,
|
||
|
|
winner: true,
|
||
|
|
subGames: { orderBy: [asc(schema.matchSubGames.gameNumber)] },
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function findSeasonMatchesByScoringEventId(scoringEventId: string) {
|
||
|
|
const db = database();
|
||
|
|
return await db.query.seasonMatches.findMany({
|
||
|
|
where: eq(schema.seasonMatches.scoringEventId, scoringEventId),
|
||
|
|
orderBy: [
|
||
|
|
asc(schema.seasonMatches.matchStage),
|
||
|
|
asc(schema.seasonMatches.matchRound),
|
||
|
|
asc(schema.seasonMatches.scheduledAt),
|
||
|
|
asc(schema.seasonMatches.createdAt),
|
||
|
|
],
|
||
|
|
with: {
|
||
|
|
participant1: true,
|
||
|
|
participant2: true,
|
||
|
|
winner: true,
|
||
|
|
subGames: { orderBy: [asc(schema.matchSubGames.gameNumber)] },
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function findSeasonMatchById(matchId: string) {
|
||
|
|
const db = database();
|
||
|
|
return await db.query.seasonMatches.findFirst({
|
||
|
|
where: eq(schema.seasonMatches.id, matchId),
|
||
|
|
with: {
|
||
|
|
participant1: true,
|
||
|
|
participant2: true,
|
||
|
|
winner: true,
|
||
|
|
subGames: { orderBy: [asc(schema.matchSubGames.gameNumber)] },
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function updateSeasonMatch(
|
||
|
|
matchId: string,
|
||
|
|
data: Partial<{
|
||
|
|
participant1Id: string | null;
|
||
|
|
participant2Id: string | null;
|
||
|
|
winnerId: string | null;
|
||
|
|
participant1Score: number | null;
|
||
|
|
participant2Score: number | null;
|
||
|
|
status: MatchStatus;
|
||
|
|
scheduledAt: Date | null;
|
||
|
|
startedAt: Date | null;
|
||
|
|
completedAt: Date | null;
|
||
|
|
}>
|
||
|
|
): Promise<SeasonMatch> {
|
||
|
|
const db = database();
|
||
|
|
const [result] = await db
|
||
|
|
.update(schema.seasonMatches)
|
||
|
|
.set({ ...data, updatedAt: new Date() })
|
||
|
|
.where(eq(schema.seasonMatches.id, matchId))
|
||
|
|
.returning();
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function deleteSeasonMatch(matchId: string): Promise<void> {
|
||
|
|
const db = database();
|
||
|
|
await db
|
||
|
|
.delete(schema.seasonMatches)
|
||
|
|
.where(eq(schema.seasonMatches.id, matchId));
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function upsertMatchSubGame(
|
||
|
|
data: UpsertMatchSubGameData
|
||
|
|
): Promise<MatchSubGame> {
|
||
|
|
const db = database();
|
||
|
|
const now = new Date();
|
||
|
|
const [result] = await db
|
||
|
|
.insert(schema.matchSubGames)
|
||
|
|
.values({ ...data, updatedAt: now })
|
||
|
|
.onConflictDoUpdate({
|
||
|
|
target: [schema.matchSubGames.seasonMatchId, schema.matchSubGames.gameNumber],
|
||
|
|
set: {
|
||
|
|
gameLabel: sql`excluded.game_label`,
|
||
|
|
participant1Score: sql`excluded.participant1_score`,
|
||
|
|
participant2Score: sql`excluded.participant2_score`,
|
||
|
|
winnerId: sql`excluded.winner_id`,
|
||
|
|
status: sql`excluded.status`,
|
||
|
|
startedAt: sql`excluded.started_at`,
|
||
|
|
completedAt: sql`excluded.completed_at`,
|
||
|
|
externalGameId: sql`excluded.external_game_id`,
|
||
|
|
updatedAt: now,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
.returning();
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function findMatchSubGamesByMatchId(matchId: string): Promise<MatchSubGame[]> {
|
||
|
|
const db = database();
|
||
|
|
return await db.query.matchSubGames.findMany({
|
||
|
|
where: eq(schema.matchSubGames.seasonMatchId, matchId),
|
||
|
|
orderBy: [asc(schema.matchSubGames.gameNumber)],
|
||
|
|
});
|
||
|
|
}
|