101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
|
|
import { database } from "~/database/context";
|
||
|
|
import * as schema from "~/database/schema";
|
||
|
|
import { eq, and } from "drizzle-orm";
|
||
|
|
import type { FetchedStandingsRecord } from "~/services/standings-sync/types";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Upsert a pending mapping for an unmatched team from a standings sync.
|
||
|
|
* Uses onConflictDoUpdate so re-syncing refreshes the standing data.
|
||
|
|
*/
|
||
|
|
export async function upsertPendingStandingsMapping(
|
||
|
|
sportsSeasonId: string,
|
||
|
|
record: FetchedStandingsRecord,
|
||
|
|
providedDb?: ReturnType<typeof database>
|
||
|
|
) {
|
||
|
|
const db = providedDb || database();
|
||
|
|
|
||
|
|
const [row] = await db
|
||
|
|
.insert(schema.pendingStandingsMappings)
|
||
|
|
.values({
|
||
|
|
sportsSeasonId,
|
||
|
|
externalTeamId: record.externalTeamId,
|
||
|
|
teamName: record.teamName,
|
||
|
|
standingData: record as unknown as Record<string, unknown>,
|
||
|
|
})
|
||
|
|
.onConflictDoUpdate({
|
||
|
|
target: [
|
||
|
|
schema.pendingStandingsMappings.sportsSeasonId,
|
||
|
|
schema.pendingStandingsMappings.externalTeamId,
|
||
|
|
],
|
||
|
|
set: {
|
||
|
|
teamName: record.teamName,
|
||
|
|
standingData: record as unknown as Record<string, unknown>,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
.returning();
|
||
|
|
|
||
|
|
return row;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Bulk upsert pending mappings for all unmatched teams in a sync.
|
||
|
|
*/
|
||
|
|
export async function upsertPendingStandingsMappings(
|
||
|
|
sportsSeasonId: string,
|
||
|
|
records: FetchedStandingsRecord[],
|
||
|
|
providedDb?: ReturnType<typeof database>
|
||
|
|
) {
|
||
|
|
const db = providedDb || database();
|
||
|
|
return Promise.all(records.map((r) => upsertPendingStandingsMapping(sportsSeasonId, r, db)));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get all pending mappings for a sports season (awaiting admin resolution).
|
||
|
|
*/
|
||
|
|
export async function getPendingStandingsMappings(
|
||
|
|
sportsSeasonId: string,
|
||
|
|
providedDb?: ReturnType<typeof database>
|
||
|
|
) {
|
||
|
|
const db = providedDb || database();
|
||
|
|
|
||
|
|
return db.query.pendingStandingsMappings.findMany({
|
||
|
|
where: eq(schema.pendingStandingsMappings.sportsSeasonId, sportsSeasonId),
|
||
|
|
orderBy: schema.pendingStandingsMappings.teamName,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Delete a resolved pending mapping by its externalTeamId.
|
||
|
|
*/
|
||
|
|
export async function deletePendingStandingsMapping(
|
||
|
|
sportsSeasonId: string,
|
||
|
|
externalTeamId: string,
|
||
|
|
providedDb?: ReturnType<typeof database>
|
||
|
|
) {
|
||
|
|
const db = providedDb || database();
|
||
|
|
|
||
|
|
await db
|
||
|
|
.delete(schema.pendingStandingsMappings)
|
||
|
|
.where(
|
||
|
|
and(
|
||
|
|
eq(schema.pendingStandingsMappings.sportsSeasonId, sportsSeasonId),
|
||
|
|
eq(schema.pendingStandingsMappings.externalTeamId, externalTeamId)
|
||
|
|
)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Delete all pending mappings for a sports season.
|
||
|
|
* Used when manually clearing the queue.
|
||
|
|
*/
|
||
|
|
export async function deleteAllPendingStandingsMappings(
|
||
|
|
sportsSeasonId: string,
|
||
|
|
providedDb?: ReturnType<typeof database>
|
||
|
|
) {
|
||
|
|
const db = providedDb || database();
|
||
|
|
|
||
|
|
await db
|
||
|
|
.delete(schema.pendingStandingsMappings)
|
||
|
|
.where(eq(schema.pendingStandingsMappings.sportsSeasonId, sportsSeasonId));
|
||
|
|
}
|