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

Per-user (ТЗ 1.2): у каждого пользователя свои настройки; строка с PK
(user_id, key). Настройки прежней эпохи (app_settings_global) копируются
в per-user при первом логине (claim) — см. services/users.py.
"""

from typing import cast

from fastapi import APIRouter

from app.dependencies import DbDep, UserIdDep
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, user_id: str, key: str, valid: tuple[str, ...], default: str) -> str:
    row = cast(AppSetting | None, db.get(AppSetting, (user_id, key)))
    if row is not None and row.value in valid:
        return row.value
    return default


def _upsert(db: DbDep, user_id: str, key: str, value: str) -> None:
    row = cast(AppSetting | None, db.get(AppSetting, (user_id, key)))
    if row is None:
        db.add(AppSetting(user_id=user_id, key=key, value=value))
    else:
        row.value = value
    db.flush()


@router.get("", response_model=AppSettingsOut)
async def get_settings(db: DbDep, user_id: UserIdDep) -> AppSettingsOut:
    return AppSettingsOut(
        currency=_read_value(db, user_id, CURRENCY_KEY, CURRENCIES, DEFAULT_CURRENCY),
        language=_read_value(db, user_id, LANGUAGE_KEY, LANGUAGES + ("",), DEFAULT_LANGUAGE),
    )


@router.put("", response_model=AppSettingsOut)
async def update_settings(
    schema: AppSettingsUpdate, db: DbDep, user_id: UserIdDep
) -> AppSettingsOut:
    # Частичный PUT: обновляем только переданные поля (model_fields_set)
    if schema.currency is not None:
        _upsert(db, user_id, CURRENCY_KEY, schema.currency)
    if schema.language is not None:
        _upsert(db, user_id, LANGUAGE_KEY, schema.language)
    db.flush()
    db.commit()
    publish(user_id, "settings.changed")
    return AppSettingsOut(
        currency=_read_value(db, user_id, CURRENCY_KEY, CURRENCIES, DEFAULT_CURRENCY),
        language=_read_value(db, user_id, LANGUAGE_KEY, LANGUAGES + ("",), DEFAULT_LANGUAGE),
    )