Coverage for dao/season_dao.py: 28.00%
98 statements
« prev ^ index » next coverage.py v7.10.6, created at 2026-04-15 12:24 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2026-04-15 12:24 +0000
1"""
2Season Data Access Object.
4Handles all database operations related to seasons and age groups including:
5- Season CRUD operations
6- Age group CRUD operations
7- Current/active season queries
8"""
10from datetime import date
12import structlog
14from dao.base_dao import BaseDAO, dao_cache, invalidates_cache
16logger = structlog.get_logger()
18# Cache patterns for invalidation
19SEASONS_CACHE_PATTERN = "mt:dao:seasons:*"
20AGE_GROUPS_CACHE_PATTERN = "mt:dao:age_groups:*"
23class SeasonDAO(BaseDAO):
24 """Data access object for season and age group operations."""
26 # === Age Group Query Methods ===
28 @dao_cache("age_groups:all")
29 def get_all_age_groups(self) -> list[dict]:
30 """Get all age groups."""
31 try:
32 response = self.client.table("age_groups").select("*").order("name").execute()
33 return response.data
34 except Exception:
35 logger.exception("Error querying age groups")
36 return []
38 def get_age_group_by_name(self, name: str) -> dict | None:
39 """Get an age group by name (case-insensitive exact match).
41 Returns the age group record (id, name).
42 For match-scraper integration, this helps look up age groups by name.
43 No caching - used for scraper lookups.
44 """
45 try:
46 response = (
47 self.client.table("age_groups")
48 .select("id, name")
49 .ilike("name", name) # Case-insensitive match
50 .limit(1)
51 .execute()
52 )
54 if response.data and len(response.data) > 0:
55 return response.data[0]
56 return None
58 except Exception:
59 logger.exception("Error getting age group by name", age_group_name=name)
60 return None
62 # === Age Group CRUD Methods ===
64 @invalidates_cache(AGE_GROUPS_CACHE_PATTERN)
65 def create_age_group(self, name: str) -> dict:
66 """Create a new age group."""
67 try:
68 result = self.client.table("age_groups").insert({"name": name}).execute()
69 return result.data[0]
70 except Exception as e:
71 logger.exception("Error creating age group")
72 raise e
74 @invalidates_cache(AGE_GROUPS_CACHE_PATTERN)
75 def update_age_group(self, age_group_id: int, name: str) -> dict | None:
76 """Update an age group."""
77 try:
78 result = self.client.table("age_groups").update({"name": name}).eq("id", age_group_id).execute()
79 return result.data[0] if result.data else None
80 except Exception as e:
81 logger.exception("Error updating age group")
82 raise e
84 @invalidates_cache(AGE_GROUPS_CACHE_PATTERN)
85 def delete_age_group(self, age_group_id: int) -> bool:
86 """Delete an age group."""
87 try:
88 result = self.client.table("age_groups").delete().eq("id", age_group_id).execute()
89 return len(result.data) > 0
90 except Exception as e:
91 logger.exception("Error deleting age group")
92 raise e
94 # === Season Query Methods ===
96 @dao_cache("seasons:all")
97 def get_all_seasons(self) -> list[dict]:
98 """Get all seasons."""
99 try:
100 response = self.client.table("seasons").select("*").order("start_date", desc=True).execute()
101 return response.data
102 except Exception:
103 logger.exception("Error querying seasons")
104 return []
106 @dao_cache("seasons:current")
107 def get_current_season(self) -> dict | None:
108 """Get the current active season based on today's date."""
109 try:
110 today = date.today().isoformat()
112 response = (
113 self.client.table("seasons")
114 .select("*")
115 .lte("start_date", today)
116 .gte("end_date", today)
117 .single()
118 .execute()
119 )
121 return response.data
122 except Exception as e:
123 logger.info("No current season found", error=str(e))
124 return None
126 @dao_cache("seasons:active")
127 def get_active_seasons(self) -> list[dict]:
128 """Get active seasons (current and future) for scheduling new matches."""
129 try:
130 today = date.today().isoformat()
132 response = (
133 self.client.table("seasons")
134 .select("*")
135 .gte("end_date", today)
136 .order("start_date", desc=False)
137 .execute()
138 )
140 return response.data
141 except Exception:
142 logger.exception("Error querying active seasons")
143 return []
145 # === Season CRUD Methods ===
147 @invalidates_cache(SEASONS_CACHE_PATTERN)
148 def create_season(self, name: str, start_date: str, end_date: str) -> dict:
149 """Create a new season."""
150 try:
151 result = (
152 self.client.table("seasons")
153 .insert({"name": name, "start_date": start_date, "end_date": end_date})
154 .execute()
155 )
156 return result.data[0]
157 except Exception as e:
158 logger.exception("Error creating season")
159 raise e
161 @invalidates_cache(SEASONS_CACHE_PATTERN)
162 def update_season(self, season_id: int, name: str, start_date: str, end_date: str) -> dict | None:
163 """Update a season."""
164 try:
165 result = (
166 self.client.table("seasons")
167 .update({"name": name, "start_date": start_date, "end_date": end_date})
168 .eq("id", season_id)
169 .execute()
170 )
171 return result.data[0] if result.data else None
172 except Exception as e:
173 logger.exception("Error updating season")
174 raise e
176 @invalidates_cache(SEASONS_CACHE_PATTERN)
177 def delete_season(self, season_id: int) -> bool:
178 """Delete a season."""
179 try:
180 result = self.client.table("seasons").delete().eq("id", season_id).execute()
181 return len(result.data) > 0
182 except Exception as e:
183 logger.exception("Error deleting season")
184 raise e