From 6b1fb42737200f97bb66ba5a352d9b13181f2b33 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Tue, 14 Jul 2026 11:24:35 +0800 Subject: [PATCH] =?UTF-8?q?do=20scan=20fix,=20add=20back=20noLot=20+=20?= =?UTF-8?q?=E6=8E=83=E6=96=B0=E5=BB=BA=E6=89=B9=20case=20handle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkbenchGoodPickExecutionDetail.tsx | 73 +++++++++++++++++-- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx b/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx index b45b8ce..0d22fbe 100644 --- a/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx +++ b/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx @@ -191,6 +191,45 @@ function hasPendingActiveRowForStockInLine( ); } +/** + * True when this item still has a pending SOL that scan can bind to — including + * noLot / expired / unavailable rows (those are excluded from activeLotsByItemId). + * Used so a brand-new stockInLineId can still reach auto-switch. + */ +function hasPendingSwitchableRowForItem( + indexes: { byItemId: Map }, + itemId: number, + processedByItemId: ProcessedStockOutLinesByItemId, +): boolean { + const rows = indexes.byItemId.get(itemId) ?? []; + return rows.some( + (lot) => + isLotRowPending(lot) && + !isStockOutLineAlreadyProcessed(processedByItemId, itemId, lot.stockOutLineId), + ); +} + +/** Allow scan when scanned SIL still needed, or item has any pending/noLot row for auto-switch. */ +function canProcessWorkbenchScanPick( + indexes: { + byStockInLineId: Map; + activeLotsByItemId: Map; + byItemId: Map; + }, + itemId: number, + stockInLineId: number, + processedByItemId: ProcessedStockOutLinesByItemId, +): boolean { + return ( + hasPendingActiveRowForStockInLine( + indexes, + itemId, + stockInLineId, + processedByItemId, + ) || hasPendingSwitchableRowForItem(indexes, itemId, processedByItemId) + ); +} + function findExactActiveMatchForStockInLine( stockInLineLots: any[], scannedItemId: number, @@ -1625,7 +1664,7 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO const scannedStockInLineId = qrData.stockInLineId; if ( - !hasPendingActiveRowForStockInLine( + !canProcessWorkbenchScanPick( indexes, scannedItemId, scannedStockInLineId, @@ -1730,20 +1769,38 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO console.log(`⚠️ [QR PROCESS] No active suggested lots, auto-switching to scanned lot.`); - // Find a rejected lot as expected lot (the one that was rejected) - const rejectedLot = allLotsForItem.find((lot: any) => - lot.stockOutLineStatus?.toLowerCase() === 'rejected' || - lot.lotAvailability === 'rejected' || - isInventoryLotLineUnavailable(lot) + // Prefer pending noLot / rejected / unavailable rows (not completed ones). + const switchableLot = allLotsForItem.find( + (lot: any) => + isLotRowPending(lot) && + !isStockOutLineAlreadyProcessed( + processedQrCombinations, + scannedItemId, + lot.stockOutLineId, + ) && + (lot.noLot === true || + lot.stockOutLineStatus?.toLowerCase() === "rejected" || + lot.lotAvailability === "rejected" || + isInventoryLotLineUnavailable(lot) || + isLotAvailabilityExpired(lot)), ); const expectedLot = - rejectedLot || + switchableLot || pickExpectedLotForSubstitution( allLotsForItem.filter( (l: any) => l.lotNo != null && String(l.lotNo).trim() !== "" ), processedQrCombinations, ) || + allLotsForItem.find( + (lot: any) => + isLotRowPending(lot) && + !isStockOutLineAlreadyProcessed( + processedQrCombinations, + scannedItemId, + lot.stockOutLineId, + ), + ) || allLotsForItem[0]; let scannedLotNo: string | null = scannedLot?.lotNo || null; @@ -2210,7 +2267,7 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO // Workbench 策略:不彈窗,直接切換到掃到的批次並提交一次掃描 const mismatchCheckStartTime = performance.now(); if ( - !hasPendingActiveRowForStockInLine( + !canProcessWorkbenchScanPick( indexes, scannedItemId, scannedStockInLineId,