Add dem_week parameter to player team updates
- Add optional dem_week parameter to PlayerService.update_player_team() - Transaction freeze sets dem_week to current.week + 2 - /ilmove command sets dem_week to current.week - Draft picks (manual and auto) set dem_week to current.week + 2 - Backwards compatible - admin commands don't set dem_week - Add 4 unit tests for dem_week scenarios - Enhanced logging shows dem_week values 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f4523b99f2
commit
be3dbf1f8d
@ -304,10 +304,15 @@ class DraftPicksCog(commands.Cog):
|
||||
await interaction.followup.send(embed=embed)
|
||||
return
|
||||
|
||||
# Update player team
|
||||
# Get current league state for dem_week calculation
|
||||
from services.league_service import league_service
|
||||
current = await league_service.get_current_state()
|
||||
|
||||
# Update player team with dem_week set to current.week + 2 for draft picks
|
||||
updated_player = await player_service.update_player_team(
|
||||
player_obj.id,
|
||||
team.id
|
||||
team.id,
|
||||
dem_week=current.week + 2 if current else None
|
||||
)
|
||||
|
||||
if not updated_player:
|
||||
|
||||
@ -372,33 +372,65 @@ class PlayerService(BaseService[Player]):
|
||||
return None
|
||||
|
||||
async def update_player_team(
|
||||
self, player_id: int, new_team_id: int
|
||||
self,
|
||||
player_id: int,
|
||||
new_team_id: int,
|
||||
dem_week: Optional[int] = None
|
||||
) -> Optional[Player]:
|
||||
"""
|
||||
Update a player's team assignment (for real-time IL moves).
|
||||
|
||||
This is used for immediate roster changes where the player needs to show
|
||||
up on their new team right away, rather than waiting for transaction processing.
|
||||
Update a player's team assignment.
|
||||
|
||||
Args:
|
||||
player_id: Player ID to update
|
||||
new_team_id: New team ID to assign
|
||||
dem_week: Optional demotion/designation week to set.
|
||||
- Transaction freeze: Current.week + 2
|
||||
- Draft picks: Current.week + 2
|
||||
- IL moves: Current.week
|
||||
- Admin/Other: Not set (None)
|
||||
|
||||
Returns:
|
||||
Updated player instance or None
|
||||
|
||||
Raises:
|
||||
APIException: If player update fails
|
||||
|
||||
Examples:
|
||||
# Transaction freeze (Monday morning)
|
||||
await player_service.update_player_team(
|
||||
player_id, new_team_id, dem_week=current.week + 2
|
||||
)
|
||||
|
||||
# Draft pick (manual or auto-draft)
|
||||
await player_service.update_player_team(
|
||||
player_id, new_team_id, dem_week=current.week + 2
|
||||
)
|
||||
|
||||
# IL move (/ilmove command)
|
||||
await player_service.update_player_team(
|
||||
player_id, new_team_id, dem_week=current.week
|
||||
)
|
||||
|
||||
# Admin move (no dem_week)
|
||||
await player_service.update_player_team(player_id, new_team_id)
|
||||
"""
|
||||
try:
|
||||
logger.info(f"Updating player {player_id} team to {new_team_id}")
|
||||
updated_player = await self.update_player(
|
||||
player_id, {"team_id": new_team_id}
|
||||
logger.info(
|
||||
f"Updating player {player_id} team to {new_team_id}"
|
||||
+ (f" with dem_week={dem_week}" if dem_week is not None else "")
|
||||
)
|
||||
|
||||
# Build update dictionary
|
||||
updates = {"team_id": new_team_id}
|
||||
if dem_week is not None:
|
||||
updates["dem_week"] = dem_week
|
||||
|
||||
updated_player = await self.update_player(player_id, updates)
|
||||
|
||||
if updated_player:
|
||||
logger.info(
|
||||
f"Successfully updated player {player_id} to team {new_team_id}"
|
||||
+ (f" with dem_week={dem_week}" if dem_week is not None else "")
|
||||
)
|
||||
return updated_player
|
||||
else:
|
||||
|
||||
@ -340,11 +340,16 @@ class DraftMonitorTask:
|
||||
self.logger.error(f"Failed to update pick {draft_pick.id}")
|
||||
return False
|
||||
|
||||
# Update player team
|
||||
# Get current league state for dem_week calculation
|
||||
from services.player_service import player_service
|
||||
from services.league_service import league_service
|
||||
current = await league_service.get_current_state()
|
||||
|
||||
# Update player team with dem_week set to current.week + 2 for draft picks
|
||||
updated_player = await player_service.update_player_team(
|
||||
player.id,
|
||||
draft_pick.owner.id
|
||||
draft_pick.owner.id,
|
||||
dem_week=current.week + 2 if current else None
|
||||
)
|
||||
|
||||
if not updated_player:
|
||||
|
||||
@ -465,11 +465,12 @@ class TransactionFreezeTask:
|
||||
|
||||
for transaction in transactions:
|
||||
try:
|
||||
# Update player's team via PATCH /players/{player_id}?team_id={new_team_id}
|
||||
# Update player's team via PATCH /players/{player_id}?team_id={new_team_id}&dem_week={current.week+2}
|
||||
await self._execute_player_update(
|
||||
player_id=transaction.player.id,
|
||||
new_team_id=transaction.newteam.id,
|
||||
player_name=transaction.player.name
|
||||
player_name=transaction.player.name,
|
||||
dem_week=current.week + 2
|
||||
)
|
||||
success_count += 1
|
||||
|
||||
@ -683,7 +684,8 @@ class TransactionFreezeTask:
|
||||
self,
|
||||
player_id: int,
|
||||
new_team_id: int,
|
||||
player_name: str
|
||||
player_name: str,
|
||||
dem_week: Optional[int] = None
|
||||
) -> bool:
|
||||
"""
|
||||
Execute a player roster update via API PATCH.
|
||||
@ -692,6 +694,7 @@ class TransactionFreezeTask:
|
||||
player_id: Player database ID
|
||||
new_team_id: New team ID to assign
|
||||
player_name: Player name for logging
|
||||
dem_week: Optional designation week to set (typically Current.week + 2)
|
||||
|
||||
Returns:
|
||||
True if update successful, False otherwise
|
||||
@ -704,10 +707,15 @@ class TransactionFreezeTask:
|
||||
"Updating player roster",
|
||||
player_id=player_id,
|
||||
player_name=player_name,
|
||||
new_team_id=new_team_id
|
||||
new_team_id=new_team_id,
|
||||
dem_week=dem_week
|
||||
)
|
||||
|
||||
updated_player = await player_service.update_player_team(player_id, new_team_id)
|
||||
updated_player = await player_service.update_player_team(
|
||||
player_id,
|
||||
new_team_id,
|
||||
dem_week=dem_week
|
||||
)
|
||||
|
||||
# Verify response (200 or 204 indicates success)
|
||||
if updated_player is not None:
|
||||
@ -715,7 +723,8 @@ class TransactionFreezeTask:
|
||||
"Successfully updated player",
|
||||
player_id=player_id,
|
||||
player_name=player_name,
|
||||
new_team_id=new_team_id
|
||||
new_team_id=new_team_id,
|
||||
dem_week=dem_week
|
||||
)
|
||||
return True
|
||||
else:
|
||||
@ -723,7 +732,8 @@ class TransactionFreezeTask:
|
||||
"Player update returned no response",
|
||||
player_id=player_id,
|
||||
player_name=player_name,
|
||||
new_team_id=new_team_id
|
||||
new_team_id=new_team_id,
|
||||
dem_week=dem_week
|
||||
)
|
||||
return False
|
||||
|
||||
@ -733,6 +743,7 @@ class TransactionFreezeTask:
|
||||
player_id=player_id,
|
||||
player_name=player_name,
|
||||
new_team_id=new_team_id,
|
||||
dem_week=dem_week,
|
||||
error=str(e),
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
@ -392,3 +392,156 @@ class TestGlobalPlayerServiceInstance:
|
||||
# But same configuration
|
||||
assert service1.model_class == service2.model_class
|
||||
assert service1.endpoint == service2.endpoint
|
||||
|
||||
|
||||
class TestPlayerTeamUpdateWithDemWeek:
|
||||
"""Test player team update functionality with dem_week parameter."""
|
||||
|
||||
@pytest.fixture
|
||||
def mock_client(self):
|
||||
"""Mock API client."""
|
||||
client = AsyncMock()
|
||||
return client
|
||||
|
||||
@pytest.fixture
|
||||
def player_service_instance(self, mock_client):
|
||||
"""Create PlayerService instance with mocked client."""
|
||||
service = PlayerService()
|
||||
service._client = mock_client
|
||||
return service
|
||||
|
||||
def create_player_data(
|
||||
self, player_id: int, name: str, team_id: int = 5, position: str = "C", **kwargs
|
||||
):
|
||||
"""Create complete player data for testing."""
|
||||
base_data = {
|
||||
"id": player_id,
|
||||
"name": name,
|
||||
"wara": 2.5,
|
||||
"season": 12,
|
||||
"team_id": team_id,
|
||||
"image": f"https://example.com/player{player_id}.jpg",
|
||||
"pos_1": position,
|
||||
}
|
||||
base_data.update(kwargs)
|
||||
return base_data
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_player_team_with_dem_week(
|
||||
self, player_service_instance, mock_client
|
||||
):
|
||||
"""
|
||||
Test player team update with dem_week parameter.
|
||||
|
||||
This test verifies that when dem_week is provided, it is correctly
|
||||
included in the update dictionary passed to the API.
|
||||
"""
|
||||
player_id = 123
|
||||
new_team_id = 5
|
||||
dem_week = 15
|
||||
|
||||
# Mock the API response
|
||||
mock_client.patch.return_value = self.create_player_data(
|
||||
player_id, "Test Player", team_id=new_team_id
|
||||
)
|
||||
|
||||
result = await player_service_instance.update_player_team(
|
||||
player_id, new_team_id, dem_week=dem_week
|
||||
)
|
||||
|
||||
# Verify result
|
||||
assert result is not None
|
||||
assert result.team_id == new_team_id
|
||||
|
||||
# Verify API call included dem_week
|
||||
mock_client.patch.assert_called_once_with(
|
||||
"players",
|
||||
{"team_id": new_team_id, "dem_week": dem_week},
|
||||
player_id,
|
||||
use_query_params=True
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_player_team_without_dem_week(
|
||||
self, player_service_instance, mock_client
|
||||
):
|
||||
"""
|
||||
Test player team update without dem_week parameter maintains backwards compatibility.
|
||||
|
||||
This test verifies that when dem_week is not provided (None), it is NOT
|
||||
included in the update dictionary, maintaining backwards compatibility with
|
||||
admin commands that don't need to set dem_week.
|
||||
"""
|
||||
player_id = 123
|
||||
new_team_id = 5
|
||||
|
||||
# Mock the API response
|
||||
mock_client.patch.return_value = self.create_player_data(
|
||||
player_id, "Test Player", team_id=new_team_id
|
||||
)
|
||||
|
||||
result = await player_service_instance.update_player_team(
|
||||
player_id, new_team_id
|
||||
)
|
||||
|
||||
# Verify result
|
||||
assert result is not None
|
||||
assert result.team_id == new_team_id
|
||||
|
||||
# Verify API call did NOT include dem_week
|
||||
call_args = mock_client.patch.call_args[0][1]
|
||||
assert "dem_week" not in call_args
|
||||
assert call_args == {"team_id": new_team_id}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_player_team_dem_week_zero(
|
||||
self, player_service_instance, mock_client
|
||||
):
|
||||
"""
|
||||
Test that dem_week=0 IS included in the update.
|
||||
|
||||
This test verifies that dem_week=0 is treated as a valid value and included
|
||||
in the update, since 0 is not None and may be a valid week number.
|
||||
"""
|
||||
player_id = 123
|
||||
new_team_id = 5
|
||||
dem_week = 0
|
||||
|
||||
# Mock the API response
|
||||
mock_client.patch.return_value = self.create_player_data(
|
||||
player_id, "Test Player", team_id=new_team_id
|
||||
)
|
||||
|
||||
await player_service_instance.update_player_team(
|
||||
player_id, new_team_id, dem_week=dem_week
|
||||
)
|
||||
|
||||
# Verify API call included dem_week=0
|
||||
call_args = mock_client.patch.call_args[0][1]
|
||||
assert call_args == {"team_id": new_team_id, "dem_week": 0}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_player_team_dem_week_none_explicit(
|
||||
self, player_service_instance, mock_client
|
||||
):
|
||||
"""
|
||||
Test that explicitly passing dem_week=None does NOT include it in updates.
|
||||
|
||||
This test verifies that when dem_week=None is explicitly passed, it behaves
|
||||
the same as not passing the parameter at all.
|
||||
"""
|
||||
player_id = 123
|
||||
new_team_id = 5
|
||||
|
||||
# Mock the API response
|
||||
mock_client.patch.return_value = self.create_player_data(
|
||||
player_id, "Test Player", team_id=new_team_id
|
||||
)
|
||||
|
||||
await player_service_instance.update_player_team(
|
||||
player_id, new_team_id, dem_week=None
|
||||
)
|
||||
|
||||
# Verify API call did NOT include dem_week
|
||||
call_args = mock_client.patch.call_args[0][1]
|
||||
assert "dem_week" not in call_args
|
||||
|
||||
@ -289,7 +289,8 @@ class SubmitConfirmationModal(discord.ui.Modal):
|
||||
for txn in created_transactions:
|
||||
updated_player = await player_service.update_player_team(
|
||||
txn.player.id,
|
||||
txn.newteam.id
|
||||
txn.newteam.id,
|
||||
dem_week=current_state.week
|
||||
)
|
||||
player_updates.append(updated_player)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user