Files
WFL/repositories/player_repository.py

449 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()
PLAYER_ADMIN_SORT_COLUMNS = {
"id": "p.id",
"full_name": "p.full_name",
"first_name": "p.first_name",
"last_name": "p.last_name",
"external_id": "p.external_id",
"position": "p.position",
"team_name": "t.name",
"photo": "p.photo_enabled",
}
def ensure_player_photo_enabled_column() -> None:
"""Добавляет флаг использования фото игрока, если база ещё не обновлена."""
conn = get_connection()
try:
with conn.cursor() as cur:
cur.execute(
"""
ALTER TABLE players
ADD COLUMN IF NOT EXISTS photo_enabled BOOLEAN NOT NULL DEFAULT FALSE;
"""
)
conn.commit()
except Exception:
conn.rollback()
raise
finally:
conn.close()
def _normalize_player_sort(sort_by: str = "id", sort_dir: str = "desc") -> tuple[str, str, str, str]:
sort_by = (sort_by or "id").strip()
if sort_by not in PLAYER_ADMIN_SORT_COLUMNS:
sort_by = "id"
sort_dir = (sort_dir or "desc").strip().lower()
if sort_dir not in {"asc", "desc"}:
sort_dir = "desc"
return sort_by, sort_dir, PLAYER_ADMIN_SORT_COLUMNS[sort_by], sort_dir.upper()
def search_players_for_admin(q: str = "", sort_by: str = "id", sort_dir: str = "desc") -> list[dict]:
sort_by, sort_dir, order_column, order_direction = _normalize_player_sort(sort_by, sort_dir)
limit = 200
conn = get_connection()
try:
with conn.cursor() as cur:
params: list = []
where_sql = ""
if q.strip():
pattern = f"%{q.strip()}%"
where_sql = """
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
OR COALESCE(t.name, '') ILIKE %s
"""
params.extend([pattern, pattern, pattern, pattern, pattern])
params.append(limit)
cur.execute(
f"""
SELECT
p.id,
p.full_name,
p.first_name,
p.last_name,
p.external_id,
p.position,
COALESCE(t.name, '') AS team_name,
COALESCE(p.photo_enabled, FALSE) AS photo_enabled
FROM players p
LEFT JOIN teams t ON t.id = p.team_id
{where_sql}
ORDER BY {order_column} {order_direction} NULLS LAST, p.id ASC
LIMIT %s
""",
tuple(params),
)
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 "",
"team_name": row[6] or "",
"photo_enabled": bool(row[7]),
}
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,
COALESCE(t.name, '') AS team_name,
COALESCE(p.photo_enabled, FALSE) AS photo_enabled
FROM players p
LEFT JOIN teams t ON t.id = p.team_id
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 "",
"team_name": row[9] or "",
"photo_enabled": bool(row[10]),
}
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 = "",
photo_enabled: bool = False,
) -> 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, ''),
photo_enabled = %s,
updated_at = NOW()
WHERE id = %s
""",
(
full_name.strip(),
first_name.strip(),
last_name.strip(),
external_id.strip(),
position.strip(),
birth_date.strip(),
photo.strip(),
video.strip(),
bool(photo_enabled),
player_id,
),
)
conn.commit()
except Exception:
conn.rollback()
raise
finally:
conn.close()
def update_player_photo_enabled(player_id: int, photo_enabled: bool = False) -> None:
conn = get_connection()
try:
with conn.cursor() as cur:
cur.execute(
"""
UPDATE players
SET
photo_enabled = %s,
updated_at = NOW()
WHERE id = %s
""",
(bool(photo_enabled), player_id),
)
conn.commit()
except Exception:
conn.rollback()
raise
finally:
conn.close()