71 lines
6.6 KiB
TypeScript
71 lines
6.6 KiB
TypeScript
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
|
import { normalizeReturnSource, type ReturnSourceIdentity } from '../returnSource'
|
|
|
|
import { normalizeOverseasPage, type OverseasPagePayload } from './lastMileOrders'
|
|
|
|
export interface ExceptionOrderQuery { page: number; size: number; keyword?: string; exceptionType?: string; status?: string; customerId?: string; warehouseId?: string; createdFrom?: string; createdTo?: string }
|
|
export interface ExceptionOrderRow {
|
|
id: string; exceptionNo: string; exceptionType: string; status: string; reason: string
|
|
customerId: string; customerName?: string | null; overseasWarehouseId?: string | null; overseasWarehouseName?: string | null
|
|
lastMileOrderId?: string | null; lastMileOrderNo?: string | null; inboundOrderId?: string | null; inboundCode?: string | null
|
|
deliveryOrderId?: string | null; deliveryNo?: string | null; outboundNo?: string | null
|
|
skuCode?: string | null; packageCount?: number | null; returnDirection?: string | null; returnLogisticsNo?: string | null
|
|
handlingAction?: string | null; handlerName?: string | null; exceptionAt: string; updatedAt: string
|
|
version?: number; allowedActions?: string[]; evidenceFileIds?: string[]; handlingResult?: string | null; completedAt?: string | null
|
|
}
|
|
|
|
export interface ExceptionReturnSource extends ReturnSourceIdentity { outboundPalletItemId: string; palletNo?: string | null; skuCode?: string | null; cartonMark?: string | null; maxReturnPackages: number }
|
|
export interface ExceptionRelatedDelivery { deliveryNo: string; status: string }
|
|
export interface ExceptionRedispatch { dispatchNo: string; status: string; selectedPackages: number; pickedPackages: number; deliveries: ExceptionRelatedDelivery[] }
|
|
export interface ExceptionReturnReceipt { receiptNo: string; receivedPackages: number; receivedAt: string; redispatches: ExceptionRedispatch[] }
|
|
export interface ExceptionDetail { order: ExceptionOrderRow; returnSources: ExceptionReturnSource[]; returnReceipts: ExceptionReturnReceipt[] }
|
|
export interface ExceptionReceipt extends ReturnSourceIdentity { outboundPalletItemId: string; receivedPackages: number; targetPalletId: string; targetPalletNo: string; targetLocationId: string; targetLocationCode: string }
|
|
export interface ExceptionCommand { expectedVersion: number; idempotencyKey: string; handlingAction?: string; reason?: string; handlingResult?: string; evidenceFileIds?: string[]; receipts?: ExceptionReceipt[] }
|
|
export type ExceptionAction = 'start-processing' | 'complete' | 'cancel'
|
|
export interface ExceptionCommandResult { exceptionNo: string; status: string; version: number; restoredPackages: number; replayed: boolean }
|
|
const exceptionPath = (number: string) => `/platform/v1/last-leg/exception-orders/${encodeURIComponent(number)}`
|
|
function safeInteger(value: unknown, label: string) {
|
|
if ((typeof value !== 'number' && typeof value !== 'string') || !/^\d+$/.test(String(value)) || !Number.isSafeInteger(Number(value))) throw new Error(`${label}无效,请重新加载`)
|
|
return Number(value)
|
|
}
|
|
export function normalizeExceptionDetail(value: ExceptionDetail): ExceptionDetail {
|
|
return { ...value, order: { ...value.order, version: safeInteger(value.order.version, '异常版本'), evidenceFileIds: value.order.evidenceFileIds?.map(String) },
|
|
returnSources: value.returnSources.map(row => ({ ...normalizeReturnSource(row), outboundPalletItemId: String(row.outboundPalletItemId), maxReturnPackages: safeInteger(row.maxReturnPackages, '剩余可收数量') })),
|
|
returnReceipts: value.returnReceipts.map(receipt => ({ ...receipt, receivedPackages: safeInteger(receipt.receivedPackages, '历史实收数量'),
|
|
redispatches: receipt.redispatches.map(dispatch => ({ ...dispatch, selectedPackages: safeInteger(dispatch.selectedPackages, '重派选定数量'),
|
|
pickedPackages: safeInteger(dispatch.pickedPackages, '重派实拣数量') })) })) }
|
|
}
|
|
export async function getExceptionDetail(customerId: string, exceptionNo: string) {
|
|
const response = await http.get<ApiEnvelope<ExceptionDetail>, ApiEnvelope<ExceptionDetail>>(exceptionPath(exceptionNo), { params: { customerId } })
|
|
return normalizeExceptionDetail(unwrapApiResponse(response))
|
|
}
|
|
export async function commandException(customerId: string, exceptionNo: string, action: ExceptionAction, payload: ExceptionCommand) {
|
|
const response = await http.post<ApiEnvelope<ExceptionCommandResult>, ApiEnvelope<ExceptionCommandResult>>(`${exceptionPath(exceptionNo)}/${action}`, payload, { params: { customerId } })
|
|
const result = unwrapApiResponse(response)
|
|
return { ...result, version: safeInteger(result.version, '操作版本'), restoredPackages: safeInteger(result.restoredPackages, '实际入账数量') }
|
|
}
|
|
export async function uploadExceptionEvidence(customerId: string, exceptionNo: string, file: File) {
|
|
const form = new FormData(); form.append('file', file)
|
|
const response = await http.post<ApiEnvelope<{ fileId: string; fileName: string }>, ApiEnvelope<{ fileId: string; fileName: string }>>(`${exceptionPath(exceptionNo)}/evidence`, form, { params: { customerId } })
|
|
return unwrapApiResponse(response)
|
|
}
|
|
export interface ExceptionRelation {
|
|
lastMileOrderId?: string | null; lastMileOrderNo?: string | null; inboundOrderId?: string | null; inboundCode?: string | null
|
|
customerId: string; customerName?: string | null; overseasWarehouseId?: string | null; overseasWarehouseName?: string | null
|
|
deliveryNo?: string | null; outboundNo?: string | null; availablePackages?: number | null
|
|
}
|
|
export interface CreateExceptionOrderPayload { customerId?: string; inboundCode?: string; lastMileOrderNo?: string; exceptionType: string; reason: string; packageCount?: number; skuCode?: string }
|
|
|
|
export async function listExceptionOrders(query: ExceptionOrderQuery) {
|
|
const response = await http.get<ApiEnvelope<OverseasPagePayload<ExceptionOrderRow>>, ApiEnvelope<OverseasPagePayload<ExceptionOrderRow>>>('/platform/v1/last-leg/exception-orders', { params: query })
|
|
return normalizeOverseasPage(unwrapApiResponse(response))
|
|
}
|
|
export async function resolveExceptionRelation(params: { customerId?: string; inboundCode?: string; lastMileOrderNo?: string }) {
|
|
const response = await http.get<ApiEnvelope<ExceptionRelation>, ApiEnvelope<ExceptionRelation>>('/platform/v1/last-leg/exception-orders/resolve', { params })
|
|
return unwrapApiResponse(response)
|
|
}
|
|
export async function createExceptionOrder(payload: CreateExceptionOrderPayload) {
|
|
const response = await http.post<ApiEnvelope<{ id: string; exceptionNo: string; status: string }>, ApiEnvelope<{ id: string; exceptionNo: string; status: string }>>('/platform/v1/last-leg/exception-orders', payload)
|
|
return unwrapApiResponse(response)
|
|
}
|