Newer
Older
gnexus-tasks / backend / app / api / settings.py
"""API глобальных настроек (ТЗ: валюта бюджетов и язык UI — общие, выбираются один раз)."""

from typing import cast

from fastapi import APIRouter

from app.dependencies import DbDep, UserDep
from app.models import AppSetting
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()
    return AppSettingsOut(
        currency=_read_value(db, CURRENCY_KEY, CURRENCIES, DEFAULT_CURRENCY),
        language=_read_value(db, LANGUAGE_KEY, LANGUAGES + ("",), DEFAULT_LANGUAGE),
    )