Coverage for models/matches.py: 91.23%
55 statements
« prev ^ index » next coverage.py v7.10.6, created at 2026-04-13 00:07 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2026-04-13 00:07 +0000
1"""
2Match-related Pydantic models.
3"""
5from datetime import datetime
7from pydantic import BaseModel
10class EnhancedMatch(BaseModel):
11 """Model for creating or updating a match with full context."""
13 match_date: str
14 home_team_id: int
15 away_team_id: int
16 home_score: int
17 away_score: int
18 season_id: int
19 age_group_id: int
20 match_type_id: int
21 division_id: int | None = None
22 status: str | None = "scheduled" # scheduled, played, postponed, cancelled (maps to match_status in DB)
23 created_by: str | None = None # User ID who created the match (for audit trail)
24 updated_by: str | None = None # User ID who last updated the match
25 source: str = "manual" # Source: manual, match-scraper, import
26 external_match_id: str | None = None # External match identifier (e.g., from match-scraper)
27 scheduled_kickoff: datetime | None = None # Scheduled kickoff datetime in UTC
28 home_penalty_score: int | None = None # Penalty shootout score (only when regulation ends in draw)
29 away_penalty_score: int | None = None
32class MatchPatch(BaseModel):
33 """Model for partial match updates."""
35 home_score: int | None = None
36 away_score: int | None = None
37 match_status: str | None = None
38 match_date: str | None = None
39 home_team_id: int | None = None
40 away_team_id: int | None = None
41 season_id: int | None = None
42 age_group_id: int | None = None
43 match_type_id: int | None = None
44 division_id: int | None = None
45 status: str | None = None
46 external_match_id: str | None = None # External match identifier
47 scheduled_kickoff: datetime | None = None # Scheduled kickoff datetime in UTC
48 home_penalty_score: int | None = None # Penalty shootout score (only when regulation ends in draw)
49 away_penalty_score: int | None = None
51 class Config:
52 # Validation for scores
53 @staticmethod
54 def validate_score(v):
55 if v is not None and v < 0:
56 raise ValueError("Score must be non-negative")
57 return v
60class MatchSubmissionData(BaseModel):
61 """
62 Match data for async submission to Celery queue.
63 This model accepts flexible data from match-scraper.
64 """
66 home_team: str # Team name (will be looked up)
67 away_team: str # Team name (will be looked up)
68 match_date: str # ISO format date
69 season: str # Season name (e.g., "2024-25")
70 age_group: str | None = None
71 division: str | None = None
72 home_score: int | None = None
73 away_score: int | None = None
74 match_status: str = "scheduled" # scheduled, live, played, postponed, cancelled
75 match_type: str | None = None
76 location: str | None = None
77 external_match_id: str | None = None # External identifier for deduplication