from db import get_connection from repositories.team_repository import get_team_id_by_external_id def normalize_birth_date_for_input(value) -> str: if not value: return "" text = str(value).strip() if not text: return "" # Уже нормальный формат для input[type=date] if len(text) == 10 and text[4] == "-" and text[7] == "-": return text # Формат ДД.ММ.ГГГГ -> YYYY-MM-DD if len(text) == 10 and text[2] == "." and text[5] == ".": dd, mm, yyyy = text.split(".") return f"{yyyy}-{mm}-{dd}" return "" def upsert_player( external_id: str, team_external_id: str, player: str, lastname: str = "", name: str = "", number: str = "", pos: str = "", amplua: str = "", born: str = "", games: int = 0, goals: int = 0, penaltys: int = 0, assists: int = 0, yellows: int = 0, reds: int = 0, is_active: bool = True, ) -> None: team_id = get_team_id_by_external_id(str(team_external_id).strip()) if team_id is None: raise ValueError(f"Team not found by external_id: {team_external_id}") query = """ INSERT INTO players ( external_id, team_id, full_name, first_name, last_name, number, position, is_active, pos, amplua, born, games, goals, penaltys, assists, yellows, reds, created_at, updated_at ) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW() ) ON CONFLICT (external_id) DO UPDATE SET team_id = EXCLUDED.team_id, full_name = EXCLUDED.full_name, first_name = EXCLUDED.first_name, last_name = EXCLUDED.last_name, number = EXCLUDED.number, position = EXCLUDED.position, is_active = EXCLUDED.is_active, pos = EXCLUDED.pos, amplua = EXCLUDED.amplua, born = EXCLUDED.born, games = EXCLUDED.games, goals = EXCLUDED.goals, penaltys = EXCLUDED.penaltys, assists = EXCLUDED.assists, yellows = EXCLUDED.yellows, reds = EXCLUDED.reds, updated_at = NOW(); """ conn = get_connection() try: with conn.cursor() as cur: cur.execute( query, ( str(external_id).strip(), team_id, player.strip(), name.strip(), lastname.strip(), str(number).strip(), amplua.strip(), is_active, pos.strip(), amplua.strip(), born.strip(), games, goals, penaltys, assists, yellows, reds, ), ) conn.commit() except Exception: conn.rollback() raise finally: conn.close() def get_match_by_external_id(external_id: str): query = """ SELECT id, external_id, home_team_id, away_team_id FROM matches WHERE external_id = %s LIMIT 1; """ conn = get_connection() try: with conn.cursor() as cur: cur.execute(query, (str(external_id).strip(),)) return cur.fetchone() finally: conn.close() def mark_match_parsed(external_id: str) -> None: query = """ UPDATE matches SET parsed = TRUE, parse_error = NULL, updated_at = NOW() WHERE external_id = %s; """ conn = get_connection() try: with conn.cursor() as cur: cur.execute(query, (str(external_id).strip(),)) conn.commit() except Exception: conn.rollback() raise finally: conn.close() def mark_match_parse_error(external_id: str, error_text: str) -> None: query = """ UPDATE matches SET parsed = FALSE, parse_error = %s, updated_at = NOW() WHERE external_id = %s; """ conn = get_connection() try: with conn.cursor() as cur: cur.execute(query, (str(error_text)[:2000], str(external_id).strip())) conn.commit() except Exception: conn.rollback() raise finally: conn.close() def get_player_id_by_name_and_team(full_name: str, team_id: int) -> int | None: query = """ SELECT id FROM players WHERE team_id = %s AND LOWER(full_name) = LOWER(%s) LIMIT 1; """ conn = get_connection() try: with conn.cursor() as cur: cur.execute(query, (team_id, full_name.strip())) row = cur.fetchone() return row[0] if row else None finally: conn.close() def get_player_id_by_external_id(external_id: str) -> int | None: query = """ SELECT id, position FROM players WHERE external_id = %s LIMIT 1; """ conn = get_connection() try: with conn.cursor() as cur: cur.execute(query, (str(external_id).strip(),)) row = cur.fetchone() return row if row else None finally: conn.close() from db import get_connection def search_players_for_admin(q: str = "") -> list[dict]: conn = get_connection() try: with conn.cursor() as cur: if q.strip(): pattern = f"%{q.strip()}%" cur.execute( """ SELECT p.id, p.full_name, p.first_name, p.last_name, p.external_id, p.position FROM players p WHERE p.full_name ILIKE %s OR p.first_name ILIKE %s OR p.last_name ILIKE %s OR COALESCE(p.external_id, '') ILIKE %s ORDER BY p.full_name ASC, p.id ASC LIMIT 200 """, (pattern, pattern, pattern, pattern), ) else: cur.execute( """ SELECT p.id, p.full_name, p.first_name, p.last_name, p.external_id, p.position FROM players p ORDER BY p.id DESC LIMIT 200 """ ) rows = cur.fetchall() return [ { "id": row[0], "full_name": row[1] or "", "first_name": row[2] or "", "last_name": row[3] or "", "external_id": row[4] or "", "position": row[5] or "", } for row in rows ] finally: conn.close() def get_player_by_id(player_id: int) -> dict | None: conn = get_connection() try: with conn.cursor() as cur: cur.execute( """ SELECT p.id, p.full_name, p.first_name, p.last_name, p.external_id, p.position, p.born, p.photo, p.video FROM players p WHERE p.id = %s LIMIT 1 """, (player_id,), ) row = cur.fetchone() if not row: return None return { "id": row[0], "full_name": row[1] or "", "first_name": row[2] or "", "last_name": row[3] or "", "external_id": row[4] or "", "position": row[5] or "", "birth_date": normalize_birth_date_for_input(row[6]), "photo": row[7] or "", "video": row[8] or "", } finally: conn.close() def update_player_admin( player_id: int, full_name: str = "", first_name: str = "", last_name: str = "", external_id: str = "", position: str = "", birth_date: str = "", photo: str = "", video: str = "", ) -> None: conn = get_connection() try: with conn.cursor() as cur: cur.execute( """ UPDATE players SET full_name = %s, first_name = %s, last_name = %s, external_id = NULLIF(%s, ''), position = %s, born = NULLIF(%s, '')::date, photo = NULLIF(%s, ''), video = NULLIF(%s, '') WHERE id = %s """, ( full_name.strip(), first_name.strip(), last_name.strip(), external_id.strip(), position.strip(), birth_date.strip(), photo.strip(), video.strip(), player_id, ), ) conn.commit() except Exception: conn.rollback() raise finally: conn.close()