"""Forms, surveys & appointment DTOs — Phase 11.6.""" from __future__ import annotations from datetime import datetime from uuid import UUID from pydantic import BaseModel, ConfigDict, Field from app.models.types import ( AppointmentBookingStatus, AppointmentPageStatus, FormStatus, FormSubmissionStatus, SurveyResponseStatus, SurveyStatus, ) from app.schemas.common import ORMBase _FORBID = ConfigDict(extra="forbid") class ExperienceFormCreate(BaseModel): model_config = _FORBID workspace_id: UUID site_id: UUID | None = None page_id: UUID | None = None code: str = Field(max_length=50) name: str = Field(max_length=255) description: str | None = None status: FormStatus = FormStatus.DRAFT form_schema_json: dict | None = None submit_action_json: dict | None = None metadata_json: dict | None = None class ExperienceFormUpdate(BaseModel): model_config = _FORBID site_id: UUID | None = None page_id: UUID | None = None name: str | None = Field(default=None, max_length=255) description: str | None = None status: FormStatus | None = None form_schema_json: dict | None = None submit_action_json: dict | None = None metadata_json: dict | None = None version: int = Field(ge=1) class ExperienceFormRead(ORMBase): id: UUID tenant_id: UUID workspace_id: UUID site_id: UUID | None page_id: UUID | None code: str name: str description: str | None status: FormStatus form_schema_json: dict | None submit_action_json: dict | None metadata_json: dict | None version: int is_deleted: bool created_by: str | None updated_by: str | None created_at: datetime updated_at: datetime class ExperienceFormListResponse(BaseModel): items: list[ExperienceFormRead] total: int page: int page_size: int class FormSubmissionCreate(BaseModel): model_config = _FORBID workspace_id: UUID form_id: UUID payload_json: dict | None = None crm_contact_ref: str | None = Field(default=None, max_length=255) communication_ref: str | None = Field(default=None, max_length=255) external_ref: str | None = Field(default=None, max_length=255) metadata_json: dict | None = None class FormSubmissionUpdate(BaseModel): model_config = _FORBID status: FormSubmissionStatus | None = None crm_contact_ref: str | None = Field(default=None, max_length=255) communication_ref: str | None = Field(default=None, max_length=255) external_ref: str | None = Field(default=None, max_length=255) metadata_json: dict | None = None version: int = Field(ge=1) class FormSubmissionRead(ORMBase): id: UUID tenant_id: UUID workspace_id: UUID form_id: UUID status: FormSubmissionStatus payload_json: dict | None crm_contact_ref: str | None communication_ref: str | None external_ref: str | None submitted_at: datetime | None metadata_json: dict | None version: int is_deleted: bool created_by: str | None updated_by: str | None created_at: datetime updated_at: datetime class FormSubmissionListResponse(BaseModel): items: list[FormSubmissionRead] total: int page: int page_size: int class ExperienceSurveyCreate(BaseModel): model_config = _FORBID workspace_id: UUID site_id: UUID | None = None page_id: UUID | None = None code: str = Field(max_length=50) name: str = Field(max_length=255) description: str | None = None status: SurveyStatus = SurveyStatus.DRAFT questions_json: dict | None = None metadata_json: dict | None = None class ExperienceSurveyUpdate(BaseModel): model_config = _FORBID site_id: UUID | None = None page_id: UUID | None = None name: str | None = Field(default=None, max_length=255) description: str | None = None status: SurveyStatus | None = None questions_json: dict | None = None metadata_json: dict | None = None version: int = Field(ge=1) class ExperienceSurveyRead(ORMBase): id: UUID tenant_id: UUID workspace_id: UUID site_id: UUID | None page_id: UUID | None code: str name: str description: str | None status: SurveyStatus questions_json: dict | None metadata_json: dict | None version: int is_deleted: bool created_by: str | None updated_by: str | None created_at: datetime updated_at: datetime class ExperienceSurveyListResponse(BaseModel): items: list[ExperienceSurveyRead] total: int page: int page_size: int class SurveyResponseCreate(BaseModel): model_config = _FORBID workspace_id: UUID survey_id: UUID answers_json: dict | None = None crm_contact_ref: str | None = Field(default=None, max_length=255) external_ref: str | None = Field(default=None, max_length=255) metadata_json: dict | None = None class SurveyResponseUpdate(BaseModel): model_config = _FORBID status: SurveyResponseStatus | None = None crm_contact_ref: str | None = Field(default=None, max_length=255) external_ref: str | None = Field(default=None, max_length=255) metadata_json: dict | None = None version: int = Field(ge=1) class SurveyResponseRead(ORMBase): id: UUID tenant_id: UUID workspace_id: UUID survey_id: UUID status: SurveyResponseStatus answers_json: dict | None crm_contact_ref: str | None external_ref: str | None submitted_at: datetime | None metadata_json: dict | None version: int is_deleted: bool created_by: str | None updated_by: str | None created_at: datetime updated_at: datetime class SurveyResponseListResponse(BaseModel): items: list[SurveyResponseRead] total: int page: int page_size: int class ExperienceAppointmentPageCreate(BaseModel): model_config = _FORBID workspace_id: UUID site_id: UUID page_id: UUID | None = None code: str = Field(max_length=50) name: str = Field(max_length=255) description: str | None = None status: AppointmentPageStatus = AppointmentPageStatus.DRAFT booking_provider_ref: str | None = Field(default=None, max_length=255) service_ref: str | None = Field(default=None, max_length=255) timezone: str | None = Field(default=None, max_length=64) availability_shell_json: dict | None = None metadata_json: dict | None = None class ExperienceAppointmentPageUpdate(BaseModel): model_config = _FORBID page_id: UUID | None = None name: str | None = Field(default=None, max_length=255) description: str | None = None status: AppointmentPageStatus | None = None booking_provider_ref: str | None = Field(default=None, max_length=255) service_ref: str | None = Field(default=None, max_length=255) timezone: str | None = Field(default=None, max_length=64) availability_shell_json: dict | None = None metadata_json: dict | None = None version: int = Field(ge=1) class ExperienceAppointmentPageRead(ORMBase): id: UUID tenant_id: UUID workspace_id: UUID site_id: UUID page_id: UUID | None code: str name: str description: str | None status: AppointmentPageStatus booking_provider_ref: str | None service_ref: str | None timezone: str | None availability_shell_json: dict | None metadata_json: dict | None version: int is_deleted: bool created_by: str | None updated_by: str | None created_at: datetime updated_at: datetime class ExperienceAppointmentPageListResponse(BaseModel): items: list[ExperienceAppointmentPageRead] total: int page: int page_size: int class AppointmentBookingRefCreate(BaseModel): model_config = _FORBID workspace_id: UUID appointment_page_id: UUID external_booking_ref: str = Field(max_length=255) status: AppointmentBookingStatus = AppointmentBookingStatus.PENDING crm_contact_ref: str | None = Field(default=None, max_length=255) slot_start: datetime | None = None slot_end: datetime | None = None metadata_json: dict | None = None class AppointmentBookingRefUpdate(BaseModel): model_config = _FORBID status: AppointmentBookingStatus | None = None crm_contact_ref: str | None = Field(default=None, max_length=255) slot_start: datetime | None = None slot_end: datetime | None = None metadata_json: dict | None = None version: int = Field(ge=1) class AppointmentBookingRefRead(ORMBase): id: UUID tenant_id: UUID workspace_id: UUID appointment_page_id: UUID external_booking_ref: str status: AppointmentBookingStatus crm_contact_ref: str | None slot_start: datetime | None slot_end: datetime | None metadata_json: dict | None version: int is_deleted: bool created_by: str | None updated_by: str | None created_at: datetime updated_at: datetime class AppointmentBookingRefListResponse(BaseModel): items: list[AppointmentBookingRefRead] total: int page: int page_size: int