átlagos kiegészítséek jó sok

This commit is contained in:
Roo
2026-03-22 11:02:05 +00:00
parent f53e0b53df
commit 5d44339f21
249 changed files with 20922 additions and 2253 deletions

View File

@@ -2,6 +2,7 @@
from typing import Any, Optional, Dict
import logging
import os
import json
from decimal import Decimal
from datetime import datetime, timezone
@@ -10,6 +11,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
# Modellek importálása a központi helyről
from app.models import ExchangeRate, AssetCost, AssetTelemetry
from app.models.system.system import SystemParameter, ParameterScope
from app.db.session import AsyncSessionLocal
logger = logging.getLogger(__name__)
@@ -59,25 +61,211 @@ class CostService:
raise e
class ConfigService:
"""
MB 2.0 Alapvető konfigurációs szerviz.
Kezeli az AI szolgáltatások (Ollama) dinamikus beállításait és promptjait.
"""
async def get_setting(self, db: AsyncSession, key: str, default: Any = None) -> Any:
Egyszerű konfigurációs szolgáltatás a SystemParameter tábla lekérdezéséhez.
Támogatja a különböző típusú értékek lekérését alapértelmezett értékkel.
"""
@staticmethod
async def get(db: AsyncSession, key: str, default: Any = None, scope_level: ParameterScope = ParameterScope.GLOBAL, scope_id: Optional[str] = None) -> Any:
"""
Lekéri a kért beállítást.
1. Megnézi a környezeti változókat (NAGYBETŰVEL).
2. Ha nincs ilyen ENV, visszaadja a kódba égetett 'default' értéket.
"""
env_val = os.getenv(key.upper())
if env_val is not None:
# Automatikus típuskonverzió a default paraméter típusa alapján
if isinstance(default, int): return int(env_val)
if isinstance(default, float): return float(env_val)
if isinstance(default, bool): return str(env_val).lower() in ('true', '1', 'yes')
return env_val
Általános lekérdezés a SystemParameter táblából.
Args:
db: AsyncSession
key: A konfigurációs kulcs
default: Alapértelmezett érték, ha a kulcs nem található
scope_level: A paraméter scope-ja (global, country, region, user)
scope_id: A scope azonosítója (pl. országkód, user_id)
Returns:
A talált érték (a megfelelő típusban) vagy a default.
"""
from sqlalchemy import select, and_, cast, String
try:
# Convert scope_level to lowercase string for comparison
# PostgreSQL enum expects lowercase values, but Python Enum may be uppercase
scope_str = scope_level.value.lower() if hasattr(scope_level, 'value') else str(scope_level).lower()
# Build query with cast to avoid strict enum type mismatch
query = select(SystemParameter).where(
and_(
SystemParameter.key == key,
cast(SystemParameter.scope_level, String) == scope_str,
SystemParameter.is_active == True
)
)
if scope_id is None:
query = query.where(SystemParameter.scope_id.is_(None))
else:
query = query.where(SystemParameter.scope_id == scope_id)
result = await db.execute(query)
param = result.scalar_one_or_none()
if param is None:
# Opcionálisan beilleszthetjük a default értéket a táblába
# await ConfigService._insert_default(db, key, default, scope_level, scope_id)
return default
# A value oszlop JSONB, lehet dict, list, string, number, bool
db_value = param.value
# Típuskonverzió a default típusa alapján
if default is None:
return db_value
if isinstance(default, int):
if isinstance(db_value, (int, float, str)):
try:
return int(db_value)
except (ValueError, TypeError):
return default
return default
elif isinstance(default, float):
if isinstance(db_value, (int, float, str)):
try:
return float(db_value)
except (ValueError, TypeError):
return default
return default
elif isinstance(default, bool):
if isinstance(db_value, bool):
return db_value
elif isinstance(db_value, str):
return db_value.lower() in ('true', '1', 'yes', 'on')
elif isinstance(db_value, int):
return db_value != 0
return default
elif isinstance(default, str):
if isinstance(db_value, str):
return db_value
elif isinstance(db_value, (dict, list)):
return json.dumps(db_value)
else:
return str(db_value)
elif isinstance(default, dict) and isinstance(db_value, dict):
return db_value
elif isinstance(default, list) and isinstance(db_value, list):
return db_value
else:
# Egyébként visszaadjuk a db_value-t
return db_value
except Exception as e:
logger.warning(f"ConfigService.get error for key '{key}': {e}")
return default
async def get_setting(self, db: AsyncSession, key: str, default: Any = None, region_code: Optional[str] = None, org_id: Optional[int] = None, **kwargs) -> Any:
"""
Általános beállítás lekérése a régi kód kompatibilitásához.
Args:
db: AsyncSession
key: A konfigurációs kulcs
default: Alapértelmezett érték
region_code: Országkód (pl. "HU") - COUNTRY scope
org_id: Szervezet azonosító - ORGANIZATION scope
**kwargs: További paraméterek (pl. user_id)
Returns:
A talált érték vagy default.
"""
from app.models.system.system import ParameterScope
# Scope meghatározása
if org_id is not None:
scope_level = ParameterScope.ORGANIZATION
scope_id = str(org_id)
elif region_code is not None:
scope_level = ParameterScope.COUNTRY
scope_id = region_code
else:
scope_level = ParameterScope.GLOBAL
scope_id = None
# További scope-ok (pl. user) a kwargs-ból
if 'user_id' in kwargs:
scope_level = ParameterScope.USER
scope_id = str(kwargs['user_id'])
return await ConfigService.get(db, key, default, scope_level, scope_id)
@staticmethod
async def get_int(db: AsyncSession, key: str, default: int, scope_level: ParameterScope = ParameterScope.GLOBAL, scope_id: Optional[str] = None) -> int:
"""Egész szám lekérése."""
value = await ConfigService.get(db, key, default, scope_level, scope_id)
if isinstance(value, int):
return value
try:
return int(value)
except (ValueError, TypeError):
return default
@staticmethod
async def get_str(db: AsyncSession, key: str, default: str, scope_level: ParameterScope = ParameterScope.GLOBAL, scope_id: Optional[str] = None) -> str:
"""Szöveg lekérése."""
value = await ConfigService.get(db, key, default, scope_level, scope_id)
if isinstance(value, str):
return value
return str(value)
@staticmethod
async def get_bool(db: AsyncSession, key: str, default: bool, scope_level: ParameterScope = ParameterScope.GLOBAL, scope_id: Optional[str] = None) -> bool:
"""Logikai érték lekérése."""
value = await ConfigService.get(db, key, default, scope_level, scope_id)
if isinstance(value, bool):
return value
if isinstance(value, str):
return value.lower() in ('true', '1', 'yes', 'on')
if isinstance(value, int):
return value != 0
return default
@staticmethod
async def get_float(db: AsyncSession, key: str, default: float, scope_level: ParameterScope = ParameterScope.GLOBAL, scope_id: Optional[str] = None) -> float:
"""Lebegőpontos szám lekérése."""
value = await ConfigService.get(db, key, default, scope_level, scope_id)
if isinstance(value, float):
return value
try:
return float(value)
except (ValueError, TypeError):
return default
@staticmethod
async def get_json(db: AsyncSession, key: str, default: dict, scope_level: ParameterScope = ParameterScope.GLOBAL, scope_id: Optional[str] = None) -> dict:
"""JSON objektum lekérése."""
value = await ConfigService.get(db, key, default, scope_level, scope_id)
if isinstance(value, dict):
return value
if isinstance(value, str):
try:
return json.loads(value)
except json.JSONDecodeError:
return default
return default
@staticmethod
async def _insert_default(db: AsyncSession, key: str, default: Any, scope_level: ParameterScope, scope_id: Optional[str] = None) -> None:
"""Opcionális: beszúrja a default értéket a táblába, hogy látható legyen az Admin UI-ban."""
try:
from app.models.system.system import SystemParameter
param = SystemParameter(
key=key,
category="auto_inserted",
value=default if isinstance(default, (dict, list)) else {"value": default},
scope_level=scope_level,
scope_id=scope_id,
is_active=True,
description=f"Auto-inserted default value for {key}"
)
db.add(param)
await db.commit()
except Exception as e:
logger.debug(f"Could not insert default for {key}: {e}")
await db.rollback()
# A példány, amit a többi modul (pl. az auth_service, ai_service) importálni próbál
config = ConfigService()