Source code for ab.api.models.shipments

"""Shipment models for ACPortal API."""

from __future__ import annotations

from typing import List, Optional

from pydantic import Field

from ab.api.models.base import RequestModel, ResponseModel
from ab.api.models.mixins import IdentifiedModel


[docs] class ShipmentParams(RequestModel): """Query parameters for GET /shipment.""" franchisee_id: Optional[str] = Field(None, alias="franchiseeId", description="Franchisee UUID") provider_id: Optional[str] = Field(None, alias="providerId", description="Provider UUID") pro_number: Optional[str] = Field(None, alias="proNumber", description="PRO/tracking number")
[docs] class RateQuotesParams(RequestModel): """Query parameters for GET rate quotes.""" ship_out_date: Optional[str] = Field(None, alias="ShipOutDate", description="Requested ship-out date (ISO 8601)") rates_sources: Optional[str] = Field( None, alias="RatesSources", description="Comma-separated rate source identifiers", ) settings_key: Optional[str] = Field(None, alias="SettingsKey", description="Settings configuration key")
[docs] class ShipmentDocumentParams(RequestModel): """Query parameters for GET shipment document.""" franchisee_id: Optional[str] = Field(None, alias="franchiseeId", description="Franchisee UUID filter")
# ---- Response models --------------------------------------------------
[docs] class RateQuote(ResponseModel): """Rate quote — GET /job/{jobDisplayId}/shipment/ratequotes.""" carrier_name: Optional[str] = Field(None, alias="carrierName", description="Carrier company name") service_type: Optional[str] = Field(None, alias="serviceType", description="Service level") total_charge: Optional[float] = Field(None, alias="totalCharge", description="Total quoted price") transit_days: Optional[int] = Field(None, alias="transitDays", description="Estimated transit time") accessorial_charges: Optional[List[dict]] = Field( None, alias="accessorialCharges", description="Itemized extras", ) provider_option_index: Optional[int] = Field( None, alias="providerOptionIndex", description="Index for booking selection", ) errors: Optional[list] = Field(None, description="Rate quote errors") rates: Optional[list] = Field(None, description="Available rates") rates_key: Optional[str] = Field(None, alias="ratesKey", description="Rates cache key") request_snapshot: Optional[dict] = Field(None, alias="requestSnapshot", description="Original request snapshot") carrier_code: Optional[str] = Field(None, alias="carrierCode", description="Carrier code identifier") used_carrier_account_info: Optional[dict] = Field( None, alias="usedCarrierAccountInfo", description="Carrier account info used for quoting", ) service_days: Optional[int] = Field(None, alias="serviceDays", description="Service delivery days") price: Optional[float] = Field(None, alias="price", description="Quoted price") accessorials: Optional[list] = Field(None, alias="accessorials", description="Accessorial services")
[docs] class ShipmentOriginDestination(ResponseModel): """Origin/destination — GET /job/{jobDisplayId}/shipment/origindestination.""" origin: Optional[dict] = Field(None, description="Origin address details") destination: Optional[dict] = Field(None, description="Destination address details")
[docs] class Accessorial(ResponseModel, IdentifiedModel): """Accessorial — GET /job/{jobDisplayId}/shipment/accessorials.""" name: Optional[str] = Field(None, description="Accessorial name") description: Optional[str] = Field(None, description="Description") price: Optional[float] = Field(None, description="Additional cost") is_selected: Optional[bool] = Field(None, alias="isSelected", description="Whether currently applied")
[docs] class ShipmentExportData(ResponseModel): """Export data — GET /job/{jobDisplayId}/shipment/exportdata.""" export_data: Optional[dict] = Field(None, alias="exportData", description="Shipment export payload") values_specified: Optional[dict] = Field(None, alias="valuesSpecified", description="Specified value flags") sold_to: Optional[dict] = Field(None, alias="soldTo", description="Sold-to contact and address") commodities: Optional[list] = Field(None, description="Commodity line items") packing_info: Optional[list] = Field(None, alias="packingInfo", description="Packing information entries") customs_value: Optional[float] = Field(None, alias="customsValue", description="Customs declared value") invoice_number: Optional[str] = Field(None, alias="invoiceNumber", description="Commercial invoice number") purchase_order_number: Optional[str] = Field( None, alias="purchaseOrderNumber", description="Purchase order number", ) terms_of_sale: Optional[str] = Field(None, alias="termsOfSale", description="Incoterms / terms of sale") exporter_tax_id: Optional[str] = Field(None, alias="exporterTaxId", description="Exporter tax identifier") consignee_tax_id: Optional[str] = Field(None, alias="consigneeTaxId", description="Consignee tax identifier") total_costs: Optional[dict] = Field(None, alias="totalCosts", description="Aggregate cost breakdown") usps_specific: Optional[dict] = Field(None, alias="uspsSpecific", description="USPS-specific export fields") fed_ex_specific: Optional[dict] = Field(None, alias="fedExSpecific", description="FedEx-specific export fields") ups_specific: Optional[dict] = Field(None, alias="upsSpecific", description="UPS-specific export fields")
[docs] class RatesState(ResponseModel): """Rates state — GET /job/{jobDisplayId}/shipment/ratesstate.""" state: Optional[str] = Field(None, description="Current rates state") rates: Optional[List[dict]] = Field(None, description="Available rates") from_zip: Optional[str] = Field(None, alias="fromZip", description="Origin ZIP code") to_zip: Optional[str] = Field(None, alias="toZip", description="Destination ZIP code") item_weight: Optional[float] = Field(None, alias="itemWeight", description="Total item weight") services: Optional[list] = Field(None, description="Available services") parcel_items: Optional[list] = Field(None, alias="parcelItems", description="Parcel items") parcel_services: Optional[list] = Field(None, alias="parcelServices", description="Parcel services") ship_out_date: Optional[str] = Field(None, alias="shipOutDate", description="Ship out date")
[docs] class ShipmentWeight(ResponseModel): """Weight details for a shipment.""" pounds: Optional[float] = Field(None, description="Weight in pounds") original_weight: Optional[float] = Field(None, alias="originalWeight", description="Original weight value") original_weight_measure_unit: Optional[str] = Field( None, alias="originalWeightMeasureUnit", description="Original weight unit" )
[docs] class ShipmentInfo(ResponseModel): """Shipment info — GET /shipment.""" shipment_id: Optional[str] = Field(None, alias="shipmentId", description="Shipment identifier") status: Optional[str] = Field(None, description="Current status") carrier: Optional[str] = Field(None, description="Carrier name") pro_number: Optional[str] = Field(None, alias="proNumber", description="PRO tracking number") used_api: Optional[int] = Field(None, alias="usedAPI", description="API used for shipment") history_provider_name: Optional[str] = Field( None, alias="historyProviderName", description="Tracking history provider" ) history_statuses: Optional[list] = Field(None, alias="historyStatuses", description="Tracking status history") weight: Optional[ShipmentWeight] = Field(None, description="Shipment weight details") job_weight: Optional[float] = Field(None, alias="jobWeight", description="Job total weight") successfully: Optional[bool] = Field(None, description="Whether shipment was successful") error_message: Optional[str] = Field(None, alias="errorMessage", description="Error message if failed") multiple_shipments: Optional[bool] = Field(None, alias="multipleShipments", description="Multiple shipments flag") packages: Optional[list] = Field(None, description="Package details") estimated_delivery: Optional[str] = Field(None, alias="estimatedDelivery", description="Estimated delivery date")
[docs] class RadioButtonOption(ResponseModel): """Radio button option within an accessorial option.""" description: Optional[str] = Field(None, description="Option description") code: Optional[str] = Field(None, description="Option code")
[docs] class AccessorialOption(ResponseModel): """Option within a global accessorial.""" key: Optional[str] = Field(None, description="Option key") type: Optional[int] = Field(None, description="Option type") radio_button_options: Optional[List[RadioButtonOption]] = Field( None, alias="radioButtonOptions", description="Radio button choices" )
[docs] class GlobalAccessorial(ResponseModel): """Global accessorial — GET /shipment/accessorials.""" id: Optional[str] = Field(None, description="Accessorial ID") name: Optional[str] = Field(None, description="Name") category: Optional[str] = Field(None, description="Category grouping") description: Optional[str] = Field(None, description="Accessorial description") price: Optional[str] = Field(None, description="Price or price range") options: Optional[List[AccessorialOption]] = Field(None, description="Accessorial options") unique_id: Optional[str] = Field(None, alias="uniqueId", description="Unique identifier") source_apis: Optional[List[int]] = Field(None, alias="sourceAPIs", description="Source API identifiers")
# ---- Request models ---------------------------------------------------
[docs] class ShipmentBookRequest(RequestModel): """Body for POST /job/{jobDisplayId}/shipment/book.""" provider_option_index: Optional[int] = Field( None, alias="providerOptionIndex", description="Selected rate quote index", ) ship_date: Optional[str] = Field(None, alias="shipDate", description="Requested ship date")
[docs] class AccessorialAddRequest(RequestModel): """Body for POST /job/{jobDisplayId}/shipment/accessorial.""" add_on_id: Optional[str] = Field(None, alias="addOnId", description="Accessorial ID to add")
[docs] class ShipmentRateQuoteRequest(RequestModel): """Body for POST /job/{jobDisplayId}/shipment/ratequotes.""" ship_out_date: Optional[str] = Field(None, alias="ShipOutDate", description="Requested ship-out date (ISO 8601)") rates_sources: Optional[str] = Field( None, alias="RatesSources", description="Comma-separated rate source identifiers", ) settings_key: Optional[str] = Field(None, alias="SettingsKey", description="Settings configuration key")
[docs] class ShipmentExportRequest(RequestModel): """Body for POST /job/{jobDisplayId}/shipment/exportdata.""" export_data: Optional[dict] = Field(None, alias="exportData", description="Shipment export payload")