"""Tenant-scoped repositories for Phase 11.10 analytics.""" from uuid import UUID from sqlalchemy import func, select from app.models.analytics import ( ExperienceAnalyticsReportDefinition, ExperienceAnalyticsSnapshot, ) from app.repositories.base import TenantBaseRepository class _FilteredRepository: async def list_filtered(self, tenant_id, *, offset, limit, spec=None): base = select(self.model).where( self.model.tenant_id == tenant_id, self.model.is_deleted.is_(False) ) count = select(func.count()).select_from(self.model).where( self.model.tenant_id == tenant_id, self.model.is_deleted.is_(False) ) if spec: base = spec.apply(base) count = count.where(*spec.filter_clauses()) else: base = base.order_by(self.model.created_at.desc()) total = int((await self.session.execute(count)).scalar_one()) items = (await self.session.execute(base.offset(offset).limit(limit))).scalars().all() return items, total class AnalyticsReportDefinitionRepository( _FilteredRepository, TenantBaseRepository[ExperienceAnalyticsReportDefinition] ): model = ExperienceAnalyticsReportDefinition async def get_by_code(self, tenant_id: UUID, code: str): stmt = select(self.model).where( self.model.tenant_id == tenant_id, self.model.code == code, self.model.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class AnalyticsSnapshotRepository( _FilteredRepository, TenantBaseRepository[ExperienceAnalyticsSnapshot] ): model = ExperienceAnalyticsSnapshot