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) standard: str = Field(default="eskd", pattern="^(eskd|espd)$") 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 standard: str = "eskd" 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 chat_id: Optional[int] = None class LlmEdit(BaseModel): op: str row_id: Optional[int] = None row_index: Optional[int] = None fields: dict[str, Any] = {} class LlmContextUsage(BaseModel): used: int = 0 limit: int = 0 percent: float = 0 prompt_tokens: Optional[int] = None completion_tokens: Optional[int] = None class LlmChatResponse(BaseModel): reply: str edits: list[LlmEdit] = [] message_id: Optional[int] = None chat_id: Optional[int] = None context: Optional[LlmContextUsage] = None class LlmApplyRequest(BaseModel): table_type: str edits: list[LlmEdit] class LlmChatCreate(BaseModel): title: Optional[str] = None table_type: Optional[str] = None class LlmChatOut(BaseModel): id: int title: str table_type: Optional[str] = None created_at: datetime updated_at: datetime message_count: int = 0 class LlmMessageOut(BaseModel): id: int role: str content: str table_type: Optional[str] = None proposed_edits: Optional[list[Any]] = None created_at: datetime class LlmChatDetail(BaseModel): id: int title: str table_type: Optional[str] = None created_at: datetime updated_at: datetime messages: list[LlmMessageOut] = [] context: Optional[LlmContextUsage] = None class ExportRequest(BaseModel): table_type: str format: str = "pdf" # pdf | xlsx class DesignatorMappingOut(BaseModel): id: int prefix: str singular_name: str plural_name: str class DesignatorMappingIn(BaseModel): prefix: str = Field(min_length=1, max_length=16) singular_name: str = "" plural_name: str = "" class DesignatorMappingsReplace(BaseModel): mappings: list[DesignatorMappingIn] class LoginRequest(BaseModel): username: str = Field(min_length=1, max_length=64) password: str = Field(min_length=1) class LoginResponse(BaseModel): access_token: str token_type: str = "bearer" username: str class TableSettingsUpdate(BaseModel): mappings: Optional[list[str]] = None column_mappings: Optional[dict[str, str]] = None simple_list: Optional[dict[str, Any]] = None