"""Single source for SystemSetting reads/writes. Services used to hand-roll ``select(SystemSetting).where(key == ...)`` + ``scalar_one_or_none`` (plus a near-identical get-or-create upsert) in a dozen places. These helpers centralise that. ``upsert_setting`` never commits — the caller owns the transaction. ``updated_at`` is managed by the model's ``onupdate`` hook, so callers don't set it. """ from __future__ import annotations from collections.abc import Iterable from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.models.settings import SystemSetting async def get_setting(db: AsyncSession, key: str) -> SystemSetting | None: """Return the SystemSetting row for ``key``, or None if unset.""" result = await db.execute(select(SystemSetting).where(SystemSetting.key == key)) return result.scalar_one_or_none() async def get_value(db: AsyncSession, key: str, default: str | None = None) -> str | None: """Return the stored value for ``key``, or ``default`` if unset.""" setting = await get_setting(db, key) return setting.value if setting is not None else default async def get_map(db: AsyncSession, keys: Iterable[str]) -> dict[str, str]: """Return a {key: value} map for the given keys that exist.""" result = await db.execute(select(SystemSetting).where(SystemSetting.key.in_(list(keys)))) return {s.key: s.value for s in result.scalars().all()} async def upsert_setting(db: AsyncSession, key: str, value: str) -> SystemSetting: """Create or update a setting. Does NOT commit; caller controls the transaction.""" setting = await get_setting(db, key) if setting is None: setting = SystemSetting(key=key, value=value) db.add(setting) else: setting.value = value return setting