major-domo-v2/models/transaction.py
2025-09-24 09:32:04 -05:00

127 lines
4.3 KiB
Python

"""
Transaction models for SBA transaction management
Represents transactions and player moves based on actual API structure.
"""
from typing import Optional, List
from pydantic import Field
from models.base import SBABaseModel
from models.player import Player
from models.team import Team
class Transaction(SBABaseModel):
"""
Represents a single player transaction (move).
Based on actual API response structure:
{
"id": 27787,
"week": 10,
"player": { ... },
"oldteam": { ... },
"newteam": { ... },
"season": 12,
"moveid": "Season-012-Week-10-19-13:04:41",
"cancelled": false,
"frozen": false
}
"""
# Core transaction fields
id: int = Field(..., description="Transaction ID")
week: int = Field(..., description="Week this transaction is for")
season: int = Field(..., description="Season number")
moveid: str = Field(..., description="Unique move identifier string")
# Player and team information
player: Player = Field(..., description="Player being moved")
oldteam: Team = Field(..., description="Team player is leaving")
newteam: Team = Field(..., description="Team player is joining")
# Transaction status
cancelled: bool = Field(default=False, description="Whether transaction is cancelled")
frozen: bool = Field(default=False, description="Whether transaction is frozen")
@property
def is_cancelled(self) -> bool:
"""Check if transaction is cancelled."""
return self.cancelled
@property
def is_frozen(self) -> bool:
"""Check if transaction is frozen (scheduled for processing)."""
return self.frozen
@property
def is_pending(self) -> bool:
"""Check if transaction is pending (not frozen, not cancelled)."""
return not self.frozen and not self.cancelled
@property
def status_emoji(self) -> str:
"""Emoji representation of transaction status."""
if self.cancelled:
return ""
elif self.frozen:
return "❄️"
else:
return ""
@property
def status_text(self) -> str:
"""Human readable status."""
if self.cancelled:
return "Cancelled"
elif self.frozen:
return "Frozen"
else:
return "Pending"
@property
def move_description(self) -> str:
"""Human readable description of the move."""
return f"{self.player.name}: {self.oldteam.abbrev}{self.newteam.abbrev}"
@property
def is_major_league_move(self) -> bool:
"""Check if this move involves major league rosters."""
# Major league if neither team ends with 'MiL' and not FA
from_is_major = self.oldteam.abbrev != 'FA' and not self.oldteam.abbrev.endswith('MiL')
to_is_major = self.newteam.abbrev != 'FA' and not self.newteam.abbrev.endswith('MiL')
return from_is_major or to_is_major
def __str__(self):
return f"📋 Week {self.week}: {self.move_description} - {self.status_emoji} {self.status_text}"
class RosterValidation(SBABaseModel):
"""Results of roster legality validation."""
is_legal: bool = Field(..., description="Whether the roster is legal")
errors: List[str] = Field(default_factory=list, description="List of validation errors")
warnings: List[str] = Field(default_factory=list, description="List of validation warnings")
# Roster statistics
total_players: int = Field(default=0, description="Total players on roster")
active_players: int = Field(default=0, description="Active players")
il_players: int = Field(default=0, description="Players on IL")
minor_league_players: int = Field(default=0, description="Minor league players")
total_sWAR: float = Field(default=0.0, description="Total team sWAR")
@property
def has_issues(self) -> bool:
"""Whether there are any errors or warnings."""
return len(self.errors) > 0 or len(self.warnings) > 0
@property
def status_emoji(self) -> str:
"""Emoji representation of validation status."""
if not self.is_legal:
return ""
elif self.warnings:
return "⚠️"
else:
return ""