418 lines
11 KiB
Python
418 lines
11 KiB
Python
from db import get_connection
|
|
from repositories.team_repository import get_team_id_by_external_id
|
|
|
|
|
|
def upsert_coach(
|
|
external_id: str,
|
|
team_external_id: str,
|
|
player: str,
|
|
lastname: str = "",
|
|
name: str = "",
|
|
born: str = "",
|
|
amplua: str = "",
|
|
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 coaches (
|
|
external_id,
|
|
team_id,
|
|
player,
|
|
lastname,
|
|
name,
|
|
born,
|
|
amplua,
|
|
is_active,
|
|
created_at,
|
|
updated_at
|
|
)
|
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())
|
|
ON CONFLICT (external_id)
|
|
DO UPDATE SET
|
|
team_id = EXCLUDED.team_id,
|
|
player = EXCLUDED.player,
|
|
lastname = EXCLUDED.lastname,
|
|
name = EXCLUDED.name,
|
|
born = EXCLUDED.born,
|
|
amplua = EXCLUDED.amplua,
|
|
is_active = EXCLUDED.is_active,
|
|
updated_at = NOW();
|
|
"""
|
|
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
query,
|
|
(
|
|
str(external_id).strip(),
|
|
team_id,
|
|
player.strip(),
|
|
lastname.strip(),
|
|
name.strip(),
|
|
born.strip(),
|
|
amplua.strip(),
|
|
is_active,
|
|
),
|
|
)
|
|
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_coach_id_by_name_and_team(full_name: str, team_id: int) -> int | None:
|
|
query = """
|
|
SELECT id
|
|
FROM coaches
|
|
WHERE team_id = %s
|
|
AND LOWER(player) = 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_coach_id_by_external_id(external_id: str) -> int | None:
|
|
query = """
|
|
SELECT id
|
|
FROM coaches
|
|
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[0] if row else None
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
def _split_coach_name_for_autocreate(full_name: str) -> tuple[str, str]:
|
|
parts = [p.strip() for p in str(full_name or "").replace("\xa0", " ").split() if p.strip()]
|
|
if not parts:
|
|
return "", ""
|
|
if len(parts) == 1:
|
|
return "", parts[0]
|
|
first_name = parts[0]
|
|
last_name = " ".join(parts[1:])
|
|
return first_name, last_name
|
|
|
|
|
|
def create_coach_from_lineup(
|
|
team_id: int,
|
|
external_id: str = "",
|
|
full_name: str = "",
|
|
role: str = "",
|
|
) -> int | None:
|
|
"""Создаёт минимальную карточку тренера из протокола матча."""
|
|
full_name = str(full_name or "").strip()
|
|
if not full_name:
|
|
return None
|
|
|
|
first_name, last_name = _split_coach_name_for_autocreate(full_name)
|
|
external_id = str(external_id or "").strip()
|
|
role = str(role or "").strip()
|
|
|
|
query = """
|
|
INSERT INTO coaches (
|
|
external_id,
|
|
team_id,
|
|
player,
|
|
lastname,
|
|
name,
|
|
amplua,
|
|
is_active,
|
|
created_at,
|
|
updated_at
|
|
)
|
|
VALUES (NULLIF(%s, ''), %s, %s, %s, %s, %s, TRUE, NOW(), NOW())
|
|
ON CONFLICT (external_id)
|
|
DO UPDATE SET
|
|
team_id = EXCLUDED.team_id,
|
|
player = COALESCE(NULLIF(EXCLUDED.player, ''), coaches.player),
|
|
lastname = COALESCE(NULLIF(EXCLUDED.lastname, ''), coaches.lastname),
|
|
name = COALESCE(NULLIF(EXCLUDED.name, ''), coaches.name),
|
|
amplua = COALESCE(NULLIF(EXCLUDED.amplua, ''), coaches.amplua),
|
|
is_active = TRUE,
|
|
updated_at = NOW()
|
|
RETURNING id;
|
|
"""
|
|
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
query,
|
|
(
|
|
external_id,
|
|
team_id,
|
|
full_name,
|
|
last_name,
|
|
first_name,
|
|
role,
|
|
),
|
|
)
|
|
row = cur.fetchone()
|
|
conn.commit()
|
|
return row[0] if row else None
|
|
except Exception:
|
|
conn.rollback()
|
|
raise
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def search_coaches_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
|
|
c.id,
|
|
c.player,
|
|
c.external_id,
|
|
c.amplua,
|
|
t.name AS team_name
|
|
FROM coaches c
|
|
LEFT JOIN teams t ON t.id = c.team_id
|
|
WHERE
|
|
c.player ILIKE %s
|
|
OR COALESCE(c.external_id, '') ILIKE %s
|
|
OR COALESCE(c.amplua, '') ILIKE %s
|
|
OR COALESCE(t.name, '') ILIKE %s
|
|
ORDER BY c.player ASC, c.id ASC
|
|
LIMIT 200
|
|
""",
|
|
(pattern, pattern, pattern, pattern),
|
|
)
|
|
else:
|
|
cur.execute(
|
|
"""
|
|
SELECT
|
|
c.id,
|
|
c.player,
|
|
c.external_id,
|
|
c.amplua,
|
|
t.name AS team_name
|
|
FROM coaches c
|
|
LEFT JOIN teams t ON t.id = c.team_id
|
|
ORDER BY c.id DESC
|
|
LIMIT 200
|
|
"""
|
|
)
|
|
rows = cur.fetchall()
|
|
|
|
return [
|
|
{
|
|
"id": row[0],
|
|
"full_name": row[1] or "",
|
|
"external_id": row[2] or "",
|
|
"role": row[3] or "",
|
|
"team_name": row[4] or "",
|
|
}
|
|
for row in rows
|
|
]
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def get_coach_by_id(coach_id: int) -> dict | None:
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"""
|
|
SELECT
|
|
c.id,
|
|
c.player,
|
|
c.external_id,
|
|
c.amplua,
|
|
c.team_id,
|
|
t.name AS team_name
|
|
FROM coaches c
|
|
LEFT JOIN teams t ON t.id = c.team_id
|
|
WHERE c.id = %s
|
|
LIMIT 1
|
|
""",
|
|
(coach_id,),
|
|
)
|
|
row = cur.fetchone()
|
|
|
|
if not row:
|
|
return None
|
|
|
|
return {
|
|
"id": row[0],
|
|
"full_name": row[1] or "",
|
|
"external_id": row[2] or "",
|
|
"role": row[3] or "",
|
|
"team_id": row[4],
|
|
"team_name": row[5] or "",
|
|
}
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def get_coach_by_id(coach_id: int) -> dict | None:
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"""
|
|
SELECT
|
|
c.id,
|
|
c.player,
|
|
c.external_id,
|
|
c.amplua,
|
|
c.team_id,
|
|
t.name AS team_name
|
|
FROM coaches c
|
|
LEFT JOIN teams t ON t.id = c.team_id
|
|
WHERE c.id = %s
|
|
LIMIT 1
|
|
""",
|
|
(coach_id,),
|
|
)
|
|
row = cur.fetchone()
|
|
|
|
if not row:
|
|
return None
|
|
|
|
return {
|
|
"id": row[0],
|
|
"full_name": row[1] or "",
|
|
"external_id": row[2] or "",
|
|
"role": row[3] or "",
|
|
"team_id": row[4],
|
|
"team_name": row[5] or "",
|
|
}
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def update_coach_admin(
|
|
coach_id: int,
|
|
full_name: str = "",
|
|
external_id: str = "",
|
|
role: str = "",
|
|
) -> None:
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"""
|
|
UPDATE coaches
|
|
SET
|
|
player = %s,
|
|
external_id = NULLIF(%s, ''),
|
|
amplua = %s
|
|
WHERE id = %s
|
|
""",
|
|
(
|
|
full_name.strip(),
|
|
external_id.strip(),
|
|
role.strip(),
|
|
coach_id,
|
|
),
|
|
)
|
|
conn.commit()
|
|
except Exception:
|
|
conn.rollback()
|
|
raise
|
|
finally:
|
|
conn.close()
|
|
|
|
def create_coach_admin(
|
|
team_id: int,
|
|
full_name: str,
|
|
first_name: str = "",
|
|
last_name: str = "",
|
|
external_id: str = "",
|
|
birth_date: str = "",
|
|
role: str = "",
|
|
is_active: bool = True,
|
|
) -> int:
|
|
"""Создаёт тренера вручную из административного раздела."""
|
|
query = """
|
|
INSERT INTO coaches (
|
|
external_id,
|
|
team_id,
|
|
player,
|
|
lastname,
|
|
name,
|
|
born,
|
|
amplua,
|
|
is_active,
|
|
created_at,
|
|
updated_at
|
|
)
|
|
VALUES (
|
|
NULLIF(%s, ''), %s, %s, %s, %s, NULLIF(%s, ''), %s, %s, NOW(), NOW()
|
|
)
|
|
RETURNING id;
|
|
"""
|
|
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
query,
|
|
(
|
|
external_id.strip(),
|
|
int(team_id),
|
|
full_name.strip(),
|
|
last_name.strip(),
|
|
first_name.strip(),
|
|
birth_date.strip(),
|
|
role.strip(),
|
|
bool(is_active),
|
|
),
|
|
)
|
|
row = cur.fetchone()
|
|
conn.commit()
|
|
return int(row[0])
|
|
except Exception:
|
|
conn.rollback()
|
|
raise
|
|
finally:
|
|
conn.close()
|