"""API глобальных настроек (ТЗ: валюта бюджетов и язык UI — общие, выбираются один раз)."""
from typing import cast
from fastapi import APIRouter
from app.dependencies import DbDep, UserDep
from app.models import AppSetting
from app.realtime import publish
from app.schemas import CURRENCIES, LANGUAGES, AppSettingsOut, AppSettingsUpdate
router = APIRouter(prefix="/api/settings", tags=["settings"])
CURRENCY_KEY = "currency"
LANGUAGE_KEY = "language"
DEFAULT_CURRENCY = "UAH"
DEFAULT_LANGUAGE = "" # '' = нет переопределения, следуем SSO locale
def _read_value(db: DbDep, key: str, valid: tuple[str, ...], default: str) -> str:
row = cast(AppSetting | None, db.get(AppSetting, key))
if row is not None and row.value in valid:
return row.value
return default
def _upsert(db: DbDep, key: str, value: str) -> None:
row = cast(AppSetting | None, db.get(AppSetting, key))
if row is None:
db.add(AppSetting(key=key, value=value))
else:
row.value = value
db.flush()
@router.get("", response_model=AppSettingsOut)
async def get_settings(db: DbDep, user: UserDep) -> AppSettingsOut:
return AppSettingsOut(
currency=_read_value(db, CURRENCY_KEY, CURRENCIES, DEFAULT_CURRENCY),
language=_read_value(db, LANGUAGE_KEY, LANGUAGES + ("",), DEFAULT_LANGUAGE),
)
@router.put("", response_model=AppSettingsOut)
async def update_settings(schema: AppSettingsUpdate, db: DbDep, user: UserDep) -> AppSettingsOut:
# Частичный PUT: обновляем только переданные поля (model_fields_set)
if schema.currency is not None:
_upsert(db, CURRENCY_KEY, schema.currency)
if schema.language is not None:
_upsert(db, LANGUAGE_KEY, schema.language)
db.flush()
db.commit()
publish(str(user["user_id"]), "settings.changed")
return AppSettingsOut(
currency=_read_value(db, CURRENCY_KEY, CURRENCIES, DEFAULT_CURRENCY),
language=_read_value(db, LANGUAGE_KEY, LANGUAGES + ("",), DEFAULT_LANGUAGE),
)