"""Brand resolver — multi-tenant white-label. Читает бренд по slug из `brands` Postgres-таблицы. Используется PDF exporter + frontend (через /api/v1/brand/{slug} endpoint). """ from __future__ import annotations import logging from dataclasses import dataclass from sqlalchemy import text from sqlalchemy.orm import Session logger = logging.getLogger(__name__) @dataclass(frozen=True, slots=True) class Brand: slug: str name: str logo_url: str | None primary_color: str accent_color: str footer_text: str | None pdf_disclaimer: str | None _DEFAULT = Brand( slug="generic", name="МЕРА", logo_url=None, primary_color="#1d4ed8", accent_color="#f59e0b", footer_text=None, pdf_disclaimer=None, ) def get_brand(slug: str | None, db: Session) -> Brand: """Возвращает Brand по slug. Fallback на 'generic' если не найден.""" if not slug: return _DEFAULT row = db.execute( text( """ SELECT slug, name, logo_url, primary_color, accent_color, footer_text, pdf_disclaimer FROM brands WHERE slug = :slug """ ), {"slug": slug.lower()}, ).fetchone() if row is None: logger.info("brand not found: %s — using generic", slug) return _DEFAULT return Brand( slug=row.slug, name=row.name, logo_url=row.logo_url, primary_color=row.primary_color or _DEFAULT.primary_color, accent_color=row.accent_color or _DEFAULT.accent_color, footer_text=row.footer_text, pdf_disclaimer=row.pdf_disclaimer, )