# /opt/docker/dev/service_finder/backend/app/services/system_service.py """ Hierarchikus System Parameters szolgáltatás. A rendszerparaméterek prioritásos felülbírálást támogatnak: User > Region > Country > Global. """ import logging from typing import Optional, Any, Dict from sqlalchemy import select, func # HOZZÁADVA: func a NOW() híváshoz from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from app.models.system import SystemParameter, ParameterScope logger = logging.getLogger(__name__) class SystemService: """ Rendszerparaméterek kezelése hierarchikus scope-okkal. """ async def get_scoped_parameter( self, db: AsyncSession, key: str, user_id: Optional[str] = None, region_id: Optional[str] = None, country_code: Optional[str] = None, default: Any = None, ) -> Any: """ Lekéri a paraméter értékét a következő prioritási sorrendben: 1. USER scope (ha user_id megadva) 2. REGION scope (ha region_id megadva) 3. COUNTRY scope (ha country_code megadva) 4. GLOBAL scope Ha egy scope-ban nem található a paraméter, a következő scope-ot próbálja. Visszaadja a paraméter JSON értékét (általában dict), vagy a default értéket. :param db: Adatbázis munkamenet :param key: A paraméter kulcsa :param user_id: Felhasználó azonosítója (opcionális) :param region_id: Régió azonosítója (opcionális) :param country_code: Országkód (pl. 'HU', 'GB') (opcionális) :param default: Alapértelmezett érték, ha a paraméter nem található :return: A paraméter értéke (általában dict) vagy default """ # Prioritási sorrend: USER -> REGION -> COUNTRY -> GLOBAL scopes = [] if user_id: scopes.append((ParameterScope.USER, str(user_id))) if region_id: scopes.append((ParameterScope.REGION, str(region_id))) if country_code: scopes.append((ParameterScope.COUNTRY, str(country_code))) scopes.append((ParameterScope.GLOBAL, None)) for scope_level, scope_id in scopes: stmt = select(SystemParameter).where( SystemParameter.key == key, SystemParameter.scope_level == scope_level, SystemParameter.is_active == True, ) if scope_id is not None: stmt = stmt.where(SystemParameter.scope_id == scope_id) else: stmt = stmt.where(SystemParameter.scope_id.is_(None)) result = await db.execute(stmt) param = result.scalar_one_or_none() if param is not None: logger.debug( f"Paraméter '{key}' található {scope_level.value} scope-ban (scope_id={scope_id})" ) return param.value else: logger.debug( f"Paraméter '{key}' nem található {scope_level.value} scope-ban (scope_id={scope_id})" ) logger.info(f"Paraméter '{key}' nem található egyetlen scope-ban sem, default értéket használunk") return default async def set_scoped_parameter( self, db: AsyncSession, key: str, value: Dict, scope_level: ParameterScope, scope_id: Optional[str] = None, category: str = "general", description: Optional[str] = None, last_modified_by: Optional[int] = None, ) -> SystemParameter: """ Létrehoz vagy frissít egy rendszerparamétert a megadott scope-ban. Ha már létezik ugyanazzal a kulccsal, scope_level-lel és scope_id-vel, felülírja. """ from sqlalchemy.dialects.postgresql import insert # UPSERT logika: ON CONFLICT DO UPDATE insert_stmt = insert(SystemParameter).values( key=key, value=value, scope_level=scope_level, scope_id=scope_id, category=category, description=description, last_modified_by=last_modified_by, is_active=True, ) upsert_stmt = insert_stmt.on_conflict_do_update( constraint="uix_param_scope", set_=dict( value=value, category=category, description=description, last_modified_by=last_modified_by, updated_at=func.now(), ), ) await db.execute(upsert_stmt) await db.commit() # Visszaolvassuk a létrehozott/frissített rekordot stmt = select(SystemParameter).where( SystemParameter.key == key, SystemParameter.scope_level == scope_level, SystemParameter.scope_id == scope_id, ) result = await db.execute(stmt) param = result.scalar_one() return param # --- GLOBÁLIS PÉLDÁNY ÉS SEGÉDFÜGGVÉNYEK --- # Ezek a fájl legszélén vannak (0-s behúzás), így kívülről importálhatóak! system_service = SystemService() async def get_system_parameter(db: AsyncSession, key: str, default: Any = None) -> Any: """ Proxy függvény, amit a marketplace_service és más modulok közvetlenül importálnak. A globális system_service példányt használja. """ return await system_service.get_scoped_parameter(db, key, default=default)