fix(lastleg): repair dispatch cancellation and return execution contracts

This commit is contained in:
2026-10-18 16:34:14 +08:00
parent 66a0beb653
commit aa33514ec6
64 changed files with 2061 additions and 213 deletions
@@ -892,6 +892,42 @@ export async function pickAll(context, token, dispatchNo) {
return success(replay.response)
}
/** 只从本次派送的真实主单及其原出库来源创建退回请求,不要求普通入仓关联。 */
export async function createDeliveryReturn(context, { customerId, warehouseId, deliveryNo, outboundNo }) {
const eligibleSource = source => /^[1-9][0-9]*$/.test(id(source?.outboundPalletItemId))
&& /^[1-9][0-9]*$/.test(id(source?.inventoryPositionId)) && source?.returnCartonId == null
&& Number.isSafeInteger(Number(source?.maxReturnPackages)) && Number(source.maxReturnPackages) > 0
const returnOptions = await platform(context, 'GET', '查询派送退回可选主单',
query(`${LASTLEG_BASE}/delivery-orders/${encodeURIComponent(deliveryNo)}/return-inbound-options`, { customerId }))
const returnCandidate = Array.isArray(returnOptions.data)
? returnOptions.data.find((value) => /^[1-9][0-9]*$/.test(id(value?.lastMileOrderId))
&& id(value?.customerId) === customerId && id(value?.overseasWarehouseId) === warehouseId
&& value?.deliveryNo === deliveryNo && value?.outboundNo === outboundNo
&& Array.isArray(value?.returnSources) && value.returnSources.some(eligibleSource)) : null
context.assert(MODULE, '退回候选严格属于当前派送单', returnOptions.response,
id(returnCandidate?.lastMileOrderId) && returnCandidate?.deliveryNo === deliveryNo && returnCandidate?.outboundNo === outboundNo,
`candidate=${Boolean(returnCandidate)}; ${trace(returnOptions.response)}`, OPTIONS)
if (!returnCandidate) return null
const returnSource = Array.isArray(returnCandidate.returnSources)
? returnCandidate.returnSources.find(eligibleSource) : null
context.assert(MODULE, '退回候选包含可追溯的出库托盘库存来源', returnOptions.response,
Boolean(returnSource), `source=${Boolean(returnSource)}; ${trace(returnOptions.response)}`, OPTIONS)
if (!returnSource) return null
const returnBody = {
lastMileOrderId: id(returnCandidate.lastMileOrderId), reason: `${context.marker}-delivery-return`,
returnDirection: 'OVERSEAS_WAREHOUSE', returnLogisticsNo: `${context.marker}-RETURN`.slice(0, 128),
items: [{
outboundPalletItemId: id(returnSource.outboundPalletItemId),
inventoryPositionId: id(returnSource.inventoryPositionId),
packageCount: 1,
}],
idempotencyKey: key(context, 'DELIVERY-RETURN'),
}
const returned = await platform(context, 'POST', '标记派送退回海外仓并创建退货异常',
query(`${LASTLEG_BASE}/delivery-orders/${encodeURIComponent(deliveryNo)}/mark-return`, { customerId }), returnBody)
return { returned, returnBody }
}
export async function run(context) {
context.createdResources.phase5OverseasFulfillment = {
marker: context.marker, dispatchNo: null, outboundNo: null, deliveryNo: null, deliveryNos: [],
@@ -1196,34 +1232,9 @@ export async function run(context) {
nonBlank(manualExceptionNo) && manualException.data?.status === 'PENDING', trace(manualException.response), OPTIONS)
context.createdResources.phase5OverseasFulfillment.manualExceptionNo = manualExceptionNo || null
const returnOptions = await platform(context, 'GET', '查询派送退回可选入仓单',
query(`${LASTLEG_BASE}/delivery-orders/${encodeURIComponent(deliveryNo)}/return-inbound-options`, { customerId }))
const returnInbound = Array.isArray(returnOptions.data)
? returnOptions.data.find((value) => Array.isArray(value?.returnSources)
&& value.returnSources.some((source) => id(source?.outboundPalletItemId)
&& id(source?.inventoryPositionId) && Number(source?.maxReturnPackages) > 0)) : null
context.assert(MODULE, '退回候选严格属于当前派送单', returnOptions.response,
id(returnInbound?.inboundOrderId) && returnInbound?.deliveryNo === deliveryNo && returnInbound?.outboundNo === outboundNo,
`candidate=${Boolean(returnInbound)}; ${trace(returnOptions.response)}`, OPTIONS)
if (!returnInbound) return
const returnSource = Array.isArray(returnInbound.returnSources)
? returnInbound.returnSources.find((value) => id(value?.outboundPalletItemId)
&& id(value?.inventoryPositionId) && Number(value?.maxReturnPackages) > 0) : null
context.assert(MODULE, '退回候选包含可追溯的出库托盘库存来源', returnOptions.response,
Boolean(returnSource), `source=${Boolean(returnSource)}; ${trace(returnOptions.response)}`, OPTIONS)
if (!returnSource) return
const returnBody = {
inboundOrderId: id(returnInbound.inboundOrderId), reason: `${context.marker}-delivery-return`,
returnDirection: 'OVERSEAS_WAREHOUSE', returnLogisticsNo: `${context.marker}-RETURN`.slice(0, 128),
items: [{
outboundPalletItemId: id(returnSource.outboundPalletItemId),
inventoryPositionId: id(returnSource.inventoryPositionId),
packageCount: 1,
}],
idempotencyKey: key(context, 'DELIVERY-RETURN'),
}
const returned = await platform(context, 'POST', '标记派送退回海外仓并创建退货异常',
query(`${LASTLEG_BASE}/delivery-orders/${encodeURIComponent(deliveryNo)}/mark-return`, { customerId }), returnBody)
const returnRequest = await createDeliveryReturn(context, { customerId, warehouseId, deliveryNo, outboundNo })
if (!returnRequest) return
const { returned, returnBody } = returnRequest
const returnExceptionNo = id(returned.data?.exceptionNo)
context.assert(MODULE, '派送退回生成独立PENDING异常单', returned.response,
nonBlank(returnExceptionNo) && returned.data?.status === 'PENDING'