Files
service-finder/backend/app/services/system_service.py
2026-03-13 10:22:41 +00:00

147 lines
5.4 KiB
Python

# /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)