| @@ -164,8 +164,8 @@ const QrCodeModal: React.FC<{ | |||
| console.log(` QR Code verified for lot: ${lot.lotNo}`); | |||
| setQrScanSuccess(true); | |||
| onQrCodeSubmit(lot.lotNo); | |||
| onClose(); | |||
| resetScan(); | |||
| // onClose(); | |||
| //resetScan(); | |||
| } else { | |||
| console.log(` QR Code mismatch. Expected: ${lot.lotNo}, Got: ${stockInLineInfo.lotNo}`); | |||
| setQrScanFailed(true); | |||
| @@ -1959,7 +1959,7 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO | |||
| return; | |||
| } | |||
| const checkTime = performance.now() - checkProcessedStartTime; | |||
| console.log(`⏱️ [QR PROCESS] Not processed check time: ${checkTime.toFixed(2)}ms`); | |||
| console.log(` [QR PROCESS] Not processed check time: ${checkTime.toFixed(2)}ms`); | |||
| // Handle special shortcut | |||
| if (latestQr === "{2fic}") { | |||
| @@ -2718,14 +2718,13 @@ const handleSubmitAllScanned = useCallback(async () => { | |||
| // ✅ noLot 情况:允许 checked / pending / partially_completed / PARTIALLY_COMPLETE | |||
| if (lot.noLot === true) { | |||
| return status === 'checked' || | |||
| status === 'pending' || | |||
| status === 'partially_completed' || | |||
| status === 'PARTIALLY_COMPLETE'; | |||
| } | |||
| // ✅ 正常 lot:也放宽为允许 checked / pending / partially_completed / PARTIALLY_COMPLETE | |||
| // 这样即使用户先改数(状态变为 pending / partially_completed),仍然可以批量提交 | |||
| return status === 'checked' || | |||
| status === 'pending' || | |||
| status === 'partially_completed' || | |||
| status === 'PARTIALLY_COMPLETE'; | |||
| }); | |||
| @@ -2741,24 +2740,36 @@ const handleSubmitAllScanned = useCallback(async () => { | |||
| try { | |||
| // 转换为 batchSubmitList 所需的格式(与后端 QrPickBatchSubmitRequest 匹配) | |||
| const lines: batchSubmitListLineRequest[] = scannedLots.map((lot) => { | |||
| const submitQty = lot.requiredQty || lot.pickOrderLineRequiredQty || 0; | |||
| const currentActualPickQty = lot.actualPickQty || 0; | |||
| const cumulativeQty = currentActualPickQty + submitQty; | |||
| let newStatus = 'partially_completed'; | |||
| if (cumulativeQty >= (lot.requiredQty || 0)) { | |||
| newStatus = 'completed'; | |||
| // 1. 需求数量:优先用 lot.requiredQty,没有就用 pickOrderLineRequiredQty | |||
| const requiredQty = | |||
| Number(lot.requiredQty || lot.pickOrderLineRequiredQty || 0); | |||
| // 2. 当前已经拣到的数量(数据库里对应的是 stock_out_line.qty) | |||
| const currentActualPickQty = Number(lot.actualPickQty || 0); | |||
| // 3. 还需要拣多少:不能为负数 | |||
| const remainingQty = Math.max(0, requiredQty - currentActualPickQty); | |||
| // 4. 本次批量提交后的目标累计值 = 当前 + 剩余 | |||
| const cumulativeQty = currentActualPickQty + remainingQty; | |||
| // 5. 根据“目标累计值是否达到需求”决定状态 | |||
| let newStatus = "partially_completed"; | |||
| if (requiredQty > 0 && cumulativeQty >= requiredQty) { | |||
| newStatus = "completed"; | |||
| } | |||
| return { | |||
| stockOutLineId: Number(lot.stockOutLineId) || 0, | |||
| pickOrderLineId: Number(lot.pickOrderLineId), | |||
| // ⚠️ 这里按你现在的写法是用 lot.lotId,当心是否真的是 inventoryLotLineId | |||
| inventoryLotLineId: lot.lotId ? Number(lot.lotId) : null, | |||
| requiredQty: Number(lot.requiredQty || lot.pickOrderLineRequiredQty || 0), | |||
| actualPickQty: Number(cumulativeQty), | |||
| requiredQty, | |||
| // 传“目标累计值”,后端会用它减去当前数据库里的 qty 得到增量 | |||
| actualPickQty: cumulativeQty, | |||
| stockOutLineStatus: newStatus, | |||
| pickOrderConsoCode: String(lot.pickOrderConsoCode || ''), | |||
| noLot: Boolean(lot.noLot === true) | |||
| pickOrderConsoCode: String(lot.pickOrderConsoCode || ""), | |||
| noLot: Boolean(lot.noLot === true), | |||
| }; | |||
| }); | |||
| @@ -2822,12 +2833,12 @@ const handleSubmitAllScanned = useCallback(async () => { | |||
| // ✅ 与 handleSubmitAllScanned 完全保持一致 | |||
| if (lot.noLot === true) { | |||
| return status === 'checked' || | |||
| status === 'pending' || | |||
| status === 'partially_completed' || | |||
| status === 'PARTIALLY_COMPLETE'; | |||
| } | |||
| return status === 'checked' || | |||
| status === 'pending' || | |||
| status === 'partially_completed' || | |||
| status === 'PARTIALLY_COMPLETE'; | |||
| }); | |||
| @@ -2844,7 +2855,7 @@ const handleSubmitAllScanned = useCallback(async () => { | |||
| return filtered.length; | |||
| }, [combinedLotData]); | |||
| /* | |||
| // ADD THIS: Auto-stop scan when no data available | |||
| useEffect(() => { | |||
| if (isManualScanning && combinedLotData.length === 0) { | |||
| @@ -2852,6 +2863,7 @@ const handleSubmitAllScanned = useCallback(async () => { | |||
| handleStopScan(); | |||
| } | |||
| }, [combinedLotData.length, isManualScanning, handleStopScan]); | |||
| */ | |||
| // Cleanup effect | |||
| useEffect(() => { | |||