Problem
getTeamAcademics loads eligibility rows by player_id only, then takes the first match per player. It also defaults missing records to is_eligible: true and academic_standing: 'good', inflating "Eligible" and understating "At Risk" summary cards.
Evidence
src/app/baseball/actions/academics.ts (lines 145-148): query .in('player_id', playerIds) with no team_id filter
src/app/baseball/actions/academics.ts (line 181): uses eligibilityRecords.find(e => e.player_id === m.player_id)
src/app/baseball/actions/academics.ts (lines 193-194): default is_eligible: eligibility?.is_eligible ?? true and academic_standing: eligibility?.academic_standing ?? 'good'
Why it matters
Coaches can see wrong GPA/eligibility for transfers or multi-semester history, and roster-wide eligibility metrics lie when no record exists.
Acceptance criteria
- Team academics reads filter eligibility by
team_id (and prefer the latest semester for that team).
- Players with no eligibility row show unknown/ineligible-safe UI defaults, not "Eligible / Good Standing".
- Summary cards recompute from the scoped data only.
Problem
getTeamAcademicsloads eligibility rows byplayer_idonly, then takes the first match per player. It also defaults missing records tois_eligible: trueandacademic_standing: 'good', inflating "Eligible" and understating "At Risk" summary cards.Evidence
src/app/baseball/actions/academics.ts(lines 145-148): query.in('player_id', playerIds)with noteam_idfiltersrc/app/baseball/actions/academics.ts(line 181): useseligibilityRecords.find(e => e.player_id === m.player_id)src/app/baseball/actions/academics.ts(lines 193-194): defaultis_eligible: eligibility?.is_eligible ?? trueandacademic_standing: eligibility?.academic_standing ?? 'good'Why it matters
Coaches can see wrong GPA/eligibility for transfers or multi-semester history, and roster-wide eligibility metrics lie when no record exists.
Acceptance criteria
team_id(and prefer the latest semester for that team).