added free agents
This commit is contained in:
@@ -79,6 +79,7 @@ type FixtureResultPlayerStats struct {
|
||||
HasMercyRuled *int
|
||||
WasMercyRuled *int
|
||||
PeriodsPlayed *int
|
||||
IsFreeAgent bool `bun:"is_free_agent,default:false"`
|
||||
|
||||
FixtureResult *FixtureResult `bun:"rel:belongs-to,join:fixture_result_id=id"`
|
||||
Player *Player `bun:"rel:belongs-to,join:player_id=id"`
|
||||
@@ -87,10 +88,11 @@ type FixtureResultPlayerStats struct {
|
||||
|
||||
// PlayerWithPlayStatus is a helper struct for overview display
|
||||
type PlayerWithPlayStatus struct {
|
||||
Player *Player
|
||||
Played bool
|
||||
IsManager bool
|
||||
Stats *FixtureResultPlayerStats // Period 3 (final cumulative) stats, nil if no result
|
||||
Player *Player
|
||||
Played bool
|
||||
IsManager bool
|
||||
IsFreeAgent bool
|
||||
Stats *FixtureResultPlayerStats // Period 3 (final cumulative) stats, nil if no result
|
||||
}
|
||||
|
||||
// InsertFixtureResult stores a new match result with all player stats in a single transaction.
|
||||
@@ -489,6 +491,12 @@ func GetFixtureTeamRosters(
|
||||
// Build maps of player IDs that played and their period 3 stats
|
||||
playedPlayerIDs := map[int]bool{}
|
||||
playerStatsByID := map[int]*FixtureResultPlayerStats{}
|
||||
freeAgentPlayerIDs := map[int]bool{}
|
||||
// Track free agents by team side for roster inclusion
|
||||
freeAgentsByTeam := map[string]map[int]*FixtureResultPlayerStats{} // "home"/"away" -> playerID -> stats
|
||||
freeAgentsByTeam["home"] = map[int]*FixtureResultPlayerStats{}
|
||||
freeAgentsByTeam["away"] = map[int]*FixtureResultPlayerStats{}
|
||||
|
||||
if result != nil {
|
||||
for _, ps := range result.PlayerStats {
|
||||
if ps.PlayerID != nil {
|
||||
@@ -496,10 +504,29 @@ func GetFixtureTeamRosters(
|
||||
if ps.PeriodNum == 3 {
|
||||
playerStatsByID[*ps.PlayerID] = ps
|
||||
}
|
||||
if ps.IsFreeAgent {
|
||||
freeAgentPlayerIDs[*ps.PlayerID] = true
|
||||
if ps.PeriodNum == 3 {
|
||||
freeAgentsByTeam[ps.Team][*ps.PlayerID] = ps
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build a set of roster player IDs so we can skip them when adding free agents
|
||||
rosterPlayerIDs := map[int]bool{}
|
||||
for _, r := range homeRosters {
|
||||
if r.Player != nil {
|
||||
rosterPlayerIDs[r.Player.ID] = true
|
||||
}
|
||||
}
|
||||
for _, r := range awayRosters {
|
||||
if r.Player != nil {
|
||||
rosterPlayerIDs[r.Player.ID] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Build home roster with play status and stats
|
||||
for _, r := range homeRosters {
|
||||
played := false
|
||||
@@ -532,5 +559,29 @@ func GetFixtureTeamRosters(
|
||||
})
|
||||
}
|
||||
|
||||
// Add free agents who played but are not on the team roster
|
||||
for team, faStats := range freeAgentsByTeam {
|
||||
for playerID, stats := range faStats {
|
||||
if rosterPlayerIDs[playerID] {
|
||||
continue // Already on the roster, skip
|
||||
}
|
||||
if stats.Player == nil {
|
||||
// Try to load the player
|
||||
player, err := GetPlayer(ctx, tx, playerID)
|
||||
if err != nil {
|
||||
continue // Skip if we can't load
|
||||
}
|
||||
stats.Player = player
|
||||
}
|
||||
rosters[team] = append(rosters[team], &PlayerWithPlayStatus{
|
||||
Player: stats.Player,
|
||||
Played: true,
|
||||
IsManager: false,
|
||||
IsFreeAgent: true,
|
||||
Stats: stats,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return rosters, nil
|
||||
}
|
||||
|
||||
342
internal/db/freeagent.go
Normal file
342
internal/db/freeagent.go
Normal file
@@ -0,0 +1,342 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
// SeasonLeagueFreeAgent tracks players registered as free agents in a season_league.
|
||||
type SeasonLeagueFreeAgent struct {
|
||||
bun.BaseModel `bun:"table:season_league_free_agents,alias:slfa"`
|
||||
|
||||
SeasonID int `bun:",pk,notnull"`
|
||||
LeagueID int `bun:",pk,notnull"`
|
||||
PlayerID int `bun:",pk,notnull"`
|
||||
RegisteredAt int64 `bun:",notnull"`
|
||||
RegisteredByUserID int `bun:",notnull"`
|
||||
|
||||
Season *Season `bun:"rel:belongs-to,join:season_id=id"`
|
||||
League *League `bun:"rel:belongs-to,join:league_id=id"`
|
||||
Player *Player `bun:"rel:belongs-to,join:player_id=id"`
|
||||
RegisteredBy *User `bun:"rel:belongs-to,join:registered_by_user_id=id"`
|
||||
}
|
||||
|
||||
// FixtureFreeAgent tracks which free agents are nominated for specific fixtures.
|
||||
type FixtureFreeAgent struct {
|
||||
bun.BaseModel `bun:"table:fixture_free_agents,alias:ffa"`
|
||||
|
||||
FixtureID int `bun:",pk,notnull"`
|
||||
PlayerID int `bun:",pk,notnull"`
|
||||
TeamID int `bun:",notnull"`
|
||||
NominatedByUserID int `bun:",notnull"`
|
||||
NominatedAt int64 `bun:",notnull"`
|
||||
|
||||
Fixture *Fixture `bun:"rel:belongs-to,join:fixture_id=id"`
|
||||
Player *Player `bun:"rel:belongs-to,join:player_id=id"`
|
||||
Team *Team `bun:"rel:belongs-to,join:team_id=id"`
|
||||
NominatedBy *User `bun:"rel:belongs-to,join:nominated_by_user_id=id"`
|
||||
}
|
||||
|
||||
// RegisterFreeAgent registers a player as a free agent in a season_league.
|
||||
func RegisterFreeAgent(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
seasonID, leagueID, playerID int,
|
||||
audit *AuditMeta,
|
||||
) error {
|
||||
user := CurrentUser(ctx)
|
||||
if user == nil {
|
||||
return errors.New("user cannot be nil")
|
||||
}
|
||||
|
||||
entry := &SeasonLeagueFreeAgent{
|
||||
SeasonID: seasonID,
|
||||
LeagueID: leagueID,
|
||||
PlayerID: playerID,
|
||||
RegisteredAt: time.Now().Unix(),
|
||||
RegisteredByUserID: user.ID,
|
||||
}
|
||||
|
||||
info := &AuditInfo{
|
||||
Action: "free_agents.add",
|
||||
ResourceType: "season_league_free_agent",
|
||||
ResourceID: fmt.Sprintf("%d-%d-%d", seasonID, leagueID, playerID),
|
||||
Details: map[string]any{
|
||||
"season_id": seasonID,
|
||||
"league_id": leagueID,
|
||||
"player_id": playerID,
|
||||
},
|
||||
}
|
||||
|
||||
err := Insert(tx, entry).WithAudit(audit, info).Exec(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Insert")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnregisterFreeAgent removes a player's free agent registration and all their nominations.
|
||||
func UnregisterFreeAgent(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
seasonID, leagueID, playerID int,
|
||||
audit *AuditMeta,
|
||||
) error {
|
||||
// First remove all nominations for this player
|
||||
err := RemoveAllFreeAgentNominationsForPlayer(ctx, tx, playerID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "RemoveAllFreeAgentNominationsForPlayer")
|
||||
}
|
||||
|
||||
// Then remove the registration
|
||||
_, err = tx.NewDelete().
|
||||
Model((*SeasonLeagueFreeAgent)(nil)).
|
||||
Where("season_id = ?", seasonID).
|
||||
Where("league_id = ?", leagueID).
|
||||
Where("player_id = ?", playerID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "tx.NewDelete")
|
||||
}
|
||||
|
||||
info := &AuditInfo{
|
||||
Action: "free_agents.remove",
|
||||
ResourceType: "season_league_free_agent",
|
||||
ResourceID: fmt.Sprintf("%d-%d-%d", seasonID, leagueID, playerID),
|
||||
Details: map[string]any{
|
||||
"season_id": seasonID,
|
||||
"league_id": leagueID,
|
||||
"player_id": playerID,
|
||||
},
|
||||
}
|
||||
err = LogSuccess(ctx, tx, audit, info)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "LogSuccess")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFreeAgentsForSeasonLeague returns all players registered as free agents in a season_league.
|
||||
func GetFreeAgentsForSeasonLeague(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
seasonID, leagueID int,
|
||||
) ([]*SeasonLeagueFreeAgent, error) {
|
||||
entries := []*SeasonLeagueFreeAgent{}
|
||||
err := tx.NewSelect().
|
||||
Model(&entries).
|
||||
Where("slfa.season_id = ?", seasonID).
|
||||
Where("slfa.league_id = ?", leagueID).
|
||||
Relation("Player", func(q *bun.SelectQuery) *bun.SelectQuery {
|
||||
return q.Relation("User")
|
||||
}).
|
||||
Relation("RegisteredBy").
|
||||
Order("slfa.registered_at ASC").
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "tx.NewSelect")
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
// IsFreeAgentRegistered checks if a player is registered as a free agent in a season_league.
|
||||
func IsFreeAgentRegistered(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
seasonID, leagueID, playerID int,
|
||||
) (bool, error) {
|
||||
count, err := tx.NewSelect().
|
||||
Model((*SeasonLeagueFreeAgent)(nil)).
|
||||
Where("season_id = ?", seasonID).
|
||||
Where("league_id = ?", leagueID).
|
||||
Where("player_id = ?", playerID).
|
||||
Count(ctx)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "tx.NewSelect")
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// NominateFreeAgent nominates a free agent for a specific fixture on behalf of a team.
|
||||
func NominateFreeAgent(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
fixtureID, playerID, teamID int,
|
||||
audit *AuditMeta,
|
||||
) error {
|
||||
user := CurrentUser(ctx)
|
||||
if user == nil {
|
||||
return errors.New("user cannot be nil")
|
||||
}
|
||||
|
||||
// Check if already nominated by another team
|
||||
existing := new(FixtureFreeAgent)
|
||||
err := tx.NewSelect().
|
||||
Model(existing).
|
||||
Where("ffa.fixture_id = ?", fixtureID).
|
||||
Where("ffa.player_id = ?", playerID).
|
||||
Scan(ctx)
|
||||
if err == nil {
|
||||
// Found existing nomination
|
||||
if existing.TeamID != teamID {
|
||||
return BadRequest("Player already nominated for this fixture by another team")
|
||||
}
|
||||
return BadRequest("Player already nominated for this fixture")
|
||||
}
|
||||
if err.Error() != "sql: no rows in result set" {
|
||||
return errors.Wrap(err, "tx.NewSelect")
|
||||
}
|
||||
|
||||
// Check max 2 free agents per team per fixture
|
||||
count, err := tx.NewSelect().
|
||||
Model((*FixtureFreeAgent)(nil)).
|
||||
Where("fixture_id = ?", fixtureID).
|
||||
Where("team_id = ?", teamID).
|
||||
Count(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "tx.NewSelect count")
|
||||
}
|
||||
if count >= 2 {
|
||||
return BadRequest("Maximum of 2 free agents per team per fixture")
|
||||
}
|
||||
|
||||
entry := &FixtureFreeAgent{
|
||||
FixtureID: fixtureID,
|
||||
PlayerID: playerID,
|
||||
TeamID: teamID,
|
||||
NominatedByUserID: user.ID,
|
||||
NominatedAt: time.Now().Unix(),
|
||||
}
|
||||
|
||||
info := &AuditInfo{
|
||||
Action: "free_agents.nominate",
|
||||
ResourceType: "fixture_free_agent",
|
||||
ResourceID: fmt.Sprintf("%d-%d", fixtureID, playerID),
|
||||
Details: map[string]any{
|
||||
"fixture_id": fixtureID,
|
||||
"player_id": playerID,
|
||||
"team_id": teamID,
|
||||
},
|
||||
}
|
||||
|
||||
err = Insert(tx, entry).WithAudit(audit, info).Exec(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Insert")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNominatedFreeAgents returns all free agents nominated for a fixture.
|
||||
func GetNominatedFreeAgents(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
fixtureID int,
|
||||
) ([]*FixtureFreeAgent, error) {
|
||||
entries := []*FixtureFreeAgent{}
|
||||
err := tx.NewSelect().
|
||||
Model(&entries).
|
||||
Where("ffa.fixture_id = ?", fixtureID).
|
||||
Relation("Player", func(q *bun.SelectQuery) *bun.SelectQuery {
|
||||
return q.Relation("User")
|
||||
}).
|
||||
Relation("Team").
|
||||
Relation("NominatedBy").
|
||||
Order("ffa.nominated_at ASC").
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "tx.NewSelect")
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
// GetNominatedFreeAgentsByTeam returns free agents nominated by a specific team for a fixture.
|
||||
func GetNominatedFreeAgentsByTeam(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
fixtureID, teamID int,
|
||||
) ([]*FixtureFreeAgent, error) {
|
||||
entries := []*FixtureFreeAgent{}
|
||||
err := tx.NewSelect().
|
||||
Model(&entries).
|
||||
Where("ffa.fixture_id = ?", fixtureID).
|
||||
Where("ffa.team_id = ?", teamID).
|
||||
Relation("Player", func(q *bun.SelectQuery) *bun.SelectQuery {
|
||||
return q.Relation("User")
|
||||
}).
|
||||
Order("ffa.nominated_at ASC").
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "tx.NewSelect")
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
// RemoveAllFreeAgentNominationsForPlayer deletes all nominations for a player.
|
||||
// Used for cascade deletion on team join and unregister.
|
||||
func RemoveAllFreeAgentNominationsForPlayer(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
playerID int,
|
||||
) error {
|
||||
_, err := tx.NewDelete().
|
||||
Model((*FixtureFreeAgent)(nil)).
|
||||
Where("player_id = ?", playerID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "tx.NewDelete")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveFreeAgentNomination removes a specific nomination.
|
||||
func RemoveFreeAgentNomination(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
fixtureID, playerID int,
|
||||
audit *AuditMeta,
|
||||
) error {
|
||||
_, err := tx.NewDelete().
|
||||
Model((*FixtureFreeAgent)(nil)).
|
||||
Where("fixture_id = ?", fixtureID).
|
||||
Where("player_id = ?", playerID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "tx.NewDelete")
|
||||
}
|
||||
|
||||
info := &AuditInfo{
|
||||
Action: "free_agents.remove_nomination",
|
||||
ResourceType: "fixture_free_agent",
|
||||
ResourceID: fmt.Sprintf("%d-%d", fixtureID, playerID),
|
||||
Details: map[string]any{
|
||||
"fixture_id": fixtureID,
|
||||
"player_id": playerID,
|
||||
},
|
||||
}
|
||||
err = LogSuccess(ctx, tx, audit, info)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "LogSuccess")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveFreeAgentRegistrationForPlayer removes all free agent registrations for a player.
|
||||
// Used on team join.
|
||||
func RemoveFreeAgentRegistrationForPlayer(
|
||||
ctx context.Context,
|
||||
tx bun.Tx,
|
||||
playerID int,
|
||||
) error {
|
||||
_, err := tx.NewDelete().
|
||||
Model((*SeasonLeagueFreeAgent)(nil)).
|
||||
Where("player_id = ?", playerID).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "tx.NewDelete")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
91
internal/db/migrations/20260222140000_free_agents.go
Normal file
91
internal/db/migrations/20260222140000_free_agents.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.haelnorr.com/h/oslstats/internal/db"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Migrations.MustRegister(
|
||||
// UP migration
|
||||
func(ctx context.Context, conn *bun.DB) error {
|
||||
// Create season_league_free_agents table
|
||||
_, err := conn.NewCreateTable().
|
||||
Model((*db.SeasonLeagueFreeAgent)(nil)).
|
||||
IfNotExists().
|
||||
ForeignKey(`("season_id") REFERENCES "seasons" ("id") ON DELETE CASCADE`).
|
||||
ForeignKey(`("league_id") REFERENCES "leagues" ("id") ON DELETE CASCADE`).
|
||||
ForeignKey(`("player_id") REFERENCES "players" ("id") ON DELETE CASCADE`).
|
||||
ForeignKey(`("registered_by_user_id") REFERENCES "users" ("id")`).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create fixture_free_agents table
|
||||
_, err = conn.NewCreateTable().
|
||||
Model((*db.FixtureFreeAgent)(nil)).
|
||||
IfNotExists().
|
||||
ForeignKey(`("fixture_id") REFERENCES "fixtures" ("id") ON DELETE CASCADE`).
|
||||
ForeignKey(`("player_id") REFERENCES "players" ("id") ON DELETE CASCADE`).
|
||||
ForeignKey(`("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE`).
|
||||
ForeignKey(`("nominated_by_user_id") REFERENCES "users" ("id")`).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create index on fixture_free_agents for team lookups
|
||||
_, err = conn.NewCreateIndex().
|
||||
Model((*db.FixtureFreeAgent)(nil)).
|
||||
Index("idx_ffa_fixture_team").
|
||||
Column("fixture_id", "team_id").
|
||||
IfNotExists().
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add is_free_agent column to fixture_result_player_stats
|
||||
_, err = conn.NewAddColumn().
|
||||
Model((*db.FixtureResultPlayerStats)(nil)).
|
||||
ColumnExpr("is_free_agent BOOLEAN NOT NULL DEFAULT false").
|
||||
IfNotExists().
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
// DOWN migration
|
||||
func(ctx context.Context, conn *bun.DB) error {
|
||||
// Drop is_free_agent column from fixture_result_player_stats
|
||||
_, err := conn.NewDropColumn().
|
||||
Model((*db.FixtureResultPlayerStats)(nil)).
|
||||
ColumnExpr("is_free_agent").
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Drop fixture_free_agents table
|
||||
_, err = conn.NewDropTable().
|
||||
Model((*db.FixtureFreeAgent)(nil)).
|
||||
IfExists().
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Drop season_league_free_agents table
|
||||
_, err = conn.NewDropTable().
|
||||
Model((*db.SeasonLeagueFreeAgent)(nil)).
|
||||
IfExists().
|
||||
Exec(ctx)
|
||||
return err
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -128,6 +128,7 @@ func AddPlayerToTeam(ctx context.Context, tx bun.Tx, seasonID, leagueID, teamID,
|
||||
|
||||
// ManageTeamRoster replaces the entire roster for a team in a season/league.
|
||||
// It deletes all existing roster entries and inserts the new ones.
|
||||
// Also auto-removes free agent registrations and nominations for players joining a team.
|
||||
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().
|
||||
@@ -140,6 +141,56 @@ func ManageTeamRoster(ctx context.Context, tx bun.Tx, seasonID, leagueID, teamID
|
||||
return errors.Wrap(err, "delete existing roster")
|
||||
}
|
||||
|
||||
// Collect all player IDs being added (including manager)
|
||||
allPlayerIDs := make([]int, 0, len(playerIDs)+1)
|
||||
if managerID > 0 {
|
||||
allPlayerIDs = append(allPlayerIDs, managerID)
|
||||
}
|
||||
for _, pid := range playerIDs {
|
||||
if pid != managerID {
|
||||
allPlayerIDs = append(allPlayerIDs, pid)
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-remove free agent registrations and nominations for players joining a team
|
||||
for _, playerID := range allPlayerIDs {
|
||||
// Check if the player is a registered free agent
|
||||
isFA, err := IsFreeAgentRegistered(ctx, tx, seasonID, leagueID, playerID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "IsFreeAgentRegistered")
|
||||
}
|
||||
if isFA {
|
||||
// Remove all nominations for this player
|
||||
err = RemoveAllFreeAgentNominationsForPlayer(ctx, tx, playerID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "RemoveAllFreeAgentNominationsForPlayer")
|
||||
}
|
||||
// Remove free agent registration
|
||||
err = RemoveFreeAgentRegistrationForPlayer(ctx, tx, playerID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "RemoveFreeAgentRegistrationForPlayer")
|
||||
}
|
||||
// Log the cascade action
|
||||
if audit != nil {
|
||||
cascadeInfo := &AuditInfo{
|
||||
"free_agents.auto_removed_on_team_join",
|
||||
"season_league_free_agent",
|
||||
fmt.Sprintf("%d-%d-%d", seasonID, leagueID, playerID),
|
||||
map[string]any{
|
||||
"season_id": seasonID,
|
||||
"league_id": leagueID,
|
||||
"player_id": playerID,
|
||||
"team_id": teamID,
|
||||
},
|
||||
}
|
||||
err = LogSuccess(ctx, tx, audit, cascadeInfo)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "LogSuccess cascade")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert manager if provided
|
||||
if managerID > 0 {
|
||||
tr := &TeamRoster{
|
||||
|
||||
Reference in New Issue
Block a user