"""Medii RAR per cont (PRD 5.20): disponibilitate + default efectiv. Sursa UNICA de adevar pentru REQ-DISP / REQ-DEFAULT: vizibilitatea selector/toggle in UI, validarea tintei in API si decizia worker-ului citesc TOATE de aici, ca sa decida identic. Un mediu ('test'|'prod') e *disponibil* pentru un cont daca e activat (bifa) SI are credentiale (slot per-mediu non-gol). Din disponibilitate decurge tot UX-ul: - 0 medii -> nicio tinta; trimiterea web e blocata, API cade pe ancora globala. - 1 mediu -> tinta implicita (acel mediu), fara selector. - 2 medii -> selector la import + toggle in statusbar + alegere in API. Functii PURE (fara DB) peste un rand de cont (sqlite3.Row sau dict). Helperele cu `conn` incarca randul si deleaga. """ from __future__ import annotations import sqlite3 from typing import Any VALID_ENVS: tuple[str, str] = ("test", "prod") def _field(account: Any, key: str, default: Any = None) -> Any: """Citire toleranta a unui camp de cont (dict sau sqlite3.Row, camp posibil absent).""" if account is None: return default if isinstance(account, dict): return account.get(key, default) try: return account[key] # sqlite3.Row except (IndexError, KeyError): return default def _are_creds(account: Any, env: str) -> bool: creds = _field(account, f"rar_creds_{env}_enc", None) return bool(creds and str(creds).strip()) def _enabled(account: Any, env: str) -> bool: return int(_field(account, f"rar_{env}_enabled", 0) or 0) == 1 def medii_disponibile(account: Any) -> list[str]: """Subset din ('test','prod') = activat AND creds prezente. Ordine stabila test str | None: """Mediul tinta implicit al contului (REQ-DEFAULT). Mereu unul din mediile disponibile: default-ul contului daca inca e disponibil, altfel singurul disponibil; daca 0 disponibile -> None (nicio tinta). """ disp = medii_disponibile(account) if not disp: return None default = _field(account, "rar_env_default", "prod") if default in disp: return default return disp[0] # --------------------------------------------------------------------------- # # Helpere cu conexiune # # --------------------------------------------------------------------------- # _ACCOUNT_ENV_COLS = ( "id, rar_test_enabled, rar_prod_enabled, " "rar_creds_test_enc, rar_creds_prod_enc, rar_env_default" ) def load_account_env(conn: sqlite3.Connection, account_id: int) -> sqlite3.Row | None: """Randul de cont cu exact coloanele de mediu (pentru medii_disponibile/rar_env_efectiv).""" from .mapping import account_or_default return conn.execute( f"SELECT {_ACCOUNT_ENV_COLS} FROM accounts WHERE id=?", (account_or_default(account_id),), ).fetchone() def medii_disponibile_cont(conn: sqlite3.Connection, account_id: int) -> list[str]: return medii_disponibile(load_account_env(conn, account_id)) def rar_env_efectiv_cont(conn: sqlite3.Connection, account_id: int) -> str | None: return rar_env_efectiv(load_account_env(conn, account_id))