brackt/app/models/canonical-golf-skills.ts
Chris Parsons cedeb844e3 Canonical golf skills migration + copy participants feature
Migrate participant_golf_skills from per-season to canonical table (one
row per real-world player), mirroring the existing participant_surface_elos
pattern. Adds admin UI to copy participants between same-sport seasons with
EV stubs, transactional writes, and comprehensive tests.
2026-05-02 09:47:54 -07:00

42 lines
1.3 KiB
TypeScript

import { eq } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
export type CanonicalGolfSkills = typeof schema.participantGolfSkills.$inferSelect;
export type NewCanonicalGolfSkills = typeof schema.participantGolfSkills.$inferInsert;
export async function upsertCanonicalGolfSkills(
data: NewCanonicalGolfSkills,
): Promise<CanonicalGolfSkills> {
if (!data.participantId) {
throw new Error("participantId is required");
}
const db = database();
const [result] = await db
.insert(schema.participantGolfSkills)
.values(data)
.onConflictDoUpdate({
target: [schema.participantGolfSkills.participantId],
set: {
sgTotal: data.sgTotal,
datagolfRank: data.datagolfRank,
mastersOdds: data.mastersOdds,
usOpenOdds: data.usOpenOdds,
openChampionshipOdds: data.openChampionshipOdds,
pgaChampionshipOdds: data.pgaChampionshipOdds,
updatedAt: new Date(),
},
})
.returning();
return result;
}
export async function getCanonicalGolfSkills(
participantId: string,
): Promise<CanonicalGolfSkills | null> {
const db = database();
return await db.query.participantGolfSkills.findFirst({
where: eq(schema.participantGolfSkills.participantId, participantId),
}) ?? null;
}