from __future__ import annotations from datetime import datetime from typing import Any, Optional from pydantic import BaseModel, Field class ProjectCreate(BaseModel): name: str = Field(min_length=1, max_length=255) class ProjectUpdate(BaseModel): name: Optional[str] = None current_variant: Optional[str] = None decimal_number: Optional[str] = None board_name: Optional[str] = None class ProjectOut(BaseModel): id: int name: str status: str current_variant: str zip_path: Optional[str] = None pcb_doc_name: Optional[str] = None decimal_number: str board_name: str error_message: Optional[str] = None created_at: datetime updated_at: datetime variants: list[str] = [] component_count: int = 0 layer_count: int = 0 model_config = {"from_attributes": True} class ComponentPropertyOut(BaseModel): key: str value: str class ComponentOut(BaseModel): id: int designator: str properties: list[ComponentPropertyOut] = [] is_fitted: bool = True model_config = {"from_attributes": True} class ProjectParamOut(BaseModel): id: int name: str value: str variant_name: str = "" model_config = {"from_attributes": True} class DielMaterialOut(BaseModel): name: str value: str height: float diel_type: int layer_number: int model_config = {"from_attributes": True} class PcbInfoOut(BaseModel): layer_count: int = 0 materials: list[DielMaterialOut] = [] class InscriptionOut(BaseModel): field_number: int field_value: str class InscriptionsUpdate(BaseModel): inscriptions: dict[int, str] class TableRowBase(BaseModel): id: Optional[int] = None row_index: int = 0 page_number: int = 1 is_header: bool = False is_empty: bool = False is_auto_generated: bool = True stretch: bool = False is_underline: bool = False class PerechenRowOut(TableRowBase): position: str = "" designation: str = "" quantity: str = "" note: str = "" class SpecPcbRowOut(TableRowBase): format: str = "" zone: str = "" position: str = "" designation: str = "" name: str = "" quantity: str = "" note: str = "" class SpecRowOut(TableRowBase): format: str = "" zone: str = "" position: str = "" designation: str = "" name: str = "" quantity: str = "" note: str = "" class VedomostRowOut(TableRowBase): name: str = "" product_code: str = "" document_code: str = "" supplier: str = "" where_used: str = "" quantity_per_item: str = "" quantity_in_set: str = "" quantity_for_reg: str = "" total_quantity: str = "" note: str = "" class SimpleListRowOut(BaseModel): id: Optional[int] = None row_index: int = 0 designator: str = "" name: str = "" quantity: str = "" is_auto_generated: bool = True is_empty: bool = False class TableRowsResponse(BaseModel): table_type: str rows: list[dict[str, Any]] class TableRowsPatch(BaseModel): rows: list[dict[str, Any]] class GenerateTableRequest(BaseModel): name_field: Optional[str] = None tech_reserve_percent: Optional[float] = None boards_count: Optional[int] = None class LlmChatRequest(BaseModel): message: str = Field(min_length=1) table_type: str class LlmEdit(BaseModel): op: str row_id: Optional[int] = None row_index: Optional[int] = None fields: dict[str, Any] = {} class LlmChatResponse(BaseModel): reply: str edits: list[LlmEdit] = [] message_id: Optional[int] = None class LlmApplyRequest(BaseModel): table_type: str edits: list[LlmEdit] class ExportRequest(BaseModel): table_type: str format: str = "pdf" # pdf | xlsx class DesignatorMappingOut(BaseModel): prefix: str singular_name: str plural_name: str