TorbatYar/backend/services/experience/app/repositories/foundation.py
Mortezakoohjani 203671a7bf feat(experience): ship Experience Platform phases 11.0-11.10
Add the experience service with sites through analytics/AI hooks, migrations through 0011, and phase docs/manifests marking the track complete.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 11:43:10 +03:30

143 lines
4.4 KiB
Python

"""Experience foundation repositories."""
from __future__ import annotations
from typing import Sequence
from uuid import UUID
from sqlalchemy import select
from app.models.foundation import (
ExperienceAuditLog,
ExperienceConfiguration,
ExperienceLocaleProfile,
ExperienceWorkspace,
ExperiencePermission,
ExperienceRole,
ExperienceSetting,
ExternalProviderConfig,
RenderEngineRegistration,
)
from app.repositories.base import TenantBaseRepository
class ExperienceWorkspaceRepository(TenantBaseRepository[ExperienceWorkspace]):
model = ExperienceWorkspace
async def get_by_code(
self, tenant_id: UUID, code: str
) -> ExperienceWorkspace | None:
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 ExperienceLocaleProfileRepository(TenantBaseRepository[ExperienceLocaleProfile]):
model = ExperienceLocaleProfile
async def list_by_organization(
self, tenant_id: UUID, workspace_id: UUID, *, offset: int = 0, limit: int = 20
) -> Sequence[ExperienceLocaleProfile]:
stmt = (
select(self.model)
.where(
self.model.tenant_id == tenant_id,
self.model.workspace_id == workspace_id,
self.model.is_deleted.is_(False),
)
.offset(offset)
.limit(limit)
)
result = await self.session.execute(stmt)
return result.scalars().all()
class ExperienceRoleRepository(TenantBaseRepository[ExperienceRole]):
model = ExperienceRole
class ExperiencePermissionRepository(TenantBaseRepository[ExperiencePermission]):
model = ExperiencePermission
class ExternalProviderConfigRepository(TenantBaseRepository[ExternalProviderConfig]):
model = ExternalProviderConfig
async def get_by_code(
self, tenant_id: UUID, code: str
) -> ExternalProviderConfig | None:
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 RenderEngineRegistrationRepository(
TenantBaseRepository[RenderEngineRegistration]
):
model = RenderEngineRegistration
class ExperienceConfigurationRepository(TenantBaseRepository[ExperienceConfiguration]):
model = ExperienceConfiguration
class ExperienceSettingRepository(TenantBaseRepository[ExperienceSetting]):
model = ExperienceSetting
async def get_by_key(
self,
tenant_id: UUID,
key: str,
*,
workspace_id: UUID | None = None,
locale_profile_id: UUID | None = None,
) -> ExperienceSetting | None:
clauses = [
self.model.tenant_id == tenant_id,
self.model.key == key,
self.model.is_deleted.is_(False),
]
if workspace_id is None:
clauses.append(self.model.workspace_id.is_(None))
else:
clauses.append(self.model.workspace_id == workspace_id)
if locale_profile_id is None:
clauses.append(self.model.locale_profile_id.is_(None))
else:
clauses.append(self.model.locale_profile_id == locale_profile_id)
stmt = select(self.model).where(*clauses)
result = await self.session.execute(stmt)
return result.scalar_one_or_none()
class ExperienceAuditLogRepository(TenantBaseRepository[ExperienceAuditLog]):
model = ExperienceAuditLog
async def list_for_entity(
self,
tenant_id: UUID,
entity_type: str,
entity_id: UUID,
*,
limit: int = 100,
) -> Sequence[ExperienceAuditLog]:
stmt = (
select(self.model)
.where(
self.model.tenant_id == tenant_id,
self.model.entity_type == entity_type,
self.model.entity_id == entity_id,
)
.order_by(self.model.created_at.desc())
.limit(limit)
)
result = await self.session.execute(stmt)
return result.scalars().all()