From c726df30070d9bfc8067764f02852a07108bd8d4 Mon Sep 17 00:00:00 2001 From: liuyihe <2513762445@qq.com> Date: Thu, 29 Oct 2026 13:37:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/fulfillment.js | 27 +++ src/pages/outbound/outbound.vue | 107 ++++++++++-- src/pages/return-counting/return-counting.vue | 2 +- .../warehouse-transfer/warehouse-transfer.vue | 6 +- tests/discard-rent-preparation.test.mjs | 86 ++++++++++ tests/fulfillment-stock-commands.test.mjs | 1 - tests/outbound-lifecycle.test.mjs | 156 +++++++++++++++++- 7 files changed, 363 insertions(+), 22 deletions(-) create mode 100644 tests/discard-rent-preparation.test.mjs diff --git a/src/api/fulfillment.js b/src/api/fulfillment.js index 78eadf9..1e4150e 100644 --- a/src/api/fulfillment.js +++ b/src/api/fulfillment.js @@ -188,9 +188,36 @@ export async function resolveCargoDiscardPallet(palletNo, discardNo) { export async function confirmCargoDiscard(discardNo, palletNo, lines, photoFileIds, scannedCartonMarks = [], confirmAllCartons = false, request = {}) { const body = { lines, photoFileIds, scannedCartonMarks, confirmAllCartons, idempotencyKey: request.idempotencyKey } requireStockCommandIdentity(request) + // 出库前按同一份货物、照片和幂等键校验仓租,资金就绪后才提交库存扣减。 + await prepareDiscardRent({ mode: 'DISCARD', businessNo: discardNo, palletNo, ...body }) return normalizeCargoDiscardTask(await overseasRequest('POST', `${CARGO_DISCARD_BASE}/${encoded(discardNo)}/pallets/${encoded(palletNo)}/confirm`, body)) } +/** 本次点击内只查询资金回执,不缓存或自动重放失败的出库命令。 */ +async function prepareDiscardRent(body) { + const base = '/pda/v1/last-leg/storage-rent/preparations' + let preparationId + try { + let preparation = await overseasRequest('POST', base, body) + preparationId = preparation?.preparationId + for (let attempt = 0; preparation?.ready !== true && preparation?.status === 'FREEZE_PENDING' && preparationId && attempt < 20; attempt++) { + await new Promise(resolve => setTimeout(resolve, 500)) + preparation = await overseasRequest('GET', `${base}/${encoded(preparationId)}`) + } + if (preparation?.ready !== true) { + const message = preparation?.message ? `仓租校验未通过:${preparation.message}` : '仓租资金预校验尚未通过,请稍后重新提交' + throw Object.assign(new Error(message), { code: 'A0409' }) + } + } catch (error) { + // 尚未发送出库命令时释放已知的未使用预占,释放失败保留原错误诊断。 + if (preparationId) { + try { await overseasRequest('DELETE', `${base}/${encoded(preparationId)}`) } + catch (releaseError) { console.error('[Overseas PDA discard] rent preparation release failed', { code: releaseError?.code, requestId: releaseError?.requestId, traceId: releaseError?.traceId }) } + } + throw error + } +} + const discardPhotoPath = (discardNo, palletNo) => `${CARGO_DISCARD_BASE}/${encoded(discardNo)}/pallets/${encoded(palletNo)}/photos/files` export const listCargoDiscardPhotos = (discardNo, palletNo) => overseasRequest('GET', discardPhotoPath(discardNo, palletNo)) export const uploadCargoDiscardPhoto = (discardNo, palletNo, filePath) => overseasUpload(discardPhotoPath(discardNo, palletNo), filePath) diff --git a/src/pages/outbound/outbound.vue b/src/pages/outbound/outbound.vue index a138331..400cf78 100644 --- a/src/pages/outbound/outbound.vue +++ b/src/pages/outbound/outbound.vue @@ -11,7 +11,7 @@ 正在加载出库任务… - {{ error.message }}错误码:{{ error.code }}requestId:{{ error.requestId }}traceId:{{ error.traceId }}网络连接失败,当前任务、扫码草稿和幂等键均已保留。 + {{ error.message }}错误码:{{ error.code }}requestId:{{ error.requestId }}traceId:{{ error.traceId }}网络连接失败,请刷新核对任务状态后重试。