from pydantic import BaseModel, Field, field_validator class TripSearchDTO(BaseModel): channel: str = "web_client" size: int = 300 only_online_trip: bool = True ticket_count: int seat_type_id: list = Field(default_factory=list) from_time: int to_time: int route_ids: list[int] origin_office_id: list = Field(default_factory=list) dest_office_id: list = Field(default_factory=list) postion: list = Field(default_factory=list) floor: list = Field(default_factory=list) sort_by: list[str] = ["price", "departure_time"] class TripOptionDTO(BaseModel): trip_id: int route: str @field_validator("trip_id", mode="before") def convert_float_to_int(cls, v): return int(v) if v is not None else None class Route(BaseModel): name: str | None = None class TripDTO(BaseModel): id: int | None = None route_id: int | None = None way_id: int | None = None route: Route | None = None raw_departure_date: str | None = None raw_departure_time: str | None = None seat_type_name: str | None = None price: int | None = None @field_validator("id", "price", "route_id", "way_id", mode="before") @classmethod def convert_float_to_int(cls, v): return int(v) if v is not None else None class CoordinateDTO(BaseModel): lat: float lon: float class PickupPointDTO(BaseModel): OfficeId: int | None = None Name: str | None = None Address: str | None = None Phone: str | None = None PickUp: int | None = None TimeOffice: int | None = None PointKind: int | None = None Note: str | None = None PointKindName: str | None = None class RouteDTO(BaseModel): name: str route_id: int origin_code: str origin_name: str origin_hub_id: int origin_hub_name: str origin_hub_office_id: int origin_hub_office_name: str origin_hub_coords: CoordinateDTO dest_code: str dest_name: str dest_hub_id: int dest_hub_name: str dest_hub_office_id: int dest_hub_office_name: str dest_hub_coords: CoordinateDTO shuttle_enable: bool allow_desktop: bool allow_mobile_app: bool allow_web_client: bool allow_web_admin: bool class ShuttleZoneResultDTO(BaseModel): is_in_zone: bool is_allow_user_to_toggle: bool distance_to_user: float zone: str | None = None nearest_pickup_point: str | None = None class ShuttleOptionDTO(BaseModel): is_enable_shuttle: bool route: RouteDTO origin_result: ShuttleZoneResultDTO dest_result: ShuttleZoneResultDTO class TripItemDTO(BaseModel): id: int departure_time: int raw_departure_time: str raw_departure_date: str arrival_time: int duration: int seat_type_id: int seat_type_name: str price: int empty_seat_quantity: int route_id: int distance: int route: RouteDTO way_id: int allow_online_booking: bool online_booking_before: int max_seats_per_booking: int point_details: str | None = None num_price: int from_bus_station_address: str to_bus_station_address: str top_first_floor_quantity: int middle_first_floor_quantity: int last_first_floor_quantity: int top_second_floor_quantity: int middle_second_floor_quantity: int last_second_floor_quantity: int way_name: str way_note: str pickup_points: list[PickupPointDTO] shuttle_option: ShuttleOptionDTO