Fix 5 code review issues in sport-based template conversion
Some checks failed
🚀 Deploy / 🧪 Test (pull_request) Successful in 3m11s
🚀 Deploy / ʦ🔍 Typecheck & Lint (pull_request) Failing after 51s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped

- Migration (0114): TRUNCATE season_template_sports before adding NOT NULL sport_id
  column to prevent failure on non-empty tables
- findDraftableSportsSeasonBySportId: add orderBy(year DESC, draftOn DESC) so the
  newest season is returned deterministically when multiple draft windows overlap
- leagues/new.tsx loader: build a Map from the already-fetched allSportsSeasons
  instead of firing N×M per-sport DB queries (eliminates ~30 redundant queries)
- schema: add UNIQUE(templateId, sportId) on season_template_sports to prevent
  duplicate sport entries via concurrent requests
- schema: add UNIQUE(name) on season_templates so import merge-mode lookup by
  name is unambiguous (migration 0115)

https://claude.ai/code/session_01CoRLHERakMncbPs877izvw
This commit is contained in:
Claude 2026-06-04 18:14:14 +00:00
parent 5cea6fd9b5
commit 553c565951
No known key found for this signature in database
7 changed files with 6251 additions and 11 deletions

View file

@ -162,6 +162,7 @@ export async function findDraftableSportsSeasonBySportId(sportId: string) {
gte(ss.draftOff, today),
isNull(ss.fantasySeasonId)
),
orderBy: (ss, { desc }) => [desc(ss.year), desc(ss.draftOn)],
with: {
sport: true,
},

View file

@ -11,7 +11,7 @@ import { createSeason } from "~/models/season";
import { linkMultipleSportsToSeason } from "~/models/season-sport";
import { createManyTeams } from "~/models/team";
import { findActiveSeasonTemplates, findSeasonTemplateWithSports } from "~/models/season-template";
import { findDraftableSportsSeasons, findDraftableSportsSeasonBySportId } from "~/models/sports-season";
import { findDraftableSportsSeasons } from "~/models/sports-season";
import { findUserById, updateUser } from "~/models/user";
import { generateUniqueTeamNames, prependOwnerToTeamName } from "~/utils/team-names";
import { format } from "date-fns";
@ -103,19 +103,18 @@ export async function loader(args: Route.LoaderArgs) {
const templates = await findActiveSeasonTemplates();
const allSportsSeasons = await findDraftableSportsSeasons();
const draftableSeasonBySportId = new Map(
allSportsSeasons.map((s) => [s.sportId, s])
);
const templatesWithSports = await Promise.all(
templates.map(async (template) => {
const t = await findSeasonTemplateWithSports(template.id);
const resolvedSeasons = await Promise.all(
(t?.seasonTemplateSports ?? []).map((ts: { sportId: string }) =>
findDraftableSportsSeasonBySportId(ts.sportId)
)
);
return {
...template,
sportsSeasonIds: resolvedSeasons
.filter((s): s is NonNullable<typeof s> => s != null)
.map((s) => s.id),
sportsSeasonIds: (t?.seasonTemplateSports ?? [])
.map((ts: { sportId: string }) => draftableSeasonBySportId.get(ts.sportId)?.id)
.filter((id): id is string => id != null),
};
})
);

View file

@ -193,7 +193,9 @@ export const seasonTemplates = pgTable("season_templates", {
isActive: boolean("is_active").notNull().default(true),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
}, (t) => ({
uniqueName: uniqueIndex("season_templates_name_unique").on(t.name),
}));
export const seasons = pgTable("seasons", {
id: uuid("id").primaryKey().defaultRandom(),
@ -570,7 +572,9 @@ export const seasonTemplateSports = pgTable("season_template_sports", {
.notNull()
.references(() => sports.id, { onDelete: "cascade" }),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
}, (t) => ({
uniqueTemplateSport: uniqueIndex("season_template_sports_template_sport_unique").on(t.templateId, t.sportId),
}));
export const seasonSports = pgTable("season_sports", {
id: uuid("id").primaryKey().defaultRandom(),

View file

@ -1,3 +1,5 @@
TRUNCATE TABLE "season_template_sports";
--> statement-breakpoint
ALTER TABLE "season_template_sports" DROP CONSTRAINT "season_template_sports_sports_season_id_sports_seasons_id_fk";
--> statement-breakpoint
ALTER TABLE "season_template_sports" ADD COLUMN "sport_id" uuid NOT NULL;--> statement-breakpoint

View file

@ -0,0 +1,2 @@
CREATE UNIQUE INDEX IF NOT EXISTS "season_template_sports_template_sport_unique" ON "season_template_sports" USING btree ("template_id","sport_id");--> statement-breakpoint
CREATE UNIQUE INDEX IF NOT EXISTS "season_templates_name_unique" ON "season_templates" USING btree ("name");

File diff suppressed because it is too large Load diff

View file

@ -806,6 +806,13 @@
"when": 1780595525976,
"tag": "0114_warm_swarm",
"breakpoints": true
},
{
"idx": 115,
"version": "7",
"when": 1780596702982,
"tag": "0115_spooky_spot",
"breakpoints": true
}
]
}