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>
113 lines
3.8 KiB
Python
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
|