export type AddressInput = { street: string; city: string; state: string; zip: string; place_id: string; formatted_address: string; selected_from_suggestions: boolean; /** MotherShip 联想候选项 ID(用户确认后必填) */ mothership_option_id?: string; /** MotherShip 下拉展示文案,RPA 精确点选 */ mothership_display_label?: string; /** 用户已从 MotherShip 多候选中确认 */ selected_from_mothership?: boolean; }; export type WeightInput = { value: number; unit: import("@/modules/quote/unit-converter").ApiWeightUnit; }; export type DimensionsInput = { length: number; width: number; height: number; unit: import("@/modules/quote/unit-converter").ApiDimUnit; }; export type QuoteRequestBody = { request_id: string; customer_id: string; pickup_address: AddressInput; delivery_address: AddressInput; weight: WeightInput; dimensions: DimensionsInput; pallet_count: number; cargo_type: string; service_level?: "standard" | "guaranteed"; rate_option?: "lowest" | "fastest"; display_unit?: "imperial" | "metric"; /** 候选 RPA 会话 ID(可选,10 分钟内有效) */ quote_session_id?: string; /** MotherShip 登录态:提货附加服务 id */ pickup_accessorials?: string[]; /** MotherShip 登录态:派送附加服务 id */ delivery_accessorials?: string[]; /** MotherShip 登录态:可提货日期 YYYY-MM-DD */ ready_date?: string; /** MotherShip 登录态:可提货时刻,如 3:00 PM */ ready_time?: string; /** MotherShip 登录态:多行货物 */ cargo_lines?: Array<{ cargo_type: string; quantity: number; weight_lb: number; length_in: number; width_in: number; height_in: number; }>; mothership_details?: { pickup: { company_name?: string; suite?: string; contact_first?: string; contact_last?: string; contact_email?: string; contact_phone?: string; reference?: string; notes?: string; opens_at?: string; closes_at?: string; }; delivery: { company_name?: string; suite?: string; contact_first?: string; contact_last?: string; contact_email?: string; contact_phone?: string; reference?: string; notes?: string; opens_at?: string; closes_at?: string; }; request_delivery_appointment?: boolean; fba_number?: string; fba_po_number?: string; cargo?: Array<{ piece_count_type?: string; piece_count_qty?: number; description?: string; nmfc?: string; hazmat?: boolean; alcohol?: boolean; tobacco?: boolean; }>; }; }; export type NormalizedCargo = { requestId: string; customerId: string; pickupAddress: AddressInput; deliveryAddress: AddressInput; weightLb: number; dimLIn: number; dimWIn: number; dimHIn: number; palletCount: number; cargoType: string; serviceLevel: "standard" | "guaranteed"; rateOption: "lowest" | "fastest"; cargoHash: string; pickupSerialized: string; deliverySerialized: string; quoteSessionId?: string; /** MotherShip 登录态附加服务 / 可提货时间(可选) */ pickupAccessorials?: string[]; deliveryAccessorials?: string[]; readyDate?: string; readyTime?: string; /** MotherShip 登录态多行货物 */ cargoLines?: Array<{ cargoType: string; quantity: number; weightLb: number; lengthIn: number; widthIn: number; heightIn: number; }>; mothershipDetails?: QuoteRequestBody["mothership_details"]; }; export type QuoteSubmitResult = { quoteId: string; status: "processing" | "done"; cached?: boolean; }; export type L2CachePayload = { quotes: Array<{ service_level: string; rate_option: string; carrier: string; transit_days: string; transit_description: string; raw_freight: number; surcharges: number; raw_total: number; }>; }; export class ValidationError extends Error { readonly code = "VALIDATION_FAILED"; constructor(message: string) { super(message); this.name = "ValidationError"; } } /** SQL 注入等安全校验失败(task-105 / TC-504) */ export class SecurityValidationError extends ValidationError { readonly isSecurity = true; constructor(message: string) { super(message); this.name = "SecurityValidationError"; } } export class QuoteIdConflictError extends Error { readonly code = "INTERNAL_ERROR"; constructor(message: string) { super(message); this.name = "QuoteIdConflictError"; } } export class RpaDataInvalidError extends Error { readonly code = "RPA_DATA_INVALID"; constructor(message: string) { super(message); this.name = "RpaDataInvalidError"; } }