package db import ( "context" "strings" "time" "github.com/pkg/errors" "github.com/uptrace/bun" ) type Season struct { bun.BaseModel `bun:"table:seasons,alias:s"` ID int `bun:"id,pk,autoincrement"` Name string `bun:"name,unique,notnull"` ShortName string `bun:"short_name,unique,notnull"` StartDate time.Time `bun:"start_date,notnull"` EndDate bun.NullTime `bun:"end_date"` FinalsStartDate bun.NullTime `bun:"finals_start_date"` FinalsEndDate bun.NullTime `bun:"finals_end_date"` 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 func NewSeason(name, version, shortname string, start time.Time) *Season { season := &Season{ Name: name, ShortName: strings.ToUpper(shortname), StartDate: start.Truncate(time.Hour * 24), SlapVersion: version, } return season } func ListSeasons(ctx context.Context, tx bun.Tx, pageOpts *PageOpts) (*List[Season], error) { defaults := &PageOpts{ 1, 10, bun.OrderDesc, "start_date", } return GetList[Season](tx).Relation("Leagues").GetPaged(ctx, pageOpts, defaults) } 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").Relation("Teams").Get(ctx) } // Update updates the season struct. It does not insert to the database func (s *Season) Update(version string, start, end, finalsStart, finalsEnd time.Time) { s.SlapVersion = version s.StartDate = start.Truncate(time.Hour * 24) if !end.IsZero() { s.EndDate.Time = end.Truncate(time.Hour * 24) } if !finalsStart.IsZero() { s.FinalsStartDate.Time = finalsStart.Truncate(time.Hour * 24) } if !finalsEnd.IsZero() { 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 }