import { overseasHttp } from '@/shared/api/overseasHttp' import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http' import { normalizeOverseasPage, type OverseasPagePayload } from './lastMileOrders' export interface DispatchQuery { page: number size: number dispatchNo?: string vehiclePlate?: string status?: string fbaAppointmentNo?: string } export interface DispatchPalletCandidateDto { planId?: string | null planPalletId?: string | null warehousePalletId?: string | null orderId: string customerId?: string | null customerName?: string | null planNo?: string | null orderType?: string | null volumeWeightKg?: number | null grossWeightKg?: number | null containerNo?: string | null appointmentAt?: string | null expectedLoadingAt?: string | null overseasWarehouseId?: string | null overseasWarehouseCode?: string | null overseasWarehouseName?: string | null orderNo?: string | null orderRefs?: string | null inboundCode?: string | null palletNo?: string | null destinationWarehouseId?: string | null destinationWarehouseCode?: string | null destinationWarehouseName?: string | null fbaWarehouseCode?: string | null packageCount?: number | null volumeCbm?: number | null sourceStage?: 'PLAN' | 'RECEIVED' | 'RELABEL' | null cartonMarks?: string | null relabelCartonMarks?: string | null destinationType?: 'FBA' | 'PRIVATE' | null deliveryAddress?: string | null postalCode?: string | null contactName?: string | null contactPhone?: string | null } export interface DispatchCandidateQuery { planIds?: string orderNo?: string fbaWarehouseCode?: string sourceStage?: 'PLAN' | 'RECEIVED' | 'RELABEL' draftToken?: string } export interface DispatchDraftContainerDto { id: string; capacity: number; palletIds: string[] } export interface DispatchDraftDto { draftToken: string; containers?: DispatchDraftContainerDto[] } export interface PreArrangeDispatchPayload { planPalletIds: string[] fbaAppointmentNo?: string fbaAppointmentStatus?: string vehicleAppointmentStatus?: string draftToken?: string relabelNo?: string } export interface DispatchSummaryDto { id: string dispatchNo: string vehiclePlate?: string | null driverName?: string | null driverPhone?: string | null carrierName?: string | null orderNos?: string | null route?: string | null overseasWarehouseId?: string | null overseasWarehouseName?: string | null departAt?: string | null fbaAppointmentNo?: string | null fbaAppointmentStatus?: string | null vehicleAppointmentStatus?: string | null estimatedArrivalAt?: string | null status?: string | null itemCount?: number | null palletCount?: number | null packageCount?: number | null pickedPackageCount?: number | null shippedPackageCount?: number | null remainingPackageCount?: number | null partialCompletionReason?: string | null createdAt?: string | null items?: DispatchItemDto[] bolLines?: DispatchBolLineDto[] } export interface DispatchBolLineDto { containerNo?: string | null palletNo?: string | null fbaWarehouseCode?: string | null destinationWarehouseName?: string | null warehouseNo?: string | null fbaShipmentId?: string | null poReferenceNo?: string | null packageCount: number } export interface UpdateDispatchPayload { vehiclePlate?: string | null driverName?: string | null driverPhone?: string | null carrierName?: string | null departAt?: string | null fbaAppointmentNo?: string | null fbaAppointmentStatus?: string | null vehicleAppointmentStatus?: string | null estimatedArrivalAt?: string | null } export interface DispatchItemDto { id: string planPalletId: string warehousePalletId?: string | null palletNo?: string | null overseasWarehouseId?: string | null overseasWarehouseName?: string | null orderNo?: string | null orderRefs?: string | null inboundCode?: string | null destinationWarehouseCode?: string | null destinationWarehouseName?: string | null fbaWarehouseCode?: string | null packageCount?: number | null volumeCbm?: number | null sourceStage?: string | null } export async function listDispatches(query: DispatchQuery) { const response = await overseasHttp.get>, ApiEnvelope>>( '/platform/v1/last-leg/dispatches', { params: query }, ) return normalizeOverseasPage(unwrapApiResponse(response)) } export async function getDispatch(dispatchNo: string) { const response = await overseasHttp.get, ApiEnvelope>( `/platform/v1/last-leg/dispatches/${encodeURIComponent(dispatchNo)}`, ) return unwrapApiResponse(response) } export async function getDispatchBolPdf(dispatchNo: string) { return overseasHttp.get( `/platform/v1/last-leg/dispatches/${encodeURIComponent(dispatchNo)}/prints/bol`, { responseType: 'blob' }, ) } export async function updateDispatch(dispatchNo: string, payload: UpdateDispatchPayload) { const response = await overseasHttp.put, ApiEnvelope>( `/platform/v1/last-leg/dispatches/${encodeURIComponent(dispatchNo)}`, payload, ) return unwrapApiResponse(response) } export async function cancelDispatch(dispatchNo: string) { const response = await overseasHttp.delete, ApiEnvelope>( `/platform/v1/last-leg/dispatches/${encodeURIComponent(dispatchNo)}`, ) return unwrapApiResponse(response) } export async function removeDispatchItem(dispatchNo: string, itemId: string) { const response = await overseasHttp.delete, ApiEnvelope>( `/platform/v1/last-leg/dispatches/${encodeURIComponent(dispatchNo)}/items/${encodeURIComponent(itemId)}`, ) return unwrapApiResponse(response) } export async function listDispatchCandidates(query: DispatchCandidateQuery) { const response = await overseasHttp.get, ApiEnvelope>( '/platform/v1/last-leg/dispatches/candidates', { params: query }, ) return unwrapApiResponse(response) } export async function preArrangeDispatch(payload: PreArrangeDispatchPayload) { const response = await overseasHttp.post, ApiEnvelope>( '/platform/v1/last-leg/dispatches/pre-arrange', payload, ) return unwrapApiResponse(response) } export async function lockDispatchDraftPallet(planPalletId: string, draftToken: string, draftContainerId?: string) { const response = await overseasHttp.post, ApiEnvelope>( '/platform/v1/last-leg/dispatches/draft-locks/lock', { planPalletId, draftToken, ...(draftContainerId ? { draftContainerId } : {}) }, ) return unwrapApiResponse(response) } export async function listDispatchDrafts() { const response = await overseasHttp.get, ApiEnvelope>('/platform/v1/last-leg/dispatches/drafts') return unwrapApiResponse(response) } export async function createDispatchDraftContainer(draftToken: string, capacity: number) { const response = await overseasHttp.post, ApiEnvelope>('/platform/v1/last-leg/dispatches/drafts/containers', { draftToken, capacity }) return unwrapApiResponse(response) } export async function deleteDispatchDraftContainer(draftToken: string, containerId: string) { const response = await overseasHttp.delete, ApiEnvelope>(`/platform/v1/last-leg/dispatches/drafts/${encodeURIComponent(draftToken)}/containers/${encodeURIComponent(containerId)}`) return unwrapApiResponse(response) } export async function unlockDispatchDraftPallet(planPalletId: string, draftToken: string) { const response = await overseasHttp.post, ApiEnvelope>( '/platform/v1/last-leg/dispatches/draft-locks/unlock', { planPalletId, draftToken }, ) return unwrapApiResponse(response) } export async function releaseDispatchDraft(draftToken: string) { const response = await overseasHttp.post, ApiEnvelope>( '/platform/v1/last-leg/dispatches/draft-locks/release', { draftToken }, ) return unwrapApiResponse(response) } export interface TransferDeliveryItem { deliveryNo: string; deliveryStatus: string; destinationWarehouseId?: string | null; destinationWarehouseCode?: string | null; destinationWarehouseName?: string | null; palletCount: number; packageCount: number } export interface TransferDeliveryResult { dispatchNo: string; outboundNo: string; outboundStatus: string; palletCount: number; packageCount: number; deliveries: TransferDeliveryItem[]; replayed: boolean } export interface TransferDeliveryPayload { idempotencyKey: string plannedDeliveryAt: string deliveryMethod: string waybillNo?: string carrierName?: string pickupMethod: string loadingType: string vehicleType?: string vehicleSize?: string driverName?: string driverPhone?: string vehiclePlate?: string appointmentAccount?: string sellerName?: string remark?: string fees: Array<{ feeType: string; feeName: string; direction: 'RECEIVABLE' | 'PAYABLE'; currency: 'CNY' | 'USD'; amount: number supplierId?: string; supplierName?: string; supplierCategory?: string; settlementMode?: 'ON_ACCOUNT' | 'DIRECT_PAID' paidAt?: string; paymentMethod?: 'ONLINE' | 'BANK_TRANSFER' | 'CASH' | 'OTHER'; paymentReferenceNo?: string paymentVoucherFileIds?: string[]; chargeableQuantity?: number; quantityUnit?: string; unitPrice?: number periodStart?: string; periodEnd?: string; remark?: string }> } export async function transferDispatchToDelivery(dispatchNo: string, payload: TransferDeliveryPayload) { const response = await overseasHttp.post, ApiEnvelope>( `/platform/v1/last-leg/dispatches/${encodeURIComponent(dispatchNo)}/transfer-delivery`, payload, ) return unwrapApiResponse(response) }