""" Data models for file-centric download system. Each download record represents ONE file, not a batch. """ from pydantic import BaseModel from typing import Optional from datetime import datetime from decimal import Decimal class FileDownload(BaseModel): """Represents a single file download record in the database.""" id: int batch_id: str # File info ge_id: str lang: str file_name: str file_path: str # Relative path in source # Mode & status mode: str # 'api' or 'sharing' status: str # 'pending', 'downloading', 'completed', 'failed', 'cancelled' # Paths destination_path: Optional[str] = None # Progress file_size: Optional[int] = None downloaded_size: int = 0 progress_percent: Decimal = Decimal('0.00') # Timestamps created_at: datetime started_at: Optional[datetime] = None completed_at: Optional[datetime] = None # Error handling error_message: Optional[str] = None retry_count: int = 0 # Metadata sharing_id: Optional[str] = None mongodb_path: Optional[str] = None class Config: from_attributes = True # For Pydantic v2 (orm_mode in v1) # ==================== REQUEST MODELS ==================== class FileInfo(BaseModel): """Single file information for batch download requests.""" name: str path: str # Relative path in source isdir: bool = False # For API mode is_folder: Optional[bool] = None # For Sharing mode (alias) class CreateDownloadBatchRequest(BaseModel): """ Request to create a batch of file downloads (API mode). Each file will become a separate download record. """ files: list[FileInfo] ge_id: str lang: str class CreateSharingDownloadBatchRequest(BaseModel): """ Request to create batch downloads from sharing link. """ sharing_id: str files: list[FileInfo] ge_id: Optional[str] = None lang: Optional[str] = None class UpdateDownloadRequest(BaseModel): """Request to update a single download (cancel/retry).""" action: str # 'retry' or 'cancel' # ==================== RESPONSE MODELS ==================== class DownloadBatchResponse(BaseModel): """Response after creating a batch of downloads.""" success: bool batch_id: str file_count: int download_ids: list[int] # List of created download IDs message: str class DownloadResponse(BaseModel): """Response for single download operation.""" success: bool download: Optional[FileDownload] = None message: str class DownloadListResponse(BaseModel): """Response for listing downloads.""" success: bool downloads: list[FileDownload] count: int # ==================== BATCH GROUPING ==================== class DownloadBatch(BaseModel): """ Grouped view of downloads for UI display. Groups files by batch_id for better UX. """ batch_id: str ge_id: str lang: str mode: str # Batch-level stats total_files: int completed_files: int failed_files: int total_size: int downloaded_size: int # Batch status (derived from files) status: str # 'downloading', 'completed', 'partial_failed', 'failed' # Timestamps (min/max from files) created_at: datetime started_at: Optional[datetime] = None completed_at: Optional[datetime] = None # Duration (if completed) duration_seconds: Optional[float] = None # Individual files in this batch files: list[FileDownload]