added teams

This commit is contained in:
2026-02-12 21:10:49 +11:00
parent ba6929629d
commit c92c722ad5
25 changed files with 1327 additions and 52 deletions

View File

@@ -16,6 +16,7 @@ type League struct {
Description string `bun:"description"`
Seasons []Season `bun:"m2m:season_leagues,join:League=Season"`
Teams []Team `bun:"m2m:team_participations,join:League=Team"`
}
type SeasonLeague struct {
@@ -35,3 +36,42 @@ func GetLeague(ctx context.Context, tx bun.Tx, shortname string) (*League, error
}
return GetByField[League](tx, "short_name", shortname).Relation("Seasons").Get(ctx)
}
// GetSeasonLeague retrieves a specific season-league combination with teams
func GetSeasonLeague(ctx context.Context, tx bun.Tx, seasonShortName, leagueShortName string) (*Season, *League, []*Team, error) {
if seasonShortName == "" {
return nil, nil, nil, errors.New("season short_name cannot be empty")
}
if leagueShortName == "" {
return nil, nil, nil, errors.New("league short_name cannot be empty")
}
// Get the season
season, err := GetSeason(ctx, tx, seasonShortName)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "GetSeason")
}
// Get the league
league, err := GetLeague(ctx, tx, leagueShortName)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "GetLeague")
}
if season == nil || league == nil || !season.HasLeague(league.ID) {
return nil, nil, nil, nil
}
// Get all teams participating in this season+league
var teams []*Team
err = tx.NewSelect().
Model(&teams).
Join("INNER JOIN team_participations AS tp ON tp.team_id = t.id").
Where("tp.season_id = ? AND tp.league_id = ?", season.ID, league.ID).
Order("t.name ASC").
Scan(ctx)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "tx.Select teams")
}
return season, league, teams, nil
}

View File

@@ -22,6 +22,7 @@ type Season struct {
SlapVersion string `bun:"slap_version,notnull,default:'rebound'"`
Leagues []League `bun:"m2m:season_leagues,join:Season=League"`
Teams []Team `bun:"m2m:team_participations,join:Season=Team"`
}
// NewSeason returns a new season. It does not add it to the database
@@ -49,7 +50,7 @@ func GetSeason(ctx context.Context, tx bun.Tx, shortname string) (*Season, error
if shortname == "" {
return nil, errors.New("short_name not provided")
}
return GetByField[Season](tx, "short_name", shortname).Relation("Leagues").Get(ctx)
return GetByField[Season](tx, "short_name", shortname).Relation("Leagues").Relation("Teams").Get(ctx)
}
// Update updates the season struct. It does not insert to the database
@@ -66,3 +67,39 @@ func (s *Season) Update(version string, start, end, finalsStart, finalsEnd time.
s.FinalsEndDate.Time = finalsEnd.Truncate(time.Hour * 24)
}
}
func (s *Season) MapTeamsToLeagues(ctx context.Context, tx bun.Tx) ([]LeagueWithTeams, error) {
// For each league, get the teams
leaguesWithTeams := make([]LeagueWithTeams, len(s.Leagues))
for i, league := range s.Leagues {
var teams []*Team
err := tx.NewSelect().
Model(&teams).
Join("INNER JOIN team_participations AS tp ON tp.team_id = t.id").
Where("tp.season_id = ? AND tp.league_id = ?", s.ID, league.ID).
Order("t.name ASC").
Scan(ctx)
if err != nil {
return nil, errors.Wrap(err, "tx.NewSelect")
}
leaguesWithTeams[i] = LeagueWithTeams{
League: &league,
Teams: teams,
}
}
return leaguesWithTeams, nil
}
type LeagueWithTeams struct {
League *League
Teams []*Team
}
func (s *Season) HasLeague(leagueID int) bool {
for _, league := range s.Leagues {
if league.ID == leagueID {
return true
}
}
return false
}

58
internal/db/team.go Normal file
View File

@@ -0,0 +1,58 @@
package db
import (
"context"
"github.com/pkg/errors"
"github.com/uptrace/bun"
)
type Team struct {
bun.BaseModel `bun:"table:teams,alias:t"`
ID int `bun:"id,pk,autoincrement"`
Name string `bun:"name,unique,notnull"`
ShortName string `bun:"short_name,notnull,unique:short_names"`
AltShortName string `bun:"alt_short_name,notnull,unique:short_names"`
Color string `bun:"color"`
Seasons []Season `bun:"m2m:team_participations,join:Team=Season"`
Leagues []League `bun:"m2m:team_participations,join:Team=League"`
}
type TeamParticipation struct {
SeasonID int `bun:",pk,unique:season_team"`
Season *Season `bun:"rel:belongs-to,join:season_id=id"`
LeagueID int `bun:",pk"`
League *League `bun:"rel:belongs-to,join:league_id=id"`
TeamID int `bun:",pk,unique:season_team"`
Team *Team `bun:"rel:belongs-to,join:team_id=id"`
}
func ListTeams(ctx context.Context, tx bun.Tx, pageOpts *PageOpts) (*List[Team], error) {
defaults := &PageOpts{
1,
10,
bun.OrderAsc,
"name",
}
return GetList[Team](tx).GetPaged(ctx, pageOpts, defaults)
}
func GetTeam(ctx context.Context, tx bun.Tx, id int) (*Team, error) {
if id == 0 {
return nil, errors.New("id not provided")
}
return GetByID[Team](tx, id).Relation("Seasons").Relation("Leagues").Get(ctx)
}
func TeamShortNamesUnique(ctx context.Context, tx bun.Tx, shortname, altshortname string) (bool, error) {
// Check if this combination of short_name and alt_short_name exists
count, err := tx.NewSelect().
Model((*Team)(nil)).
Where("short_name = ? AND alt_short_name = ?", shortname, altshortname).
Count(ctx)
if err != nil {
return false, errors.Wrap(err, "tx.Select")
}
return count == 0, nil
}