""" Multi-tenant context resolver for service_auto. Pattern-ul urmează `modules/reports`: - `server_id` vine din JWT (`request.state.server_id`), propagat la `oracle_pool.get_connection(server_id)`. - `schema` se rezolvă din `CONTAFIN_ORACLE.V_NOM_FIRME` bazat pe `id_firma`, pe serverul utilizatorului. - Rezultatul e cached in-process 24h per (company_id, server_id). NU introduce hardcodări de schemă sau server_id în service_auto. Toate query-urile SQL trebuie să folosească `f"{schema}.{TABLE}"`, iar toate `get_connection()` trebuie să primească `server_id`. """ import time from typing import Optional, Tuple import oracledb from fastapi import HTTPException from shared.database.oracle_pool import oracle_pool from .. import logger _SCHEMA_TTL = 86400 # 24h — schema / firma binding changes via DB migration, not runtime _schema_cache: dict = {} async def get_schema(company_id: int, server_id: Optional[str]) -> str: """ Rezolvă schema Oracle pentru o firmă pe serverul curent al utilizatorului. Query pe `CONTAFIN_ORACLE.V_NOM_FIRME` (prezent pe fiecare server în arhitectura ROA2WEB). Cached per (company_id, server_id) 24h. Raises 422 dacă firma nu există pe serverul respectiv (misconfiguration). """ key = (company_id, server_id or "") entry: Optional[Tuple[float, str]] = _schema_cache.get(key) if entry and (time.monotonic() - entry[0]) < _SCHEMA_TTL: return entry[1] try: async with oracle_pool.get_connection(server_id) as conn: with conn.cursor() as cur: cur.execute( "SELECT schema FROM CONTAFIN_ORACLE.V_NOM_FIRME WHERE id_firma = :id", {"id": company_id}, ) row = cur.fetchone() except oracledb.DatabaseError: logger.error("service_auto._context.get_schema Oracle error", exc_info=True) raise HTTPException(status_code=503, detail="Eroare la rezolvarea schemei firmei") if not row or not row[0]: raise HTTPException( status_code=422, detail=f"Firma {company_id} nu are schemă configurată pe serverul curent.", ) schema = row[0] _schema_cache[key] = (time.monotonic(), schema) return schema def reset_schema_cache() -> None: """Test helper — clear the schema cache.""" _schema_cache.clear()