"""Pydantic schemas for the 乙方侧 安全问卷 routers (answer library, evidence documents, inbound questionnaires).""" from __future__ import annotations from datetime import date from uuid import UUID from pydantic import BaseModel, Field # ── Answer library ──────────────────────────────────────────────────── class LibEntryCreateRequest(BaseModel): category: str = Field(default="general", max_length=64) question_zh: str = Field(min_length=1, max_length=8000) question_en: str = Field(min_length=1, max_length=8000) answer_zh: str = Field(min_length=1, max_length=16000) answer_en: str = Field(min_length=1, max_length=16000) tags: list[str] | None = None owner_person_id: UUID | None = None review_interval_months: int = Field(default=12, ge=1, le=60) source_doc_ids: list[str] | None = None # Employee-facing 安全 FAQ. Visible by default — the library is our # own posture, and an entry nobody can find helps nobody — with the # switch there so one answer can be retracted without archiving it # out of the customer-questionnaire flow too. employee_visible: bool = True is_featured: bool = False class LibEntryUpdateRequest(BaseModel): category: str | None = Field(default=None, max_length=64) question_zh: str | None = Field(default=None, max_length=8000) question_en: str | None = Field(default=None, max_length=8000) answer_zh: str | None = Field(default=None, max_length=16000) answer_en: str | None = Field(default=None, max_length=16000) tags: list[str] | None = None owner_person_id: UUID | None = None review_interval_months: int | None = Field(default=None, ge=1, le=60) source_doc_ids: list[str] | None = None status: str | None = Field(default=None, max_length=16) employee_visible: bool | None = None is_featured: bool | None = None # ── Evidence documents ──────────────────────────────────────────────── class DocPresignRequest(BaseModel): filename: str = Field(min_length=1, max_length=255) content_type: str = Field(min_length=3, max_length=128) size_bytes: int = Field(gt=0) checksum_sha256: str = Field(min_length=44, max_length=44) class DocCreateRequest(BaseModel): title: str = Field(min_length=1, max_length=255) category: str = Field(default="other", max_length=32) description: str | None = Field(default=None, max_length=4000) object_key: str = Field(min_length=1, max_length=512) filename: str = Field(min_length=1, max_length=255) content_type: str = Field(min_length=3, max_length=128) size_bytes: int | None = Field(default=None, ge=0) version: str | None = Field(default=None, max_length=32) owner_person_id: UUID | None = None valid_until: date | None = None is_shareable: bool = True class DocUpdateRequest(BaseModel): title: str | None = Field(default=None, max_length=255) category: str | None = Field(default=None, max_length=32) description: str | None = Field(default=None, max_length=4000) version: str | None = Field(default=None, max_length=32) owner_person_id: UUID | None = None valid_until: date | None = None is_shareable: bool | None = None status: str | None = Field(default=None, max_length=16) # ── Inbound questionnaires ──────────────────────────────────────────── class InboundCreateRequest(BaseModel): customer_name: str = Field(min_length=1, max_length=255) title: str = Field(min_length=1, max_length=255) due_date: date | None = None owner_person_id: UUID | None = None notes: str | None = Field(default=None, max_length=8000) class InboundMetaUpdateRequest(BaseModel): customer_name: str | None = Field(default=None, max_length=255) title: str | None = Field(default=None, max_length=255) due_date: date | None = None owner_person_id: UUID | None = None notes: str | None = Field(default=None, max_length=8000) class InboundStatusRequest(BaseModel): status: str = Field(max_length=16) class InboundSourcePresignRequest(BaseModel): filename: str = Field(min_length=1, max_length=255) content_type: str = Field(min_length=3, max_length=128) size_bytes: int = Field(gt=0) checksum_sha256: str = Field(min_length=44, max_length=44) class InboundSourceRegisterRequest(BaseModel): object_key: str = Field(min_length=1, max_length=512) filename: str = Field(min_length=1, max_length=255) class QuestionItem(BaseModel): text: str = Field(min_length=1, max_length=8000) section: str | None = Field(default=None, max_length=255) class AddQuestionsRequest(BaseModel): items: list[QuestionItem] = Field(min_length=1, max_length=1000) class SetAnswerRequest(BaseModel): answer_text: str | None = Field(default=None, max_length=16000) matched_library_entry_id: UUID | None = None class ReviewQuestionRequest(BaseModel): reviewed: bool = True class BackfillRequest(BaseModel): category: str = Field(default="general", max_length=64) existing_entry_id: UUID | None = None class ExportRequest(BaseModel): note: str | None = Field(default=None, max_length=2000)