""" DTOs (Data Transfer Objects) para módulo de partes/componentes Reemplaza schemas.py siguiendo enfoque DDD y estilo NestJS """ from datetime import datetime from decimal import Decimal from typing import Optional from pydantic import BaseModel, Field class PartCreateDTO(BaseModel): """DTO para crear una parte""" client_id: int = Field(..., description="Client key") part_number: str = Field(..., max_length=49, description="Part number") fraction: Optional[str] = Field(None, max_length=10, description="Tariff fraction") description_spanish: Optional[str] = Field( None, max_length=500, description="Description in Spanish" ) description_english: Optional[str] = Field( None, max_length=500, description="Description in English" ) part_class: Optional[str] = Field(None, max_length=8, description="Part class") unit_of_measure: Optional[str] = Field( None, max_length=5, description="Unit of measure" ) commercial_part_number: Optional[str] = Field( None, max_length=70, description="Commercial part number" ) country_of_origin: Optional[str] = Field( None, max_length=3, description="Country of origin code" ) # Pricing and currency unit_cost: Optional[Decimal] = Field(None, description="Unit cost") currency_type: Optional[str] = Field( None, max_length=2, description="Currency type" ) currency_key: Optional[str] = Field(None, max_length=3, description="Currency key") # Weight information unit_weight: Optional[Decimal] = Field(None, description="Unit weight") weight_type: Optional[str] = Field(None, max_length=6, description="Weight type") # Classification and regulatory us_fraction: Optional[str] = Field( None, max_length=16, description="US tariff fraction" ) fda_key: Optional[str] = Field(None, max_length=20, description="FDA key") fcc_key: Optional[str] = Field(None, max_length=30, description="FCC key") license_code: Optional[str] = Field(None, max_length=3, description="License code") eccn: Optional[str] = Field( None, max_length=20, description="Export Control Classification Number" ) export_code: Optional[str] = Field(None, max_length=2, description="Export code") exclusion_symbol: Optional[str] = Field( None, max_length=19, description="Exclusion symbol" ) # Additional information supplier: Optional[str] = Field(None, max_length=14, description="Supplier") alternate_unit_measure: Optional[str] = Field( None, max_length=14, description="Alternate unit of measure" ) added_value: Optional[Decimal] = Field(None, description="Added value") # Status and media is_active: Optional[bool] = Field(None, description="Enabled/Disabled status") creation_date: Optional[int] = Field(None, description="Creation date") part_photo: Optional[str] = Field( None, max_length=255, description="Part photo URL" ) class Config: from_attributes = True class PartUpdateDTO(BaseModel): """DTO para actualizar una parte""" fraction: Optional[str] = Field(None, max_length=10, description="Tariff fraction") description_spanish: Optional[str] = Field( None, max_length=500, description="Description in Spanish" ) description_english: Optional[str] = Field( None, max_length=500, description="Description in English" ) part_class: Optional[str] = Field(None, max_length=8, description="Part class") unit_of_measure: Optional[str] = Field( None, max_length=5, description="Unit of measure" ) commercial_part_number: Optional[str] = Field( None, max_length=70, description="Commercial part number" ) country_of_origin: Optional[str] = Field( None, max_length=3, description="Country of origin code" ) # Pricing and currency unit_cost: Optional[Decimal] = Field(None, description="Unit cost") currency_type: Optional[str] = Field( None, max_length=2, description="Currency type" ) currency_key: Optional[str] = Field(None, max_length=3, description="Currency key") # Weight information unit_weight: Optional[Decimal] = Field(None, description="Unit weight") weight_type: Optional[str] = Field(None, max_length=6, description="Weight type") # Classification and regulatory us_fraction: Optional[str] = Field( None, max_length=16, description="US tariff fraction" ) fda_key: Optional[str] = Field(None, max_length=20, description="FDA key") fcc_key: Optional[str] = Field(None, max_length=30, description="FCC key") license_code: Optional[str] = Field(None, max_length=3, description="License code") eccn: Optional[str] = Field( None, max_length=20, description="Export Control Classification Number" ) export_code: Optional[str] = Field(None, max_length=2, description="Export code") exclusion_symbol: Optional[str] = Field( None, max_length=19, description="Exclusion symbol" ) # Additional information supplier: Optional[str] = Field(None, max_length=14, description="Supplier") alternate_unit_measure: Optional[str] = Field( None, max_length=14, description="Alternate unit of measure" ) added_value: Optional[Decimal] = Field(None, description="Added value") # Status and media is_active: Optional[bool] = Field(None, description="Enabled/Disabled status") part_photo: Optional[str] = Field( None, max_length=255, description="Part photo URL" ) class Config: from_attributes = True class PartResponseDTO(BaseModel): """DTO para respuesta de parte""" client_id: int part_number: str fraction: Optional[str] = None description_spanish: Optional[str] = None description_english: Optional[str] = None part_class: Optional[str] = None unit_of_measure: Optional[str] = None commercial_part_number: Optional[str] = None country_of_origin: Optional[str] = None # Pricing and currency unit_cost: Optional[Decimal] = None currency_type: Optional[str] = None currency_key: Optional[str] = None # Weight information unit_weight: Optional[Decimal] = None weight_type: Optional[str] = None # Classification and regulatory us_fraction: Optional[str] = None fda_key: Optional[str] = None fcc_key: Optional[str] = None license_code: Optional[str] = None eccn: Optional[str] = None export_code: Optional[str] = None exclusion_symbol: Optional[str] = None # Additional information supplier: Optional[str] = None alternate_unit_measure: Optional[str] = None added_value: Optional[Decimal] = None # Status and dates is_active: Optional[bool] = None creation_date: Optional[int] = None modification_date: Optional[int] = None modification_date_iso: Optional[datetime] = None # Media part_photo: Optional[str] = None class Config: from_attributes = True class PartBasicDTO(BaseModel): """DTO para información básica de parte""" client_id: int part_number: str description_spanish: Optional[str] = None description_english: Optional[str] = None part_class: Optional[str] = None unit_cost: Optional[Decimal] = None currency_key: Optional[str] = None is_active: Optional[bool] = None class Config: from_attributes = True class PartListDTO(BaseModel): """DTO para lista de partes""" parts: list[PartBasicDTO] total: int page: int size: int class Config: from_attributes = True class PartSearchDTO(BaseModel): """DTO para búsqueda de partes""" client_id: Optional[int] = Field(None, description="Filter by client key") part_number: Optional[str] = Field(None, description="Search by part number") description: Optional[str] = Field(None, description="Search in descriptions") fraction: Optional[str] = Field(None, description="Filter by tariff fraction") supplier: Optional[str] = Field(None, description="Filter by supplier") enabled_only: bool = Field(False, description="Show only enabled parts") class Config: from_attributes = True