Files
oslstats/internal/db/teamroster.go

177 lines
4.6 KiB
Go

package db
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/uptrace/bun"
)
type TeamRoster struct {
bun.BaseModel `bun:"table:team_rosters,alias:tr"`
TeamID int `bun:",pk,notnull" json:"team_id"`
SeasonID int `bun:",pk,notnull,unique:player" json:"season_id"`
LeagueID int `bun:",pk,notnull,unique:player" json:"league_id"`
PlayerID int `bun:",pk,notnull,unique:player" json:"player_id"`
IsManager bool `bun:"is_manager,default:'false'" json:"is_manager"`
Team *Team `bun:"rel:belongs-to,join:team_id=id" json:"-"`
Player *Player `bun:"rel:belongs-to,join:player_id=id" json:"-"`
Season *Season `bun:"rel:belongs-to,join:season_id=id" json:"-"`
League *League `bun:"rel:belongs-to,join:league_id=id" json:"-"`
}
type TeamWithRoster struct {
Team *Team
Season *Season
League *League
Manager *Player
Players []*Player
}
func GetTeamRoster(ctx context.Context, tx bun.Tx, seasonShortName, leagueShortName string, teamID int) (*TeamWithRoster, error) {
tr := []*TeamRoster{}
err := tx.NewSelect().
Model(&tr).
Relation("Team", func(q *bun.SelectQuery) *bun.SelectQuery {
return q.Where("team.id = ?", teamID)
}).
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)
}).
Relation("Player").Scan(ctx)
if err != nil {
return nil, errors.Wrap(err, "tx.NewSelect")
}
team, err := GetTeam(ctx, tx, teamID)
if err != nil {
return nil, errors.Wrap(err, "GetTeam")
}
sl, err := GetSeasonLeague(ctx, tx, seasonShortName, leagueShortName)
if err != nil {
return nil, errors.Wrap(err, "GetSeasonLeague")
}
var manager *Player
players := []*Player{}
for _, tp := range tr {
if tp.IsManager {
manager = tp.Player
} else {
players = append(players, tp.Player)
}
}
players = append([]*Player{manager}, players...)
twr := &TeamWithRoster{
team,
sl.Season,
sl.League,
manager,
players,
}
return twr, nil
}
func AddPlayerToTeam(ctx context.Context, tx bun.Tx, seasonID, leagueID, teamID, playerID int, manager bool, audit *AuditMeta) error {
season, err := GetByID[Season](tx, seasonID).Get(ctx)
if err != nil {
return errors.Wrap(err, "GetSeason")
}
league, err := GetByID[League](tx, leagueID).Get(ctx)
if err != nil {
return errors.Wrap(err, "GetLeague")
}
team, err := GetByID[Team](tx, teamID).Get(ctx)
if err != nil {
return errors.Wrap(err, "GetTeam")
}
player, err := GetByID[Player](tx, playerID).Get(ctx)
if err != nil {
return errors.Wrap(err, "GetPlayer")
}
tr := &TeamRoster{
SeasonID: season.ID,
LeagueID: league.ID,
TeamID: team.ID,
PlayerID: player.ID,
IsManager: manager,
}
err = Insert(tx, tr).WithAudit(audit, nil).Exec(ctx)
if err != nil {
return errors.Wrap(err, "Insert")
}
return nil
}
// ManageTeamRoster replaces the entire roster for a team in a season/league.
// It deletes all existing roster entries and inserts the new ones.
func ManageTeamRoster(ctx context.Context, tx bun.Tx, seasonID, leagueID, teamID, managerID int, playerIDs []int, audit *AuditMeta) error {
// Delete all existing roster entries for this team/season/league
_, err := tx.NewDelete().
Model((*TeamRoster)(nil)).
Where("season_id = ?", seasonID).
Where("league_id = ?", leagueID).
Where("team_id = ?", teamID).
Exec(ctx)
if err != nil {
return errors.Wrap(err, "delete existing roster")
}
// Insert manager if provided
if managerID > 0 {
tr := &TeamRoster{
SeasonID: seasonID,
LeagueID: leagueID,
TeamID: teamID,
PlayerID: managerID,
IsManager: true,
}
err = Insert(tx, tr).Exec(ctx)
if err != nil {
return errors.Wrap(err, "Insert manager")
}
}
// Insert players
for _, playerID := range playerIDs {
if playerID == managerID {
continue // Already inserted as manager
}
tr := &TeamRoster{
SeasonID: seasonID,
LeagueID: leagueID,
TeamID: teamID,
PlayerID: playerID,
IsManager: false,
}
err = Insert(tx, tr).Exec(ctx)
if err != nil {
return errors.Wrap(err, "Insert player")
}
}
// Log the roster change
details := map[string]any{
"season_id": seasonID,
"league_id": leagueID,
"team_id": teamID,
"manager_id": managerID,
"player_ids": playerIDs,
}
info := &AuditInfo{
"teams.manage_players",
"team_roster",
fmt.Sprintf("%d-%d-%d", seasonID, leagueID, teamID),
details,
}
err = LogSuccess(ctx, tx, audit, info)
if err != nil {
return errors.Wrap(err, "LogSuccess")
}
return nil
}