package db import ( "context" "database/sql" "git.haelnorr.com/h/oslstats/internal/permissions" "github.com/pkg/errors" "github.com/uptrace/bun" ) type SeasonLeague struct { SeasonID int `bun:",pk"` Season *Season `bun:"rel:belongs-to,join:season_id=id"` LeagueID int `bun:",pk"` League *League `bun:"rel:belongs-to,join:league_id=id"` } // GetSeasonLeague retrieves a specific season-league combination func GetSeasonLeague(ctx context.Context, tx bun.Tx, seasonShortName, leagueShortName string) (*SeasonLeague, error) { if seasonShortName == "" { return nil, errors.New("season short_name cannot be empty") } if leagueShortName == "" { return nil, errors.New("league short_name cannot be empty") } sl := new(SeasonLeague) err := tx.NewSelect(). Model(sl). Relation("Season", func(q *bun.SelectQuery) *bun.SelectQuery { return q.Where("season.short_name = ?", seasonShortName) }). Relation("League", func(q *bun.SelectQuery) *bun.SelectQuery { return q.Where("league.short_name = ?", leagueShortName) }).Scan(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, BadRequestNotFound("season_league", "season.short_name,league.short_name", seasonShortName+","+leagueShortName) } return nil, errors.Wrap(err, "tx.NewSelect") } return sl, nil } // GetSeasonLeagueWithTeams retrieves a specific season-league combination with teams func GetSeasonLeagueWithTeams(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") } season, err := GetSeason(ctx, tx, seasonShortName) if err != nil { return nil, nil, nil, errors.Wrap(err, "GetSeason") } league, err := season.GetLeague(leagueShortName) if err != nil { return nil, nil, nil, errors.Wrap(err, "season.GetLeague") } // 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"). Relation("Players", func(q *bun.SelectQuery) *bun.SelectQuery { return q.Where("season_id = ? AND league_id = ?", season.ID, league.ID) }). Scan(ctx) if err != nil { return nil, nil, nil, errors.Wrap(err, "tx.Select teams") } return season, league, teams, nil } func NewSeasonLeague(ctx context.Context, tx bun.Tx, seasonShortName, leagueShortName string, audit *AuditMeta) error { season, err := GetSeason(ctx, tx, seasonShortName) if err != nil { return errors.Wrap(err, "GetSeason") } league, err := GetLeague(ctx, tx, leagueShortName) if err != nil { return errors.Wrap(err, "GetLeague") } if season.HasLeague(league) { return BadRequestAssociated("season", "league", "id", "id", season.ID, league.ID) } seasonLeague := &SeasonLeague{ SeasonID: season.ID, LeagueID: league.ID, } info := &AuditInfo{ string(permissions.SeasonsAddLeague), "season", season.ID, map[string]any{"league_id": league.ID}, } err = Insert(tx, seasonLeague).WithAudit(audit, info).Exec(ctx) if err != nil { return errors.Wrap(err, "db.Insert") } return nil } func (s *Season) RemoveLeague(ctx context.Context, tx bun.Tx, leagueShortName string, audit *AuditMeta) error { league, err := s.GetLeague(leagueShortName) if err != nil { return errors.Wrap(err, "s.GetLeague") } info := &AuditInfo{ string(permissions.SeasonsRemoveLeague), "season", s.ID, map[string]any{"league_id": league.ID}, } err = DeleteItem[SeasonLeague](tx). Where("season_id = ?", s.ID). Where("league_id = ?", league.ID). WithAudit(audit, info). Delete(ctx) if err != nil { return errors.Wrap(err, "db.DeleteItem") } return nil } func (t *Team) InTeams(teams []*Team) bool { for _, team := range teams { if t.ID == team.ID { return true } } return false }