From 68fa2a575f3db4cada50ab34677e0f6d15fabe45 Mon Sep 17 00:00:00 2001 From: zhaoxing <2558691827@qq.com> Date: Sun, 15 Nov 2026 15:15:29 +0800 Subject: [PATCH] =?UTF-8?q?fix(consignment):=20=E5=86=85=E9=83=A8=E5=BA=93?= =?UTF-8?q?=E5=AD=98=E5=80=99=E9=80=89=E8=BF=87=E6=BB=A4=E6=8E=89=E5=B7=B2?= =?UTF-8?q?=E6=97=A0=E5=8F=AF=E7=94=A8=E4=BD=99=E9=87=8F=E7=9A=84=E7=8E=B0?= =?UTF-8?q?=E8=B4=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 内部库存匹配提醒与订单侧手动指定现货候选都过滤 remaining_quantity = 0 的库存 - 与提交接口 matchConsignmentWorkOrderManually 的可用性口径保持一致,避免「弹窗有货、提交报错」 - 补充源码断言用例 --- .../consignment-fulfillment-service.ts | 12 ++++++-- .../worker-platform-service.test.ts | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/apps/backend/src/services/worker-platform/consignment-fulfillment-service.ts b/apps/backend/src/services/worker-platform/consignment-fulfillment-service.ts index db4e13f6..584ebf18 100644 --- a/apps/backend/src/services/worker-platform/consignment-fulfillment-service.ts +++ b/apps/backend/src/services/worker-platform/consignment-fulfillment-service.ts @@ -251,7 +251,11 @@ export async function listWorkOrderInventoryMatchOptions(workOrderId: number | s return { hasMatch: false, exactCount: 0, partialCount: 0, options: [] } } const fields = resolveCollectSubmittedFieldValues(workOrder) - const inventories = await listActiveConsignmentInventoriesForMatching() + // 已被其它工单占用或已用尽的现货不能再出现在候选里:remaining_quantity=0 的库存 + // 提交时会被匹配引擎过滤掉,列出来只会让客服点了才知道不可用。 + const inventories = (await listActiveConsignmentInventoriesForMatching()).filter( + (inventory) => Number(inventory.remaining_quantity ?? 1) > 0, + ) const ranking = { exact: 0, partial: 1, conflict: 2 } const options = listConsignmentMatchOptions(workOrder.product_name, inventories, { system: fields.system, @@ -389,7 +393,11 @@ export async function checkWorkOrderInventoryMatches(workOrderId: number | strin const fields = resolveCollectSubmittedFieldValues(workOrder) - const inventories = await listActiveConsignmentInventoriesForMatching() + // 同上:无可用余量的现货(已被其它工单占用)不能作为「可直接履约」的提醒, + // 否则点进去只会被提交接口拒绝。 + const inventories = (await listActiveConsignmentInventoriesForMatching()).filter( + (inventory) => Number(inventory.remaining_quantity ?? 1) > 0, + ) const matches = findMatchingPeacekeeperInventories(workOrder.product_name, inventories, { system: fields.system, diff --git a/apps/backend/src/services/worker-platform/worker-platform-service.test.ts b/apps/backend/src/services/worker-platform/worker-platform-service.test.ts index dcbf7368..a30f51f3 100644 --- a/apps/backend/src/services/worker-platform/worker-platform-service.test.ts +++ b/apps/backend/src/services/worker-platform/worker-platform-service.test.ts @@ -2511,6 +2511,34 @@ test('寄卖只做整单:拼单工单不得进入寄卖现货履约链路', as ) }) +test('内部库存候选必须过滤掉无可用余量的现货:弹窗与提交口径一致', async () => { + const readFile = await import('node:fs/promises') + const src = await readFile.readFile( + new URL('./consignment-fulfillment-service.ts', import.meta.url), + 'utf8', + ) + + // 订单侧「手动指定现货」全量列表 + const optionsBody = src.slice( + src.indexOf('export async function listWorkOrderInventoryMatchOptions'), + src.indexOf('export async function listInventoryMatchableOrders'), + ) + assert.ok( + optionsBody.includes('Number(inventory.remaining_quantity ?? 1) > 0'), + '订单侧候选现货必须过滤掉已被其它工单占用/用尽的库存', + ) + + // 发布时的内部库存提醒:不过滤会出现「弹窗说有货、点履约报请选择可用库存」 + const matchesBody = src.slice( + src.indexOf('export async function checkWorkOrderInventoryMatches'), + src.indexOf('export async function fulfillWorkOrderWithConsignment'), + ) + assert.ok( + matchesBody.includes('Number(inventory.remaining_quantity ?? 1) > 0'), + '内部库存提醒必须与提交接口使用同一套可用性口径(remaining_quantity > 0)', + ) +}) + test('寄卖履约必须写入真实 SUB 单号:只能取带 join 的预读库存', async () => { const readFile = await import('node:fs/promises') const src = await readFile.readFile(