TorbatYar/backend/services/experience/app/policies/forms.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

113 lines
3.8 KiB
Python

"""Forms / surveys / appointments policies — Phase 11.6."""
from __future__ import annotations
from typing import Any
from app.models.types import (
AppointmentBookingStatus,
AppointmentPageStatus,
FormStatus,
FormSubmissionStatus,
SurveyResponseStatus,
SurveyStatus,
)
from app.validators.forms import (
ensure_appointment_page_status_transition,
ensure_booking_status_transition,
ensure_form_status_transition,
ensure_response_status_transition,
ensure_submission_status_transition,
ensure_survey_status_transition,
)
from shared.exceptions import AppError
class FormLifecyclePolicy:
def assert_status_change(
self, *, current: FormStatus, target: FormStatus
) -> FormStatus:
ensure_form_status_transition(current, target)
return target
def assert_accepts_submissions(self, form: Any) -> None:
if getattr(form, "is_deleted", False):
raise AppError(
"فرم حذف‌شده قابل ارسال نیست",
error_code="form_deleted",
status_code=409,
)
if getattr(form, "status", None) != FormStatus.ACTIVE:
raise AppError(
"فقط فرم فعال قابل ارسال است",
error_code="form_not_active",
status_code=409,
)
class FormSubmissionPolicy:
def assert_status_change(
self, *, current: FormSubmissionStatus, target: FormSubmissionStatus
) -> FormSubmissionStatus:
ensure_submission_status_transition(current, target)
return target
class SurveyLifecyclePolicy:
def assert_status_change(
self, *, current: SurveyStatus, target: SurveyStatus
) -> SurveyStatus:
ensure_survey_status_transition(current, target)
return target
def assert_accepts_responses(self, survey: Any) -> None:
if getattr(survey, "is_deleted", False):
raise AppError(
"نظرسنجی حذف‌شده قابل پاسخ نیست",
error_code="survey_deleted",
status_code=409,
)
if getattr(survey, "status", None) != SurveyStatus.ACTIVE:
raise AppError(
"فقط نظرسنجی فعال قابل پاسخ است",
error_code="survey_not_active",
status_code=409,
)
class SurveyResponsePolicy:
def assert_status_change(
self, *, current: SurveyResponseStatus, target: SurveyResponseStatus
) -> SurveyResponseStatus:
ensure_response_status_transition(current, target)
return target
class AppointmentPagePolicy:
def assert_status_change(
self, *, current: AppointmentPageStatus, target: AppointmentPageStatus
) -> AppointmentPageStatus:
ensure_appointment_page_status_transition(current, target)
return target
def assert_accepts_bookings(self, page: Any) -> None:
if getattr(page, "is_deleted", False):
raise AppError(
"صفحه نوبت حذف‌شده قابل رزرو نیست",
error_code="appointment_page_deleted",
status_code=409,
)
if getattr(page, "status", None) != AppointmentPageStatus.ACTIVE:
raise AppError(
"فقط صفحه نوبت فعال قابل رزرو است",
error_code="appointment_page_not_active",
status_code=409,
)
class AppointmentBookingPolicy:
def assert_status_change(
self, *, current: AppointmentBookingStatus, target: AppointmentBookingStatus
) -> AppointmentBookingStatus:
ensure_booking_status_transition(current, target)
return target