e2b03d98创建于 2025年9月23日历史提交
"""Document models and schemas (UUID / PG)."""

from __future__ import annotations
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field, AliasChoices

from whyhow_api.schemas.base import (
    AllowedUserMetadataTypes,
    BaseAssignmentModel,
    BaseDocument,
    BaseResponse,
    BaseUnassignmentModel,
    Document_Status,
    ErrorDetails,
    File_Extensions,
)
from whyhow_api.schemas.workspaces import WorkspaceDetails


class DocumentInfo(BaseModel):
    """Document info model for uploads."""
    content: bytes = Field(..., description="Content of the document in bytes")
    filename: str = Field(..., description="Filename of the document")
    content_type: str
    size: int = Field(..., description="Size of the document", examples=[1234])
    tags: list[str] | None = None
    user_metadata: dict[str, dict[str, AllowedUserMetadataTypes | list[AllowedUserMetadataTypes]]] | None = None


class DocumentMetadata(BaseModel):
    """Document metadata model."""
    size: int = Field(..., description="Size of the document", examples=[1234])
    format: File_Extensions = Field(..., description="Format of the document")
    filename: str = Field(..., description="Filename of the document", min_length=1)


class DocumentDocumentModel(BaseDocument):
    """Document document model (PG)."""
    workspaces: list[UUID] = Field(default_factory=list, description="Workspace IDs document is assigned to.")
    status: Document_Status
    errors: list[ErrorDetails] = Field(default=[], description="Errors during processing.")
    metadata: DocumentMetadata
    tags: dict[str, list[str]] = Field(default_factory=dict, description="List of tags")
    user_metadata: dict[str, dict[str, AllowedUserMetadataTypes | list[AllowedUserMetadataTypes]]] = Field(
        default_factory=dict, description="User defined metadata"
    )

class DocumentOut(DocumentDocumentModel):
    """Document response model."""
    id: UUID = Field(..., validation_alias=AliasChoices("_id", "id"), serialization_alias="id")
    created_by: UUID
    workspaces: list[UUID]

    model_config = ConfigDict(use_enum_values=True, from_attributes=True, populate_by_name=True)


class DocumentOutWithWorkspaceDetails(DocumentOut):
    """Document response model with workspace details."""
    workspaces: list[WorkspaceDetails]


class DocumentUpdate(BaseModel):
    """Document model for PUT body."""
    user_metadata: dict[str, AllowedUserMetadataTypes | list[AllowedUserMetadataTypes]] | None = None
    tags: list[str] | None = None


class DocumentDetail(BaseModel):
    """Schema for document details."""
    id: UUID = Field(..., validation_alias=AliasChoices("_id", "id"), serialization_alias="id")
    filename: str = Field(..., description="Filename of the document", min_length=1)


class DocumentsResponse(BaseResponse):
    """Schema for the response body of the documents endpoints."""
    documents: list[DocumentOut] = Field(default_factory=list, description="list of documents")


class DocumentsResponseWithWorkspaceDetails(BaseResponse):
    """Schema for the response body of the documents endpoints with workspace details."""
    documents: list[DocumentOutWithWorkspaceDetails] = Field(default_factory=list, description="list of documents")


class DocumentUnassignments(BaseUnassignmentModel):
    """Document unassignments model."""
    pass


class DocumentAssignments(BaseAssignmentModel):
    """Document assignments model."""
    pass


class DocumentAssignmentResponse(BaseResponse):
    """Response model for the assign documents endpoint."""
    documents: DocumentAssignments


class DocumentUnassignmentResponse(BaseResponse):
    """Response model for the unassign documents endpoint."""
    documents: DocumentUnassignments


class GeneratePresignedRequest(BaseModel):
    """Request model for generating a presigned post."""
    filename: str = Field(..., description="Filename of the document", min_length=1)
    workspace_id: UUID


class GeneratePresignedResponse(BaseModel):
    """Response model for generating a presigned post."""
    url: str
    fields: dict[str, str]


class GeneratePresignedDownloadRequest(BaseModel):
    """Request model for generating a presigned download url."""
    filename: str = Field(..., description="Filename of the document", min_length=1)


class GeneratePresignedDownloadResponse(BaseModel):
    """Response model for generating a presigned download url."""
    url: str = Field(..., description="Download URL of the document", min_length=1)


class DocumentStateErrorsUpdate(BaseModel):
    """Model for updating the state and errors of a document."""
    status: Document_Status
    errors: list[ErrorDetails] = Field(default_factory=list, description="Details about processing errors.")