"""Pydantic schemas for report generation API Request and response models for the report generation endpoints. """ from pydantic import BaseModel, Field, ConfigDict, field_serializer from typing import Optional, List from datetime import datetime from enum import Enum class ReportStatus(str, Enum): """Report generation status""" PENDING = "pending" COLLECTING_DATA = "collecting_data" GENERATING_CONTENT = "generating_content" ASSEMBLING_DOCUMENT = "assembling_document" COMPLETED = "completed" FAILED = "failed" # Request Schemas class ReportGenerateRequest(BaseModel): """Request to generate a report (optional parameters)""" include_images: bool = Field(default=True, description="Whether to embed images in the report") include_file_list: bool = Field(default=True, description="Whether to include file attachment list") # Response Schemas class ReportGenerateResponse(BaseModel): """Response after triggering report generation""" report_id: str = Field(..., description="Unique report identifier") status: ReportStatus = Field(..., description="Initial status (typically 'pending')") message: str = Field(default="Report generation started", description="Status message") class ReportStatusResponse(BaseModel): """Full report metadata response""" report_id: str room_id: str generated_by: str generated_at: datetime status: ReportStatus error_message: Optional[str] = None report_title: Optional[str] = None prompt_tokens: Optional[int] = None completion_tokens: Optional[int] = None model_config = ConfigDict(from_attributes=True) @field_serializer("generated_at") def serialize_datetime(self, dt: datetime) -> str: """Serialize datetime with 'Z' suffix to indicate UTC""" return dt.isoformat() + "Z" class ReportListItem(BaseModel): """Report item in list response""" report_id: str generated_at: datetime generated_by: str status: ReportStatus report_title: Optional[str] = None model_config = ConfigDict(from_attributes=True) @field_serializer("generated_at") def serialize_datetime(self, dt: datetime) -> str: """Serialize datetime with 'Z' suffix to indicate UTC""" return dt.isoformat() + "Z" class ReportListResponse(BaseModel): """List of reports for a room""" reports: List[ReportListItem] total: int class ReportMarkdownResponse(BaseModel): """Report content in Markdown format for in-page preview""" report_id: str report_title: Optional[str] = None markdown: str = Field(..., description="Full report content in Markdown format") # AI Report Content Schemas (validated JSON from DIFY) class TimelineEvent(BaseModel): """Single event in timeline""" time: str = Field(..., description="Time of event (HH:MM or YYYY-MM-DD HH:MM)") description: str = Field(..., description="Event description") class ParticipantInfo(BaseModel): """Participant information""" name: str = Field(..., description="Participant name") role: str = Field(..., description="Role in incident (e.g., 事件發起人, 維修負責人)") class AIReportContent(BaseModel): """Validated JSON schema from DIFY AI response""" summary: dict = Field(..., description="Event summary with 'content' field") timeline: dict = Field(..., description="Timeline with 'events' list") participants: dict = Field(..., description="Participants with 'members' list") resolution_process: dict = Field(..., description="Resolution process with 'content' field") current_status: dict = Field(..., description="Current status with 'status' and 'description' fields") final_resolution: dict = Field(..., description="Final resolution with 'has_resolution' and 'content' fields") @classmethod def validate_structure(cls, data: dict) -> bool: """Validate the basic structure of AI response""" required_keys = ["summary", "timeline", "participants", "resolution_process", "current_status", "final_resolution"] for key in required_keys: if key not in data: return False return True # Error Response class ErrorResponse(BaseModel): """Error response""" detail: str # Health Check Response class HealthCheckResponse(BaseModel): """DIFY service health check response""" status: str = Field(..., description="Status: 'ok' or 'error'") message: str = Field(..., description="Human-readable status message")