637 lines
25 KiB
Python
637 lines
25 KiB
Python
from typing import Literal, Optional, List
|
|
from datetime import datetime, date
|
|
from decimal import Decimal
|
|
from pydantic import BaseModel, Field, field_validator
|
|
from .models import (
|
|
DestinationOriginCove,
|
|
OperationType,
|
|
Currency,
|
|
TransportType,
|
|
WeightUnit,
|
|
)
|
|
|
|
|
|
# --- Base Schemas ---
|
|
class InvoiceHeaderBase(BaseModel):
|
|
"""Base fields for Invoice Header"""
|
|
|
|
system: Optional[str] = Field(None, max_length=12, description="System of origin")
|
|
operation_type: Optional[OperationType] = Field(
|
|
..., description="Operation type: imp/exp/sm/ctm"
|
|
)
|
|
|
|
@field_validator("operation_type", mode="before")
|
|
@classmethod
|
|
def normalize_operation_type(cls, v):
|
|
"""Accept DB string (e.g. 'IMP') and coerce to enum value ('imp')."""
|
|
if isinstance(v, str):
|
|
return v.lower() if v else v
|
|
return v
|
|
invoice_type: Optional[str] = Field(
|
|
None, max_length=5, description="Invoice type key"
|
|
)
|
|
document_type: Optional[str] = Field(
|
|
None, max_length=3, description="Document type (Regimen Aduanero)"
|
|
)
|
|
invoice_number: Optional[str] = Field(
|
|
None, max_length=100, 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"
|
|
)
|
|
alternate_invoice: Optional[str] = Field(
|
|
None, max_length=99, description="Alternate invoice"
|
|
)
|
|
invoice_ref: Optional[str] = Field(
|
|
None, max_length=19, description="Invoice reference"
|
|
)
|
|
proforma_number: Optional[str] = Field(
|
|
None, max_length=20, description="Proforma number"
|
|
)
|
|
invoice_date: date = Field(..., description="Invoice date")
|
|
emission_date: Optional[date] = Field(None, description="Emission date")
|
|
is_updated: bool = Field(False, description="Status")
|
|
updated_date: Optional[datetime] = Field(None, description="Update date")
|
|
who_updated: Optional[str] = Field(None, max_length=20, description="Who updated")
|
|
capture_user: Optional[str] = Field(None, max_length=20, description="Capture user")
|
|
traffic_light_status: Optional[str] = Field(
|
|
None, max_length=50, description="Traffic light status"
|
|
)
|
|
process_log: Optional[str] = Field(
|
|
None, max_length=300, description="Processing log"
|
|
)
|
|
is_updated_rec: Optional[int] = Field(None, description="Reception status")
|
|
is_updated_rep: Optional[str] = Field(
|
|
None, max_length=2, description="Report status"
|
|
)
|
|
observation_es: Optional[str] = Field(None, description="Observations in Spanish")
|
|
observation_en: Optional[str] = Field(None, description="Observations in English")
|
|
comments_status: Optional[str] = Field(None, description="Comments status")
|
|
vu_observations: Optional[str] = Field(
|
|
None, max_length=500, description="VUCEM 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"
|
|
)
|
|
subcompany: Optional[str] = Field(None, max_length=5, description="Subcompany")
|
|
party_count: Optional[int] = Field(None, description="Quantity of parties")
|
|
generate_id: Optional[bool] = Field(False, description="Generate ID")
|
|
generate_desc_parties: Optional[str] = Field(
|
|
None, max_length=12, description="Generate description of parties"
|
|
)
|
|
apply_manual_discount: Optional[bool] = Field(
|
|
False, description="Apply manual discount"
|
|
)
|
|
is_bulk: Optional[bool] = Field(None, description="Is bulk")
|
|
download_substance: Optional[bool] = Field(None, description="Download substance")
|
|
download_class: Optional[bool] = Field(None, description="Download class")
|
|
download_def: Optional[bool] = Field(None, description="Definitive download")
|
|
payment_terms: Optional[str] = Field(
|
|
None, max_length=200, description="Payment terms"
|
|
)
|
|
handling_fees: Optional[Decimal] = Field(None, description="Handling fees")
|
|
option_iv18: Optional[str] = Field(None, max_length=50, description="Option IV18")
|
|
enajenation_goods: Optional[bool] = Field(None, description="Enajenation of goods")
|
|
|
|
|
|
class InvoiceComplianceMxBase(BaseModel):
|
|
"""Base fields for Compliance MX"""
|
|
|
|
pedimento_id: Optional[int] = Field(None, description="Pedimento id")
|
|
pedimento_r1: Optional[int] = Field(None, description="Pedimento id (R1)")
|
|
pedimento_k1: Optional[int] = Field(None, description="Pedimento id (K1)")
|
|
remesa: Optional[int] = Field(None, description="Remesa")
|
|
aduana: Optional[str] = Field(None, max_length=5, description="Customs office")
|
|
port_of_entry: Optional[str] = Field(
|
|
None, max_length=6, description="Port of entry"
|
|
)
|
|
destination: Optional[str] = Field(
|
|
None, max_length=3, description="Destination code"
|
|
)
|
|
manifest_number: Optional[str] = Field(
|
|
None, max_length=15, description="Manifest number"
|
|
)
|
|
provider_header: Optional[str] = Field(None, max_length=20, description="Provider header")
|
|
provider_id: Optional[int] = Field(None, description="Provider ID")
|
|
sold_to_header: Optional[str] = Field(None, max_length=20, description="Sold to header")
|
|
sold_to_id: Optional[int] = Field(None, description="Sold to ID")
|
|
shipped_to_header: Optional[str] = Field(None, max_length=20, description="Shipped to header")
|
|
shipped_to_id: Optional[int] = Field(None, description="Shipped to ID")
|
|
shipped_by_header: Optional[str] = Field(
|
|
None, max_length=20, description="Shipped by header"
|
|
)
|
|
shipped_by_id: Optional[int] = Field(None, description="Shipped by ID")
|
|
customs_broker_id: Optional[int] = Field(None, description="Customs broker ID")
|
|
customs_broker_us_id: Optional[int] = Field(
|
|
None, description="US customs broker ID"
|
|
)
|
|
broker_invoice_num: Optional[str] = Field(
|
|
None, max_length=20, description="Broker invoice number"
|
|
)
|
|
broker_invoice_date: Optional[date] = Field(None, description="Broker invoice date")
|
|
is_mixed: Optional[bool] = Field(False, description="Is mixed operation")
|
|
waste_type: Optional[str] = Field(None, max_length=1, description="Waste type")
|
|
scrap_type: Optional[str] = Field(None, max_length=1, description="Scrap type")
|
|
appendix_17: Optional[int] = Field(None, description="Appendix 17")
|
|
is_regime_change: Optional[bool] = Field(False, description="Is regime change")
|
|
which_exchange_rate: Optional[str] = Field(
|
|
None, max_length=5, description="Which exchange rate"
|
|
)
|
|
rule_3121_parties_ii: Optional[bool] = Field(
|
|
False, description="Is Rule 3.1.21 Parties II"
|
|
)
|
|
value_method: Optional[str] = Field(None, max_length=2, description="Value method")
|
|
act_value: Optional[str] = Field(None, max_length=5, description="Act value")
|
|
is_pedimento_pending: bool = Field(..., description="Is pedimento pending")
|
|
is_owner_of_goods: Optional[bool] = Field(False, description="Is owner of goods")
|
|
generate_balances: Optional[bool] = Field(False, description="Generate balances")
|
|
was_reviewed_by_company: Optional[bool] = Field(
|
|
None, description="Was reviewed by company"
|
|
)
|
|
edocument: Optional[str] = Field(None, max_length=50, description="E-document")
|
|
electronic_signature: Optional[str] = Field(
|
|
None, max_length=999, description="Electronic signature"
|
|
)
|
|
certificate_number: Optional[str] = Field(
|
|
None, max_length=99, description="Certificate number"
|
|
)
|
|
niu_number: Optional[str] = Field(None, max_length=19, description="NIU number")
|
|
bill_of_lading_count: Optional[str] = Field(
|
|
None, max_length=12, description="Bill of lading count"
|
|
)
|
|
addendum_vu: Optional[str] = Field(
|
|
None, max_length=204, description="VUCEM addendum"
|
|
)
|
|
origin_destination_cove: Optional[DestinationOriginCove] = Field(
|
|
"franja_front_norte", max_length=20, description="Origin/Destination COVE"
|
|
)
|
|
vucem_operation_num: Optional[str] = Field(
|
|
None, max_length=19, description="VUCEM operation number"
|
|
)
|
|
customs_person_line: Optional[int] = Field(None, description="Customs person line")
|
|
contingency_mode: Optional[bool] = Field(None, description="Contingency mode")
|
|
enclosure: Optional[str] = Field(None, max_length=4, description="Enclosure")
|
|
guide_type_to_identify: Optional[str] = Field(
|
|
None, max_length=1, description="Guide type to identify"
|
|
)
|
|
location: Optional[str] = Field(None, max_length=200, description="Location")
|
|
dot_code: Optional[str] = Field(None, max_length=20, description="DOT code")
|
|
subdivision: Optional[str] = Field(None, max_length=20, description="Subdivision")
|
|
acts_as: Optional[str] = Field(None, max_length=20, description="Acts as")
|
|
movement_type: Optional[str] = Field(
|
|
None, max_length=31, description="Movement type"
|
|
)
|
|
office_document: Optional[str] = Field(
|
|
None, max_length=30, description="Office document"
|
|
)
|
|
reason_export: Optional[str] = Field(
|
|
None, max_length=1, description="Reason for export"
|
|
)
|
|
signature_key: Optional[str] = Field(
|
|
None, max_length=100, description="Signature key"
|
|
)
|
|
sem_id: Optional[int] = Field(None, description="SEM ID")
|
|
|
|
|
|
class InvoiceFinancialsBase(BaseModel):
|
|
"""Base fields for Financials"""
|
|
|
|
currency: Optional[Currency] = Field(None, max_length=7, description="Currency code")
|
|
currency_type: Optional[str] = Field("USD", description="Currency type")
|
|
exchange_rate: Optional[Decimal] = Field(0.00, description="Exchange rate")
|
|
exchange_rate_mm: Optional[Decimal] = Field(
|
|
None, description="Exchange rate currency to currency"
|
|
)
|
|
value_mn: Optional[Decimal] = Field(None, description="Value in MXN")
|
|
value_me: Optional[Decimal] = Field(None, description="Value in foreign currency")
|
|
value_mc: Optional[Decimal] = Field(None, description="Value in third currency")
|
|
customs_value_mn: Optional[Decimal] = Field(
|
|
None, description="Customs value in MXN"
|
|
)
|
|
customs_value_me: Optional[Decimal] = Field(
|
|
None, description="Customs value in foreign currency"
|
|
)
|
|
raw_material_value_mn: Optional[Decimal] = Field(
|
|
None, description="Raw material value in MXN"
|
|
)
|
|
raw_material_value_me: Optional[Decimal] = Field(
|
|
None, description="Raw material value in foreign currency"
|
|
)
|
|
aggregate_value_mn: Optional[Decimal] = Field(
|
|
None, description="Aggregate value in MXN"
|
|
)
|
|
aggregate_value_me: Optional[Decimal] = Field(
|
|
None, description="Aggregate value in foreign currency"
|
|
)
|
|
aggregate_value_mc: Optional[Decimal] = Field(
|
|
None, description="Aggregate value in third currency"
|
|
)
|
|
mexican_value_mn: Optional[Decimal] = Field(
|
|
None, description="Mexican merchandise value in MXN"
|
|
)
|
|
mexican_value_me: Optional[Decimal] = Field(
|
|
None, description="Mexican merchandise value in foreign currency"
|
|
)
|
|
mexican_value_mc: Optional[Decimal] = Field(
|
|
None, description="Mexican merchandise value in third currency"
|
|
)
|
|
national_packaging_mn: Optional[Decimal] = Field(
|
|
None, description="National packaging in MXN"
|
|
)
|
|
national_packaging_me: Optional[Decimal] = Field(
|
|
None, description="National packaging in foreign currency"
|
|
)
|
|
national_packaging_mc: Optional[Decimal] = Field(
|
|
None, description="National packaging in third currency"
|
|
)
|
|
freight: Optional[Decimal] = Field(None, description="Freight cost")
|
|
insurance: Optional[Decimal] = Field(None, description="Insurance cost")
|
|
insurance_value: Optional[Decimal] = Field(None, description="Insurance value")
|
|
packaging: Optional[Decimal] = Field(None, description="Packaging")
|
|
other_increments: Optional[Decimal] = Field(None, description="Other increments")
|
|
other_deductibles: Optional[Decimal] = Field(None, description="Other deductibles")
|
|
total_increments_mn: Optional[Decimal] = Field(
|
|
None, description="Total increments in MXN"
|
|
)
|
|
total_increments_me: Optional[Decimal] = Field(
|
|
None, description="Total increments in foreign currency"
|
|
)
|
|
iva_mn: Optional[Decimal] = Field(None, description="IVA in MXN")
|
|
iva_me: Optional[Decimal] = Field(None, description="IVA in foreign currency")
|
|
iva_mc: Optional[Decimal] = Field(None, description="IVA in third currency")
|
|
iva_factor: Optional[Decimal] = Field(None, description="IVA factor")
|
|
tax_value_me: Optional[Decimal] = Field(
|
|
None, description="Tax value in foreign currency"
|
|
)
|
|
seal_value_2500: Optional[bool] = Field(None, description="Seal value 2500")
|
|
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")
|
|
weight_factor: Optional[Decimal] = Field(None, description="Weight factor")
|
|
|
|
|
|
class InvoiceLogisticsBase(BaseModel):
|
|
"""Base fields for Logistics"""
|
|
|
|
carrier_id: Optional[str] = Field(None, max_length=10, description="Carrier ID")
|
|
transport_id: Optional[str] = Field(None, max_length=10, description="Transport ID")
|
|
transport_us_id: Optional[str] = Field(
|
|
None, max_length=10, description="US transport ID"
|
|
)
|
|
transport_type: TransportType = Field(
|
|
"none", max_length=15, description="Transport type"
|
|
)
|
|
transport_num: Optional[str] = Field(
|
|
None, max_length=20, description="Transport number"
|
|
)
|
|
transport_mode: Optional[str] = Field(
|
|
30, max_length=15, description="Transport mode"
|
|
)
|
|
driver_name: Optional[str] = Field(None, max_length=80, description="Driver name")
|
|
is_rail: Optional[bool] = Field(False, 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"
|
|
)
|
|
license_plate_complete: Optional[str] = Field(
|
|
None, max_length=40, description="Complete license plate"
|
|
)
|
|
trailer_num: Optional[str] = Field(
|
|
None, max_length=20, description="Trailer number"
|
|
)
|
|
seal_number: Optional[str] = Field(None, max_length=15, description="Seal number")
|
|
guide_number: Optional[str] = Field(None, max_length=20, description="Guide number")
|
|
bill_number: Optional[str] = Field(None, max_length=15, description="Bill number")
|
|
reference_number: Optional[str] = Field(
|
|
None, max_length=14, description="Reference number"
|
|
)
|
|
shipment_number: Optional[str] = Field(
|
|
None, max_length=19, description="Shipment number"
|
|
)
|
|
incoterm: Optional[str] = Field(None, max_length=5, description="Incoterm")
|
|
identifier_1: Optional[str] = Field(None, max_length=2, description="Identifier 1")
|
|
complement_1: Optional[str] = Field(None, max_length=30, description="Complement 1")
|
|
identifier_2: Optional[str] = Field(None, max_length=2, description="Identifier 2")
|
|
complement_2: Optional[str] = Field(None, max_length=30, description="Complement 2")
|
|
weight_type: WeightUnit = Field(
|
|
default="kgs", max_length=3, description="Weight type"
|
|
)
|
|
|
|
@field_validator("weight_type", mode="before")
|
|
@classmethod
|
|
def normalize_weight_type(cls, v):
|
|
if isinstance(v, str):
|
|
return v.lower()
|
|
return v
|
|
container_types: Optional[str] = Field(
|
|
None, max_length=500, description="Container types"
|
|
)
|
|
vehicle_data: Optional[str] = Field(
|
|
None, max_length=500, description="Vehicle data"
|
|
)
|
|
origin_location: Optional[str] = Field(
|
|
None, max_length=200, description="Origin location"
|
|
)
|
|
destination_location: Optional[str] = Field(
|
|
None, max_length=200, description="Destination location"
|
|
)
|
|
transport_itinerary: Optional[str] = Field(
|
|
None, max_length=1000, description="Transport itinerary"
|
|
)
|
|
destination_goods: Optional[str] = Field(
|
|
None, max_length=50, description="Destination of goods"
|
|
)
|
|
entry_exit_date: Optional[date] = Field(None, description="Entry/Exit date")
|
|
delivery_date: Optional[date] = Field(None, description="Delivery date")
|
|
delivered_status: Optional[bool] = Field(False, description="Delivered status")
|
|
received_by: Optional[str] = Field(None, max_length=50, description="Received by")
|
|
payment_date: Optional[date] = Field(None, description="Payment date")
|
|
payment_receipt_num: Optional[str] = Field(
|
|
None, max_length=20, description="Payment receipt number"
|
|
)
|
|
is_ctm_process: Optional[bool] = Field(False, description="Is CTM process")
|
|
# Continuation Tab Fields
|
|
equipment_reviewed: Optional[bool] = Field(False, description="Equipment reviewed")
|
|
is_subdivision: Optional[bool] = Field(False, description="Is subdivision")
|
|
acts_as_cd: Optional[bool] = Field(False, description="Acts as CD")
|
|
pedimento_arrived: Optional[bool] = Field(False, description="Pedimento arrived")
|
|
green_light_mx: Optional[bool] = Field(False, description="Green light Mexico")
|
|
green_light_us: Optional[bool] = Field(False, description="Green light USA")
|
|
red_light_mx: Optional[bool] = Field(False, description="Red light Mexico")
|
|
red_light_us: Optional[bool] = Field(False, description="Red light USA")
|
|
|
|
|
|
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"""
|
|
|
|
line_number: int = Field(..., description="Line number")
|
|
invoice_number: Optional[str] = Field(
|
|
None, max_length=15, description="Invoice number"
|
|
)
|
|
concept: Optional[str] = Field(None, max_length=100, description="Concept")
|
|
|
|
|
|
# --- 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[InvoiceLogisticsCreate] = None
|
|
details: Optional[List[InvoiceSalesDetailsCreate]] = None
|
|
collections: Optional[List[InvoiceCollectionsCreate]] = None
|
|
|
|
|
|
# --- Update Schemas ---
|
|
|
|
|
|
|
|
class InvoiceComplianceMxUpdate(InvoiceComplianceMxBase):
|
|
"""Schema for updating Compliance MX"""
|
|
|
|
is_pedimento_pending: Optional[bool] = None
|
|
|
|
|
|
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"""
|
|
|
|
line_number: Optional[int] = None
|
|
|
|
|
|
class InvoiceHeaderUpdate(InvoiceHeaderBase):
|
|
"""Schema for updating Invoice Header with nested relations"""
|
|
|
|
id: int
|
|
document_type: Optional[str] = None
|
|
invoice_date: Optional[date] = None
|
|
operation_type: Optional[OperationType] = None
|
|
|
|
compliance_mx: Optional[InvoiceComplianceMxUpdate] = None
|
|
financials: Optional[InvoiceFinancialsUpdate] = None
|
|
logistics: Optional[InvoiceLogisticsUpdate] = None
|
|
details: Optional[List[InvoiceSalesDetailsUpdate]] = None
|
|
collections: Optional[List[InvoiceCollectionsUpdate]] = None
|
|
|
|
|
|
# --- Response Schemas ---
|
|
|
|
|
|
class PedimentoBasicInfo(BaseModel):
|
|
"""Basic Pedimento information for Invoice response"""
|
|
|
|
pedimento_number: Optional[str] = None
|
|
pedimento_code: Optional[str] = None
|
|
customs_office: Optional[str] = None
|
|
license: Optional[str] = None
|
|
year: Optional[str] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvoiceComplianceMxResponse(InvoiceComplianceMxBase):
|
|
"""Schema for Compliance MX response"""
|
|
|
|
invoice_id: int
|
|
pedimento: Optional[PedimentoBasicInfo] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvoiceFinancialsResponse(InvoiceFinancialsBase):
|
|
"""Schema for Financials response"""
|
|
|
|
id: int
|
|
invoice_id: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvoiceLogisticsResponse(InvoiceLogisticsBase):
|
|
"""Schema for Logistics response"""
|
|
|
|
id: int
|
|
invoice_id: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvoiceSalesDetailsResponse(InvoiceSalesDetailsBase):
|
|
"""Schema for Sales Details response"""
|
|
|
|
id: int
|
|
invoice_id: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvoiceCollectionsResponse(InvoiceCollectionsBase):
|
|
"""Schema for Collections response"""
|
|
|
|
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: Optional[InvoiceLogisticsResponse] = None
|
|
details: Optional[List[InvoiceSalesDetailsResponse]] = []
|
|
collections: Optional[List[InvoiceCollectionsResponse]] = []
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class InvoiceHeaderListResponse(BaseModel):
|
|
items: List[InvoiceHeaderResponse]
|
|
total: int
|
|
page: int
|
|
|
|
# --- Consolidated Response Schemas ---
|
|
|
|
# Import necessary DTOs from other modules
|
|
from api.v1.modules.public.reference_data.invoice_types.dto import InvoiceTypeDTO
|
|
from api.v1.modules.a76.customs_brokers.dto import CustomsBrokerResponseDTO
|
|
from api.v1.modules.a76.clients_and_providers.dto import ClientProviderResponseDTO
|
|
from api.v1.modules.public.reference_data.currency_types.dto import CurrencyTypeDTO
|
|
from api.v1.modules.public.reference_data.transport_types.dto import TransportTypeDTO
|
|
from api.v1.modules.public.reference_data.customs_sections.dto import CustomsSectionDTO
|
|
from api.v1.modules.public.reference_data.incoterms.dto import IncotermDTO
|
|
from api.v1.modules.public.reference_data.transport_modes.dto import TransportModeDTO
|
|
from api.v1.modules.public.reference_data.code_pedimento_regimens.dto import CodePedimentoRegimenDTO
|
|
|
|
# TODO: Check if these paths are correct or need adjustment based on actual file locations
|
|
# Using Any for now for potentially complex or unverified paths to avoid immediate ImportErrors
|
|
# Detailed verification is needed for:
|
|
# - TransporterDTO
|
|
# - VehicleDTO
|
|
# - DriverDTO
|
|
# - TrailerDTO
|
|
# - SealResponseDTO
|
|
# - PedimentoDTO
|
|
|
|
class InvoiceCatalogsResponse(BaseModel):
|
|
"""Consolidated response for all catalogs needed in Invoice Create/Edit views"""
|
|
invoice_types: List[InvoiceTypeDTO] = []
|
|
customs_brokers: List[CustomsBrokerResponseDTO] = []
|
|
clients: List[ClientProviderResponseDTO] = []
|
|
providers: List[ClientProviderResponseDTO] = []
|
|
currency_types: List[CurrencyTypeDTO] = []
|
|
transport_types: List[TransportTypeDTO] = []
|
|
transporters: List[dict] = [] # Placeholder, refine with actual DTO
|
|
vehicles: List[dict] = [] # Placeholder, refine with actual DTO
|
|
drivers: List[dict] = [] # Placeholder, refine with actual DTO
|
|
trailers: List[dict] = [] # Placeholder, refine with actual DTO
|
|
customs_sections: List[CustomsSectionDTO] = []
|
|
code_pedimento_regimens: List[CodePedimentoRegimenDTO] = []
|
|
seals: List[dict] = [] # Placeholder, refine with actual DTO
|
|
incoterms: List[IncotermDTO] = []
|
|
pedimentos: List[dict] = [] # Placeholder, refine with actual DTO
|
|
transport_modes: List[TransportModeDTO] = []
|
|
default_settings: Optional[dict] = None
|
|
|
|
class InvoiceCreationResponse(InvoiceCatalogsResponse):
|
|
"""Response for Invoice Creation View"""
|
|
is_create: bool = True
|
|
invoice: Optional[dict] = None # Should be null for creation
|
|
invoice_id: Optional[int] = None
|
|
filters: Optional[dict] = None # Pre-filled filters if any
|
|
|
|
class InvoiceEditionResponse(InvoiceCatalogsResponse):
|
|
"""Response for Invoice Edition View"""
|
|
is_create: bool = False
|
|
invoice: InvoiceHeaderResponse
|
|
invoice_id: int
|
|
filters: Optional[dict] = None
|
|
|