diff --git a/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx b/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx index 2e0e0c3..b45b8ce 100644 --- a/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx +++ b/src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx @@ -737,6 +737,12 @@ const [pickOrderSwitching, setPickOrderSwitching] = useState(false); const lastProcessedQrRef = useRef(''); /** Prevent double-submit while a scan-pick API is in flight (scanner bounce). */ const qrPickInFlightRef = useRef(false); + /** + * Only process newly appended qrValues entries. + * Prevents refresh/deps re-running the effect from auto-picking the next SOL + * with the same stale QR still sitting at the end of qrValues. + */ + const lastConsumedQrValuesLengthRef = useRef(0); /** Latest lot indexes for QR re-scan allow checks outside processOutsideQrCode. */ const lotDataIndexesRef = useRef<{ byStockInLineId: Map; @@ -2429,6 +2435,21 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO if (!isManualScanning || qrValues.length === 0 || combinedLotData.length === 0 || isRefreshingData) { return; } + + // Only react to newly appended QR events — not effect re-runs after refresh / index updates. + if (qrValues.length <= lastConsumedQrValuesLengthRef.current) { + console.log( + ` [QR PROCESS] Skipping — no new QR append (len=${qrValues.length}, consumed=${lastConsumedQrValuesLengthRef.current})`, + ); + return; + } + // Don't consume yet if a pick is in flight; retry after refresh / inFlight clears. + if (qrPickInFlightRef.current) { + console.log( + ` [QR PROCESS] Deferring new QR — scan-pick still in flight (len=${qrValues.length})`, + ); + return; + } const qrValuesChangeStartTime = performance.now(); console.log(` [QR VALUES EFFECT] Triggered at: ${new Date().toISOString()}`); @@ -2436,6 +2457,8 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO console.log(` [QR VALUES EFFECT] qrValues:`, qrValues); const latestQr = qrValues[qrValues.length - 1]; + // Claim this append immediately so refresh/deps re-entry cannot re-process it. + lastConsumedQrValuesLengthRef.current = qrValues.length; console.log(` [QR VALUES EFFECT] Latest QR: ${latestQr}`); console.log(` [QR VALUES EFFECT] Latest QR detected at: ${new Date().toISOString()}`); @@ -3311,6 +3334,8 @@ const handleStartScan = useCallback(() => { processedQrCodesRef.current = new Set(); lastProcessedQrRef.current = ''; qrPickInFlightRef.current = false; + // Ignore any QR values already in the buffer; only new scans after Start count. + lastConsumedQrValuesLengthRef.current = qrValues.length; setQrScanError(false); setQrScanSuccess(false); @@ -3322,7 +3347,7 @@ const handleStartScan = useCallback(() => { const totalTime = performance.now() - startTime; console.log(` [START SCAN] Total start scan time: ${totalTime.toFixed(2)}ms`); console.log(` [START SCAN] Start scan completed at: ${new Date().toISOString()}`); -}, [startScan]); +}, [startScan, qrValues.length]); const handlePickOrderSwitch = useCallback(async (pickOrderId: number) => { if (pickOrderSwitching) return; @@ -3347,6 +3372,7 @@ const handleStartScan = useCallback(() => { setQrScanSuccess(false); stopScan(); resetScan(); + lastConsumedQrValuesLengthRef.current = 0; }, [stopScan, resetScan]); // ... existing code around line 1469 ... const handlelotnull = useCallback(async (lot: any) => {