Files
plantillas-proyectos/backend/api/v1/modules/a76/parts/dto.py
acazares 52b8fcd434 feat: Implement multi-tenancy support in middleware and security layers
- Enhanced TenantMiddleware to validate tenant information from JWT tokens.
- Added LicenseValidationMiddleware to check tenant licenses before processing requests.
- Updated security utilities to extract tenant information from tokens and validate company access.
- Introduced CompanyStore to manage active company state and handle company switching in the frontend.
- Modified API routes to include company_id in requests for better resource management.
- Improved logging and error handling throughout the middleware and API layers.
- Updated frontend components to reflect changes in company management and selection.
- Added new API route for fetching user's companies with proper authentication handling.
2025-11-11 14:15:31 -06:00

232 lines
8.1 KiB
Python

"""
DTOs (Data Transfer Objects) para módulo de partes/componentes
Reemplaza schemas.py siguiendo enfoque DDD y estilo NestJS
"""
from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime
from decimal import Decimal
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
enabled_disabled: Optional[int] = 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
enabled_disabled: Optional[int] = 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
enabled_disabled: Optional[int] = 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
enabled_disabled: Optional[int] = 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