bmc_hub/app/modules/shipmondo/models/schemas.py
2026-08-25 01:09:45 +02:00

107 lines
3.5 KiB
Python

from datetime import datetime
from typing import Any, Dict, List, Literal, Optional
from pydantic import BaseModel, Field, field_validator
ShipmentStatus = Literal[
"draft",
"submitted",
"booked",
"in_transit",
"delivered",
"cancelled",
"failed",
]
class ShipmondoAddress(BaseModel):
recipient_name: str = Field(min_length=2, max_length=150)
company_name: Optional[str] = Field(default=None, max_length=150)
address_line1: str = Field(min_length=2, max_length=200)
address_line2: Optional[str] = Field(default=None, max_length=200)
postal_code: str = Field(min_length=2, max_length=20)
city: str = Field(min_length=2, max_length=120)
country_code: str = Field(min_length=2, max_length=2)
phone: Optional[str] = Field(default=None, max_length=50)
email: Optional[str] = Field(default=None, max_length=150)
@field_validator("country_code")
@classmethod
def normalize_country_code(cls, value: str) -> str:
return value.strip().upper()
class ShipmondoParcelInput(BaseModel):
weight_kg: float = Field(gt=0, le=2000)
length_cm: Optional[float] = Field(default=None, gt=0, le=400)
width_cm: Optional[float] = Field(default=None, gt=0, le=400)
height_cm: Optional[float] = Field(default=None, gt=0, le=400)
description: str = Field(min_length=1, max_length=255)
class ShipmondoBookingCreate(BaseModel):
case_id: int = Field(gt=0)
customer_id: Optional[int] = Field(default=None, gt=0)
contact_id: Optional[int] = Field(default=None, gt=0)
product_code: str = Field(min_length=1, max_length=80)
product_name: Optional[str] = Field(default=None, max_length=180)
carrier_code: Optional[str] = Field(default=None, max_length=80)
carrier_name: Optional[str] = Field(default=None, max_length=120)
service_codes: List[str] = Field(default_factory=list, max_length=30)
own_agreement: bool = False
automatic_select_service_point: bool = False
address: ShipmondoAddress
parcels: List[ShipmondoParcelInput] = Field(min_length=1, max_length=30)
@field_validator("service_codes")
@classmethod
def normalize_service_codes(cls, values: List[str]) -> List[str]:
return list(dict.fromkeys(value.strip().upper() for value in values if value.strip()))
class ShipmondoBookingResponse(BaseModel):
id: int
booking_ref: str
case_id: int
customer_id: Optional[int] = None
contact_id: Optional[int] = None
product_code: str
product_name: Optional[str] = None
carrier_code: Optional[str] = None
carrier_name: Optional[str] = None
service_codes: List[str] = Field(default_factory=list)
shipment_status: ShipmentStatus
recipient_name: str
city: str
country_code: str
tracking_number: Optional[str] = None
tracking_url: Optional[str] = None
label_url: Optional[str] = None
total_amount: Optional[float] = None
currency: Optional[str] = None
dry_run: bool
submitted_at: Optional[datetime] = None
created_at: datetime
updated_at: datetime
parcels: List[ShipmondoParcelInput] = Field(default_factory=list)
class ShipmondoBookingListResponse(BaseModel):
items: List[ShipmondoBookingResponse]
class ShipmondoBookingSubmitResponse(BaseModel):
booking_ref: str
status: ShipmentStatus
dry_run: bool
tracking_number: Optional[str] = None
tracking_url: Optional[str] = None
label_url: Optional[str] = None
total_amount: Optional[float] = None
currency: Optional[str] = None
class ShipmondoProductListResponse(BaseModel):
items: List[Dict[str, Any]]