major-domo-v2/utils/team_utils.py
Cal Corum 758be0f166 CLAUDE: Fix trade system issues and enhance documentation
Major fixes and improvements:

Trade System Fixes:
- Fix duplicate player moves in trade embed Player Exchanges section
- Resolve "WVMiL not participating" error for Minor League destinations
- Implement organizational authority model for ML/MiL/IL team relationships
- Update Trade.cross_team_moves to deduplicate using moves_giving only

Team Model Enhancements:
- Rewrite roster_type() method using sname as definitive source per spec
- Fix edge cases like "BHMIL" (Birmingham IL) vs "BHMMIL"
- Update _get_base_abbrev() to use consistent sname-based logic
- Add organizational lookup support in trade participation

Autocomplete System:
- Fix major_league_team_autocomplete invalid roster_type parameter
- Implement client-side filtering using Team.roster_type() method
- Add comprehensive test coverage for all autocomplete functions
- Centralize autocomplete logic to shared utils functions

Test Infrastructure:
- Add 25 new tests for trade models and trade builder
- Add 13 autocomplete function tests with error handling
- Fix existing test failures with proper mocking patterns
- Update dropadd tests to use shared autocomplete functions

Documentation Updates:
- Document trade model enhancements and deduplication fix
- Add autocomplete function documentation with usage examples
- Document organizational authority model and edge case handling
- Update README files with recent fixes and implementation notes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 16:10:13 -05:00

109 lines
2.9 KiB
Python

"""
Team Utilities
Common team-related helper functions used across commands.
"""
from typing import Optional
import discord
from models.team import Team
from services.team_service import team_service
from constants import SBA_CURRENT_SEASON
async def get_user_major_league_team(
user_id: int,
season: int = SBA_CURRENT_SEASON
) -> Optional[Team]:
"""
Get the major league team owned by a Discord user.
This is a very common pattern used across many commands, so it's
extracted into a utility function for consistency and reusability.
Args:
user_id: Discord user ID
season: Season to check (defaults to current season)
Returns:
Team object if user owns a major league team, None otherwise
"""
try:
major_league_teams = await team_service.get_teams_by_owner(
user_id,
season,
roster_type="ml"
)
if major_league_teams:
return major_league_teams[0] # Return first ML team
return None
except Exception:
# Silently fail and return None - let calling code handle the error
return None
async def validate_user_has_team(
interaction: discord.Interaction,
season: int = SBA_CURRENT_SEASON
) -> Optional[Team]:
"""
Validate that a user has a major league team and send error message if not.
This combines team lookup with standard error messaging for consistency.
Args:
interaction: Discord interaction object
season: Season to check (defaults to current season)
Returns:
Team object if user has a team, None if not (error message already sent)
"""
user_team = await get_user_major_league_team(interaction.user.id, season)
if not user_team:
await interaction.followup.send(
"❌ You don't appear to own a major league team in the current season.",
ephemeral=True
)
return None
return user_team
async def get_team_by_abbrev_with_validation(
team_abbrev: str,
interaction: discord.Interaction,
season: int = SBA_CURRENT_SEASON
) -> Optional[Team]:
"""
Get a team by abbreviation with standard error messaging.
Args:
team_abbrev: Team abbreviation to look up
interaction: Discord interaction object for error messaging
season: Season to check (defaults to current season)
Returns:
Team object if found, None if not (error message already sent)
"""
try:
team = await team_service.get_team_by_abbrev(team_abbrev, season)
if not team:
await interaction.followup.send(
f"❌ Team '{team_abbrev}' not found.",
ephemeral=True
)
return None
return team
except Exception:
await interaction.followup.send(
f"❌ Error looking up team '{team_abbrev}'. Please try again.",
ephemeral=True
)
return None