TorbatYar/backend/services/experience/app/commands/themes.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

241 lines
7.4 KiB
Python

"""Theme & layout command handlers — Phase 11.3 (versioned)."""
from __future__ import annotations
from uuid import UUID
from sqlalchemy.ext.asyncio import AsyncSession
from app.schemas.themes import (
ExperienceLayoutCreate,
ExperienceLayoutUpdate,
ExperienceLayoutVersionCreate,
ExperienceLayoutVersionUpdate,
ExperienceThemeCreate,
ExperienceThemeUpdate,
ExperienceThemeVersionCreate,
ExperienceThemeVersionUpdate,
PageLayoutBindingCreate,
PageLayoutBindingUpdate,
SiteThemeBindingCreate,
SiteThemeBindingUpdate,
)
from app.services.themes import ExperienceThemeService
from shared.security import CurrentUser
class ThemeLayoutCommands:
def __init__(self, session: AsyncSession) -> None:
self.service = ExperienceThemeService(session)
# --- Themes ---
async def create_theme(
self, tenant_id: UUID, body: ExperienceThemeCreate, *, actor: CurrentUser | None
):
return await self.service.create_theme(tenant_id, body, actor=actor)
async def update_theme(
self,
tenant_id: UUID,
theme_id: UUID,
body: ExperienceThemeUpdate,
*,
actor: CurrentUser | None,
):
return await self.service.update_theme(tenant_id, theme_id, body, actor=actor)
async def activate_theme(
self, tenant_id: UUID, theme_id: UUID, *, actor: CurrentUser | None
):
return await self.service.activate_theme(tenant_id, theme_id, actor=actor)
async def deprecate_theme(
self, tenant_id: UUID, theme_id: UUID, *, actor: CurrentUser | None
):
return await self.service.deprecate_theme(tenant_id, theme_id, actor=actor)
async def archive_theme(
self, tenant_id: UUID, theme_id: UUID, *, actor: CurrentUser | None
):
return await self.service.archive_theme(tenant_id, theme_id, actor=actor)
async def soft_delete_theme(
self, tenant_id: UUID, theme_id: UUID, *, actor: CurrentUser | None
):
return await self.service.soft_delete_theme(tenant_id, theme_id, actor=actor)
# --- Theme Versions ---
async def create_theme_version(
self,
tenant_id: UUID,
body: ExperienceThemeVersionCreate,
*,
actor: CurrentUser | None,
):
return await self.service.create_theme_version(tenant_id, body, actor=actor)
async def update_theme_version(
self,
tenant_id: UUID,
version_id: UUID,
body: ExperienceThemeVersionUpdate,
*,
actor: CurrentUser | None,
):
return await self.service.update_theme_version(
tenant_id, version_id, body, actor=actor
)
async def publish_theme_version(
self, tenant_id: UUID, version_id: UUID, *, actor: CurrentUser | None
):
return await self.service.publish_theme_version(
tenant_id, version_id, actor=actor
)
async def retire_theme_version(
self, tenant_id: UUID, version_id: UUID, *, actor: CurrentUser | None
):
return await self.service.retire_theme_version(
tenant_id, version_id, actor=actor
)
# --- Layouts ---
async def create_layout(
self, tenant_id: UUID, body: ExperienceLayoutCreate, *, actor: CurrentUser | None
):
return await self.service.create_layout(tenant_id, body, actor=actor)
async def update_layout(
self,
tenant_id: UUID,
layout_id: UUID,
body: ExperienceLayoutUpdate,
*,
actor: CurrentUser | None,
):
return await self.service.update_layout(
tenant_id, layout_id, body, actor=actor
)
async def activate_layout(
self, tenant_id: UUID, layout_id: UUID, *, actor: CurrentUser | None
):
return await self.service.activate_layout(tenant_id, layout_id, actor=actor)
async def deprecate_layout(
self, tenant_id: UUID, layout_id: UUID, *, actor: CurrentUser | None
):
return await self.service.deprecate_layout(tenant_id, layout_id, actor=actor)
async def archive_layout(
self, tenant_id: UUID, layout_id: UUID, *, actor: CurrentUser | None
):
return await self.service.archive_layout(tenant_id, layout_id, actor=actor)
async def soft_delete_layout(
self, tenant_id: UUID, layout_id: UUID, *, actor: CurrentUser | None
):
return await self.service.soft_delete_layout(
tenant_id, layout_id, actor=actor
)
# --- Layout Versions ---
async def create_layout_version(
self,
tenant_id: UUID,
body: ExperienceLayoutVersionCreate,
*,
actor: CurrentUser | None,
):
return await self.service.create_layout_version(tenant_id, body, actor=actor)
async def update_layout_version(
self,
tenant_id: UUID,
version_id: UUID,
body: ExperienceLayoutVersionUpdate,
*,
actor: CurrentUser | None,
):
return await self.service.update_layout_version(
tenant_id, version_id, body, actor=actor
)
async def publish_layout_version(
self, tenant_id: UUID, version_id: UUID, *, actor: CurrentUser | None
):
return await self.service.publish_layout_version(
tenant_id, version_id, actor=actor
)
async def retire_layout_version(
self, tenant_id: UUID, version_id: UUID, *, actor: CurrentUser | None
):
return await self.service.retire_layout_version(
tenant_id, version_id, actor=actor
)
# --- Site Theme Bindings ---
async def assign_site_theme(
self,
tenant_id: UUID,
body: SiteThemeBindingCreate,
*,
actor: CurrentUser | None,
):
return await self.service.assign_site_theme(tenant_id, body, actor=actor)
async def update_site_theme_binding(
self,
tenant_id: UUID,
binding_id: UUID,
body: SiteThemeBindingUpdate,
*,
actor: CurrentUser | None,
):
return await self.service.update_site_theme_binding(
tenant_id, binding_id, body, actor=actor
)
async def unassign_site_theme(
self, tenant_id: UUID, binding_id: UUID, *, actor: CurrentUser | None
):
return await self.service.soft_delete_site_theme_binding(
tenant_id, binding_id, actor=actor
)
# --- Page Layout Bindings ---
async def assign_page_layout(
self,
tenant_id: UUID,
body: PageLayoutBindingCreate,
*,
actor: CurrentUser | None,
):
return await self.service.assign_page_layout(tenant_id, body, actor=actor)
async def update_page_layout_binding(
self,
tenant_id: UUID,
binding_id: UUID,
body: PageLayoutBindingUpdate,
*,
actor: CurrentUser | None,
):
return await self.service.update_page_layout_binding(
tenant_id, binding_id, body, actor=actor
)
async def unassign_page_layout(
self, tenant_id: UUID, binding_id: UUID, *, actor: CurrentUser | None
):
return await self.service.soft_delete_page_layout_binding(
tenant_id, binding_id, actor=actor
)