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>
75 lines
2.7 KiB
Python
75 lines
2.7 KiB
Python
"""Template domain policies — Phase 11.4."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from app.models.types import TemplateStatus, TemplateVersionStatus
|
|
from app.validators.templates import (
|
|
ensure_template_status_transition,
|
|
ensure_template_version_mutable,
|
|
ensure_template_version_status_transition,
|
|
)
|
|
from shared.exceptions import AppError
|
|
|
|
|
|
class TemplateLifecyclePolicy:
|
|
def assert_status_change(
|
|
self, *, current: TemplateStatus, target: TemplateStatus
|
|
) -> TemplateStatus:
|
|
ensure_template_status_transition(current, target)
|
|
return target
|
|
|
|
|
|
class TemplateVersionPolicy:
|
|
def assert_can_update(self, version: Any) -> None:
|
|
ensure_template_version_mutable(version)
|
|
|
|
def assert_publish(
|
|
self, *, current: TemplateVersionStatus
|
|
) -> TemplateVersionStatus:
|
|
ensure_template_version_status_transition(
|
|
current, TemplateVersionStatus.PUBLISHED
|
|
)
|
|
return TemplateVersionStatus.PUBLISHED
|
|
|
|
def assert_retire(
|
|
self, *, current: TemplateVersionStatus
|
|
) -> TemplateVersionStatus:
|
|
ensure_template_version_status_transition(
|
|
current, TemplateVersionStatus.RETIRED
|
|
)
|
|
return TemplateVersionStatus.RETIRED
|
|
|
|
|
|
class TemplateInstantiationPolicy:
|
|
def assert_template_instantiable(self, template: Any) -> None:
|
|
status = getattr(template, "status", None)
|
|
if status == TemplateStatus.ARCHIVED:
|
|
raise AppError(
|
|
"قالب بایگانیشده قابل نمونهسازی نیست",
|
|
error_code="template_archived",
|
|
status_code=409,
|
|
)
|
|
if getattr(template, "is_deleted", False):
|
|
raise AppError(
|
|
"قالب حذفشده قابل نمونهسازی نیست",
|
|
error_code="template_deleted",
|
|
status_code=409,
|
|
)
|
|
|
|
def assert_version_instantiable(self, version: Any) -> None:
|
|
status = getattr(version, "status", None)
|
|
if status != TemplateVersionStatus.PUBLISHED:
|
|
raise AppError(
|
|
"فقط نسخه منتشرشده قالب قابل نمونهسازی است",
|
|
error_code="template_version_not_published",
|
|
status_code=409,
|
|
details={"status": getattr(status, "value", status)},
|
|
)
|
|
if getattr(version, "is_deleted", False):
|
|
raise AppError(
|
|
"نسخه حذفشده قالب قابل نمونهسازی نیست",
|
|
error_code="template_version_deleted",
|
|
status_code=409,
|
|
)
|