import uuid from fastapi import HTTPException from sqlalchemy.ext.asyncio import AsyncSession from org_settings.models import OrgSettings from org_settings.serializers import serialize_org_setting VALID_CATEGORIES = ( "general", "notifications", "email_templates", "career_portal", "branding", "security", # REQ-ANL-08: holds `analytics.tth_baseline` ({"days": N, "source": "..."}), # surfaced by /analytics/kpis/fetch as tth_baseline_* fields. "analytics", ) def _as_uuid(value): if value in (None, ""): return None try: return uuid.UUID(str(value)) except (TypeError, ValueError): return None def _user_id(current_user): if not current_user or not current_user.get("id"): raise HTTPException(status_code=401, detail="Not authenticated") uid = _as_uuid(current_user["id"]) if uid is None: raise HTTPException(status_code=401, detail="Invalid user id") return uid class OrgSetting: def __init__(self, session: AsyncSession): self.session = session async def get_settings(self, category=None): if category and category not in VALID_CATEGORIES: raise HTTPException( status_code=422, detail=f"category must be one of {', '.join(VALID_CATEGORIES)}" ) rows, total = await OrgSettings.fetch_settings(self.session, category=category) return [serialize_org_setting(r) for r in rows], total async def update_settings(self, payload, current_user): items = payload.get("settings") or [] if not items: raise HTTPException(status_code=400, detail="settings is required") cleaned = [] for item in items: key = (item.get("key") or "").strip() category = (item.get("category") or "").strip() if not key: raise HTTPException(status_code=422, detail="key is required") if category not in VALID_CATEGORIES: raise HTTPException( status_code=422, detail=f"category must be one of {', '.join(VALID_CATEGORIES)}" ) cleaned.append({ "setting_key": key, "setting_value": item.get("value"), "category": category, }) rows = await OrgSettings.upsert_settings(self.session, cleaned, _user_id(current_user)) return [serialize_org_setting(r) for r in rows]