from typing import Optional, List from datetime import datetime, date from decimal import Decimal from pydantic import BaseModel, Field from .models import OperationType # --- Base Schemas --- class InvoiceHeaderBase(BaseModel): """Base fields for Invoice Header""" operation_type: Optional[OperationType] = Field( None, max_length=20, description="Operation type: imp/exp") invoice_type: Optional[str] = Field( None, max_length=5, description="Invoice type key") invoice_number: Optional[str] = Field( None, max_length=20, description="Invoice number") project_number: Optional[str] = Field( None, max_length=14, description="Project number") purchase_order: Optional[str] = Field( None, max_length=50, description="Purchase order") related_doc_id: Optional[int] = Field( None, description="Related document ID for rectifications") invoice_date: Optional[date] = Field(None, description="Invoice date") is_updated: Optional[bool] = Field(None, description="Status") traffic_light_status: Optional[str] = Field( None, max_length=50, description="Traffic light status (SEMAFORO)") process_log: Optional[str] = Field( None, max_length=300, description="Processing log") comments_status: Optional[str] = Field( None, description="Comments and observations") cfdi_uuid: Optional[str] = Field( None, max_length=100, description="CFDI UUID") path_pdf: Optional[str] = Field( None, max_length=500, description="Path to PDF file") path_xml: Optional[str] = Field( None, max_length=500, description="Path to XML file") class InvoiceComplianceMxBase(BaseModel): """Base fields for Compliance MX""" pedimento: Optional[str] = Field( None, max_length=19, description="Pedimento number") pedimento_code: Optional[str] = Field( None, max_length=5, description="Pedimento code (R1/K1)") remesa: Optional[int] = Field(None, description="Remesa") aduana: Optional[str] = Field( None, max_length=5, description="Customs office") customs_agent: Optional[str] = Field( None, max_length=10, description="Customs agent") is_mixed: Optional[bool] = Field( None, description="Is mixed operation") waste_type: Optional[str] = Field( None, max_length=1, description="Waste type") appendix_17: Optional[int] = Field(None, description="Appendix 17") edocument: Optional[str] = Field( None, max_length=50, description="E-document") electronic_signature: Optional[str] = Field( None, max_length=999, description="Electronic signature") sem_id: Optional[int] = Field(None, description="SEM ID") class InvoiceFinancialsBase(BaseModel): """Base fields for Financials""" currency: Optional[str] = Field( None, max_length=3, description="Currency code") exchange_rate: Optional[Decimal] = Field(None, description="Exchange rate") value_mn: Optional[Decimal] = Field(None, description="Value in MXN") value_me: Optional[Decimal] = Field( None, description="Value in foreign currency") customs_value_mn: Optional[Decimal] = Field( None, description="Customs value in MXN") freight: Optional[Decimal] = Field(None, description="Freight cost") insurance: Optional[Decimal] = Field(None, description="Insurance cost") iva_mn: Optional[Decimal] = Field(None, description="IVA in MXN") iva_factor: Optional[Decimal] = Field(None, description="IVA factor") total_quantity: Optional[Decimal] = Field( None, description="Total quantity") gross_weight: Optional[Decimal] = Field(None, description="Gross weight") net_weight: Optional[Decimal] = Field(None, description="Net weight") bundle_count: Optional[int] = Field(None, description="Bundle count") class InvoiceLogisticsBase(BaseModel): """Base fields for Logistics""" carrier_id: Optional[str] = Field( None, max_length=10, description="Carrier ID") transport_mode: Optional[str] = Field( None, max_length=15, description="Transport mode") driver_name: Optional[str] = Field( None, max_length=80, description="Driver name") is_rail: Optional[str] = Field( None, max_length=2, description="Is rail transport") rail_id: Optional[str] = Field(None, max_length=31, description="Rail ID") vehicle_num: Optional[str] = Field( None, max_length=20, description="Vehicle number") license_plate: Optional[str] = Field( None, max_length=20, description="License plate") seal_number: Optional[str] = Field( None, max_length=15, description="Seal number") guide_number: Optional[str] = Field( None, max_length=20, description="Guide number") entry_exit_date: Optional[date] = Field( None, description="Entry/Exit date") class InvoiceSalesDetailsBase(BaseModel): """Base fields for Sales Details""" line_number: int = Field(..., description="Line number") sales_order: Optional[str] = Field( None, max_length=20, description="Sales order") colors_description: Optional[str] = Field( None, max_length=49, description="Colors description") square_color_code: Optional[str] = Field( None, max_length=1, description="Square color code") line_bundles: Optional[int] = Field(None, description="Line bundles count") class InvoiceCollectionsBase(BaseModel): """Base fields for Collections""" concept: Optional[str] = Field(None, max_length=100, description="Concept") is_collected: Optional[int] = Field(None, description="Is collected flag") collection_date: Optional[date] = Field( None, description="Collection date") amount: Optional[Decimal] = Field(None, description="Amount") collector_user: Optional[str] = Field( None, max_length=20, description="Collector user") # --- Create Schemas --- class InvoiceComplianceMxCreate(InvoiceComplianceMxBase): """Schema for creating Compliance MX""" pass class InvoiceFinancialsCreate(InvoiceFinancialsBase): """Schema for creating Financials""" pass class InvoiceLogisticsCreate(InvoiceLogisticsBase): """Schema for creating Logistics""" pass class InvoiceSalesDetailsCreate(InvoiceSalesDetailsBase): """Schema for creating Sales Details""" pass class InvoiceCollectionsCreate(InvoiceCollectionsBase): """Schema for creating Collections""" pass class InvoiceHeaderCreate(InvoiceHeaderBase): """Schema for creating Invoice Header with nested relations""" compliance_mx: Optional[InvoiceComplianceMxCreate] = None financials: Optional[InvoiceFinancialsCreate] = None logistics: Optional[List[InvoiceLogisticsCreate]] = None details: Optional[List[InvoiceSalesDetailsCreate]] = None collections: Optional[List[InvoiceCollectionsCreate]] = None # --- Update Schemas --- class InvoiceComplianceMxUpdate(InvoiceComplianceMxBase): """Schema for updating Compliance MX""" pass class InvoiceFinancialsUpdate(InvoiceFinancialsBase): """Schema for updating Financials""" pass class InvoiceLogisticsUpdate(InvoiceLogisticsBase): """Schema for updating Logistics""" pass class InvoiceSalesDetailsUpdate(InvoiceSalesDetailsBase): """Schema for updating Sales Details""" line_number: Optional[int] = None class InvoiceCollectionsUpdate(InvoiceCollectionsBase): """Schema for updating Collections""" pass class InvoiceHeaderUpdate(InvoiceHeaderBase): """Schema for updating Invoice Header with nested relations""" compliance_mx: Optional[InvoiceComplianceMxUpdate] = None financials: Optional[InvoiceFinancialsUpdate] = None logistics: Optional[List[InvoiceLogisticsUpdate]] = None details: Optional[List[InvoiceSalesDetailsUpdate]] = None collections: Optional[List[InvoiceCollectionsUpdate]] = None # --- Response Schemas --- class InvoiceComplianceMxResponse(InvoiceComplianceMxBase): """Schema for Compliance MX response""" invoice_id: int class Config: from_attributes = True class InvoiceFinancialsResponse(InvoiceFinancialsBase): """Schema for Financials response""" invoice_id: int class Config: from_attributes = True class InvoiceLogisticsResponse(InvoiceLogisticsBase): """Schema for Logistics response""" logistics_id: int invoice_id: int class Config: from_attributes = True class InvoiceSalesDetailsResponse(InvoiceSalesDetailsBase): """Schema for Sales Details response""" detail_id: int invoice_id: int class Config: from_attributes = True class InvoiceCollectionsResponse(InvoiceCollectionsBase): """Schema for Collections response""" collection_id: int invoice_id: int class Config: from_attributes = True class InvoiceHeaderResponse(InvoiceHeaderBase): """Schema for Invoice Header response with nested relations""" id: int capture_date: datetime compliance_mx: Optional[InvoiceComplianceMxResponse] = None financials: Optional[InvoiceFinancialsResponse] = None logistics: List[InvoiceLogisticsResponse] = [] details: List[InvoiceSalesDetailsResponse] = [] collections: List[InvoiceCollectionsResponse] = [] class Config: from_attributes = True