Files
admin-web/src/modules/overseas-warehouse/api/lastMileOrders.ts
T

293 lines
8.9 KiB
TypeScript
Raw Normal View History

2026-08-20 09:10:36 +08:00
import { overseasHttp } from '@/shared/api/overseasHttp'
2026-08-31 14:42:28 +08:00
import { ApiResponseError, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
2026-08-27 16:34:32 +08:00
import type { InboundPlanDetailDto } from './inboundPlans'
2026-08-20 09:10:36 +08:00
export interface OverseasPageResult<T> {
records: T[]
page: number
size: number
total: number
pages: number
}
export type OverseasPagePayload<T> = Omit<OverseasPageResult<T>, 'page' | 'size' | 'total' | 'pages'> & {
page: number | string
size: number | string
total: number | string
pages: number | string
}
export function normalizeOverseasPage<T>(value: OverseasPagePayload<T>): OverseasPageResult<T> {
return { ...value, page: Number(value.page), size: Number(value.size), total: Number(value.total), pages: Number(value.pages) }
}
2026-08-20 09:10:36 +08:00
export interface LastMileOrderQuery {
page: number
size: number
orderNo?: string
2026-08-21 17:20:40 +08:00
orderType?: string
2026-08-20 09:10:36 +08:00
inboundCode?: string
containerNo?: string
2026-08-21 17:20:40 +08:00
currentStatus?: string
2026-08-20 09:10:36 +08:00
status?: string
2026-08-21 17:20:40 +08:00
warehouse?: string
2026-08-21 11:20:09 +08:00
sourceOrderNo?: string
transferWarehouseCode?: string
abnormal?: boolean
detained?: boolean
createdFrom?: string
createdTo?: string
2026-08-20 09:10:36 +08:00
}
export interface LastMileOrderSummaryDto {
id: string
2026-08-21 11:20:09 +08:00
customerId: string
2026-08-27 16:34:32 +08:00
sourceContainerBookingId?: string | null
2026-08-20 09:10:36 +08:00
orderNo: string
orderType?: string | null
2026-08-22 12:24:15 +08:00
orderTypeName?: string | null
2026-08-20 09:10:36 +08:00
inboundCode?: string | null
sourceOrderNo?: string | null
2026-08-21 11:20:09 +08:00
sourceInboundId?: string | null
2026-08-20 09:10:36 +08:00
customerName?: string | null
overseasWarehouseName?: string | null
transferWarehouseName?: string | null
2026-08-21 11:20:09 +08:00
transferWarehouseId?: string | null
transferWarehouseCode?: string | null
2026-08-20 09:10:36 +08:00
fbaWarehouseCode?: string | null
containerNo?: string | null
containerStatus?: string | null
abnormal?: boolean | null
detained?: boolean | null
palletCount?: number | null
packageCount?: number | null
volumeCbm?: number | null
productQuantity?: number | null
volumeWeightKg?: number | null
estimatedArrivalAt?: string | null
actualArrivalAt?: string | null
estimatedWarehouseAt?: string | null
inboundOrderNo?: string | null
2026-08-21 11:20:09 +08:00
/** Legacy read-only association retained for compatibility; absent from current service DTO. */
2026-08-20 09:10:36 +08:00
deliveryOrderNo?: string | null
2026-08-21 11:20:09 +08:00
outboundOrderNo?: string | null
2026-08-20 09:10:36 +08:00
relabelOrderNo?: string | null
relabelStatus?: string | null
palletMergeFlag?: string | null
/** Optional grouping facts returned by newer last-leg services. */
palletMergeBatchId?: string | null
2026-08-31 14:42:28 +08:00
palletMergeInboundNos?: string[] | null
2026-08-20 09:10:36 +08:00
currentStatus?: string | null
privateRemark?: string | null
customerRemark?: string | null
warehouseRemark?: string | null
2026-08-22 12:24:15 +08:00
createdAt?: string | null
2026-08-20 09:10:36 +08:00
}
export interface LastMileOrderDto extends LastMileOrderSummaryDto {
customerId: string
sourceOrderNo?: string | null
subOrderStatus?: string | null
updatedAt?: string | null
}
export interface LastMileCargoDto {
id: string
skuCode?: string | null
productNameZh?: string | null
productNameEn?: string | null
packageCount?: number | null
productQuantity?: number | null
palletCount?: number | null
grossWeightKg?: number | null
dimensionalWeightKg?: number | null
volumeCbm?: number | null
destinationWarehouseName?: string | null
fbaTrackingNo?: string | null
shipmentNo?: string | null
}
export interface LastMileStatusHistoryDto {
id: string
fromStatus?: string | null
toStatus?: string | null
remark?: string | null
createdAt?: string | null
}
2026-08-26 11:10:22 +08:00
export interface LastMileFeeDto {
id: string
customerId: string
orderId: string
feeItem: string
currency: string
amount: number
status: string
supplierDescription?: string | null
createdBy: string
createdAt: string
updatedAt: string
}
export interface LastMileOperationDto {
id: string
operationNode: string
operatorName: string
result: string
createdAt: string
}
export interface CreateLastMileFeePayload {
feeItem: string
currency: string
amount: number
status: string
supplierDescription?: string
}
2026-08-21 11:20:09 +08:00
export interface TransferDestinationPayload {
orderIds: string[]
warehouseId: string
warehouseCode: string
warehouseName: string
remark?: string
}
2026-08-21 17:20:40 +08:00
export interface ConvertInboundPlanPayload {
orderId: string
customerId: string
2026-08-21 17:20:40 +08:00
}
2026-08-28 13:54:44 +08:00
export interface ContainerPlanProgressQuery {
2026-08-27 17:16:38 +08:00
page: number
size: number
containerNo?: string
createdFrom?: string
createdTo?: string
2026-08-28 14:33:57 +08:00
}
2026-08-28 13:54:44 +08:00
export interface ContainerPlanProgressSummaryDto {
2026-08-27 17:16:38 +08:00
sourceContainerBookingId: string
containerNo: string | null
2026-08-28 13:54:44 +08:00
totalOrderCount: number
2026-08-27 17:16:38 +08:00
inboundCodeCount: number
2026-08-28 13:54:44 +08:00
missingInboundCodeCount: number
planCount: number
plannedInboundCodeCount: number
pendingPlanCount: number
plannedArrivalAt: string | null
allPlansReady: boolean
blockingReason: string | null
}
export interface ContainerPlanProgressItemDto {
orderId: string
customerId: string
orderNo: string | null
inboundCode: string | null
orderStatus: string
planId: string | null
planNo: string | null
planStatus: string | null
planValid: boolean
plannedArrivalAt: string | null
}
export interface ContainerPlanProgressDetailDto {
summary: ContainerPlanProgressSummaryDto
orders: ContainerPlanProgressItemDto[]
2026-08-27 17:16:38 +08:00
}
2026-08-27 16:34:32 +08:00
export interface ConvertContainerInboundPlanPayload {
sourceContainerBookingId: string
2026-08-28 14:33:57 +08:00
}
2026-08-20 09:10:36 +08:00
export interface LastMileOrderDetailDto {
order: LastMileOrderDto
cargo: LastMileCargoDto[]
statusHistory: LastMileStatusHistoryDto[]
2026-08-26 11:10:22 +08:00
fees: LastMileFeeDto[]
operationHistory: LastMileOperationDto[]
2026-08-20 09:10:36 +08:00
}
export async function listLastMileOrders(query: LastMileOrderQuery) {
const response = await overseasHttp.get<ApiEnvelope<OverseasPagePayload<LastMileOrderSummaryDto>>, ApiEnvelope<OverseasPagePayload<LastMileOrderSummaryDto>>>(
2026-08-20 09:10:36 +08:00
'/platform/v1/last-leg/orders',
2026-08-21 11:20:09 +08:00
{ params: query },
2026-08-20 09:10:36 +08:00
)
return normalizeOverseasPage(unwrapApiResponse(response))
2026-08-20 09:10:36 +08:00
}
2026-08-21 11:20:09 +08:00
export async function getLastMileOrder(orderId: string) {
2026-08-20 09:10:36 +08:00
const response = await overseasHttp.get<ApiEnvelope<LastMileOrderDetailDto>, ApiEnvelope<LastMileOrderDetailDto>>(
`/platform/v1/last-leg/orders/${encodeURIComponent(orderId)}`,
2026-08-21 11:20:09 +08:00
)
return unwrapApiResponse(response)
}
2026-08-30 18:50:16 +08:00
export async function downloadLastMileOrders(query: Partial<LastMileOrderQuery>) {
2026-08-31 14:42:28 +08:00
const { page: _page, size: _size, ...filters } = query
const params = Object.fromEntries(
Object.entries(filters).filter(([, value]) => value !== undefined && value !== null && value !== ''),
)
const blob = await overseasHttp.get<Blob, Blob>('/platform/v1/last-leg/orders/export', { params, responseType: 'blob' })
if (!blob.type.toLowerCase().includes('json')) return blob
let error: Partial<ApiEnvelope<unknown>>
try {
error = JSON.parse(await blob.text()) as Partial<ApiEnvelope<unknown>>
} catch {
throw new ApiResponseError('导出接口返回了非 CSV 内容', 'INVALID_EXPORT_RESPONSE')
}
throw new ApiResponseError(
error.message || '尾程订单导出失败',
error.code || 'INVALID_EXPORT_RESPONSE',
undefined,
error.data,
error.requestId,
error.traceId,
)
2026-08-30 18:50:16 +08:00
}
2026-08-26 11:10:22 +08:00
export async function createLastMileOrderFee(orderId: string, payload: CreateLastMileFeePayload) {
const response = await overseasHttp.post<ApiEnvelope<LastMileFeeDto>, ApiEnvelope<LastMileFeeDto>>(
`/platform/v1/last-leg/orders/${encodeURIComponent(orderId)}/fees`, payload,
)
return unwrapApiResponse(response)
}
2026-08-21 11:20:09 +08:00
export async function transferLastMileOrders(payload: TransferDestinationPayload) {
const response = await overseasHttp.put<ApiEnvelope<number>, ApiEnvelope<number>>(
'/platform/v1/last-leg/orders/destination', payload,
2026-08-20 09:10:36 +08:00
)
return unwrapApiResponse(response)
}
2026-08-21 17:20:40 +08:00
export async function convertLastMileOrderToInboundPlan(payload: ConvertInboundPlanPayload) {
const response = await overseasHttp.post<ApiEnvelope<unknown>, ApiEnvelope<unknown>>(
'/platform/v1/last-leg/inbound-plans/convert', payload,
)
return unwrapApiResponse(response)
}
2026-08-28 14:33:57 +08:00
2026-08-28 13:54:44 +08:00
export async function listContainerPlanProgress(query: ContainerPlanProgressQuery): Promise<OverseasPageResult<ContainerPlanProgressSummaryDto>> {
const response = await overseasHttp.get<ApiEnvelope<OverseasPagePayload<ContainerPlanProgressSummaryDto>>, ApiEnvelope<OverseasPagePayload<ContainerPlanProgressSummaryDto>>>(
2026-08-27 17:16:38 +08:00
'/platform/v1/last-leg/orders/container-summaries',
{ params: query },
)
return normalizeOverseasPage(unwrapApiResponse(response))
}
2026-08-28 13:54:44 +08:00
export async function getContainerPlanProgress(sourceContainerBookingId: string) {
const response = await overseasHttp.get<ApiEnvelope<ContainerPlanProgressDetailDto>, ApiEnvelope<ContainerPlanProgressDetailDto>>(
`/platform/v1/last-leg/orders/container-summaries/${encodeURIComponent(sourceContainerBookingId)}`,
2026-08-28 14:33:57 +08:00
)
return unwrapApiResponse(response)
}
2026-08-27 16:34:32 +08:00
export async function convertLastMileContainerToInboundPlans(payload: ConvertContainerInboundPlanPayload) {
const response = await overseasHttp.post<ApiEnvelope<InboundPlanDetailDto[]>, ApiEnvelope<InboundPlanDetailDto[]>>(
'/platform/v1/last-leg/inbound-plans/convert-container', payload,
2026-08-31 14:42:28 +08:00
)
return unwrapApiResponse(response)
}