from datetime import date from rest_framework import serializers from apps.competitions.models import Competition, Season from apps.players.models import Player from apps.stats.models import PlayerSeason from apps.teams.models import Team class CompetitionSerializer(serializers.ModelSerializer): country = serializers.CharField(source="country.name", allow_null=True) class Meta: model = Competition fields = [ "id", "name", "slug", "competition_type", "gender", "level", "country", "is_active", ] class TeamSerializer(serializers.ModelSerializer): country = serializers.CharField(source="country.name", allow_null=True) class Meta: model = Team fields = ["id", "name", "short_name", "slug", "country", "is_national_team"] class SeasonSerializer(serializers.ModelSerializer): class Meta: model = Season fields = ["id", "label", "start_date", "end_date", "is_current"] class PlayerListSerializer(serializers.ModelSerializer): nationality = serializers.CharField(source="nationality.name", allow_null=True) nominal_position = serializers.CharField(source="nominal_position.code", allow_null=True) inferred_role = serializers.CharField(source="inferred_role.name", allow_null=True) origin_competition = serializers.CharField(source="origin_competition.name", allow_null=True) origin_team = serializers.CharField(source="origin_team.name", allow_null=True) class Meta: model = Player fields = [ "id", "full_name", "birth_date", "nationality", "nominal_position", "inferred_role", "origin_competition", "origin_team", "height_cm", "weight_kg", "dominant_hand", "is_active", ] class PlayerAliasSerializer(serializers.Serializer): alias = serializers.CharField() source = serializers.CharField(allow_blank=True) is_primary = serializers.BooleanField() class PlayerSeasonStatSerializer(serializers.Serializer): season = serializers.CharField(allow_null=True) team = serializers.CharField(allow_null=True) competition = serializers.CharField(allow_null=True) games_played = serializers.IntegerField() minutes_played = serializers.IntegerField() points = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True) rebounds = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True) assists = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True) steals = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True) blocks = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True) turnovers = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True) fg_pct = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True) three_pct = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True) ft_pct = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True) player_efficiency_rating = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True) class PlayerDetailSerializer(serializers.ModelSerializer): nationality = serializers.CharField(source="nationality.name", allow_null=True) nominal_position = serializers.CharField(source="nominal_position.name", allow_null=True) inferred_role = serializers.CharField(source="inferred_role.name", allow_null=True) origin_competition = serializers.CharField(source="origin_competition.name", allow_null=True) origin_team = serializers.CharField(source="origin_team.name", allow_null=True) age = serializers.SerializerMethodField() aliases = serializers.SerializerMethodField() season_stats = serializers.SerializerMethodField() class Meta: model = Player fields = [ "id", "full_name", "birth_date", "age", "nationality", "nominal_position", "inferred_role", "origin_competition", "origin_team", "height_cm", "weight_kg", "dominant_hand", "aliases", "season_stats", ] def get_age(self, obj): if not obj.birth_date: return None today = date.today() return today.year - obj.birth_date.year - ( (today.month, today.day) < (obj.birth_date.month, obj.birth_date.day) ) def get_aliases(self, obj): return PlayerAliasSerializer(obj.aliases.all(), many=True).data def get_season_stats(self, obj): rows = ( PlayerSeason.objects.filter(player=obj) .select_related("season", "team", "competition", "stats") .order_by("-season__start_date", "-id") ) payload = [] for row in rows: stats = getattr(row, "stats", None) payload.append( { "season": row.season.label if row.season else None, "team": row.team.name if row.team else None, "competition": row.competition.name if row.competition else None, "games_played": row.games_played, "minutes_played": row.minutes_played, "points": getattr(stats, "points", None), "rebounds": getattr(stats, "rebounds", None), "assists": getattr(stats, "assists", None), "steals": getattr(stats, "steals", None), "blocks": getattr(stats, "blocks", None), "turnovers": getattr(stats, "turnovers", None), "fg_pct": getattr(stats, "fg_pct", None), "three_pct": getattr(stats, "three_pct", None), "ft_pct": getattr(stats, "ft_pct", None), "player_efficiency_rating": getattr(stats, "player_efficiency_rating", None), } ) return PlayerSeasonStatSerializer(payload, many=True).data