diff --git a/src/components/Jodetail/JobPickExecutionsecondscan.tsx b/src/components/Jodetail/JobPickExecutionsecondscan.tsx index 167b23e..1a22e8a 100644 --- a/src/components/Jodetail/JobPickExecutionsecondscan.tsx +++ b/src/components/Jodetail/JobPickExecutionsecondscan.tsx @@ -601,77 +601,64 @@ const JobPickExecution: React.FC = ({ filterArgs, onBack }) => { }, [currentPickOrderId, currentUserId, handleUnassign, onBack]); const handleSubmitAllScanned = useCallback(async () => { - const scannedLots = combinedLotData.filter(lot => - lot.matchStatus === 'scanned'|| - lot.stockOutLineStatus === 'completed' + // A) 先算每个 item 的 actual pick 总量(仅给 Confirm All 用) + const itemTotalActualPickQtyMap = combinedLotData.reduce>((acc, lot) => { + const itemKey = `${lot.pickOrderId}-${lot.pickOrderLineId}-${lot.itemId}`; // 或 getItemKey(lot) + const qty = Number(lot.actualPickQty ?? 0); + acc[itemKey] = (acc[itemKey] ?? 0) + qty; + return acc; + }, {}); + + // B) 只选 pending(不要 completed) + const pendingLots = combinedLotData.filter( + (lot) => String(lot.matchStatus || "").toLowerCase() === "pending" ); - - if (scannedLots.length === 0) { - console.log("No scanned items to submit"); + + // C) 同一个 item 只提交一次(避免重复) + const uniqueLots = Array.from( + new Map( + pendingLots.map((lot) => [ + `${lot.pickOrderId}-${lot.pickOrderLineId}-${lot.itemId}`, + lot, + ]) + ).values() + ); + + if (uniqueLots.length === 0) { + console.log("No pending items to submit"); return; } - + setIsSubmittingAll(true); - console.log(`📦 Submitting ${scannedLots.length} scanned items in parallel...`); - + try { - const submitPromises = scannedLots.map(async (lot) => { - const submitQty = lot.requiredQty || lot.pickOrderLineRequiredQty; - - console.log(`Submitting item ${lot.itemCode}: qty=${submitQty}`); - - const result = await submitSecondScanQuantity( - lot.pickOrderId, - lot.itemId, - { - qty: submitQty, - userId: currentUserId !!, - isMissing: false, - isBad: false, - reason: undefined - } - ); - + const submitPromises = uniqueLots.map(async (lot) => { + const itemKey = `${lot.pickOrderId}-${lot.pickOrderLineId}-${lot.itemId}`; + const submitQty = Number(itemTotalActualPickQtyMap[itemKey] ?? 0); // Confirm All 用 actual total + + if (submitQty <= 0) { + return { success: false, itemCode: lot.itemCode }; + } + + const result = await submitSecondScanQuantity(lot.pickOrderId, lot.itemId, { + qty: submitQty, + userId: currentUserId!!, + isMissing: false, + isBad: false, + reason: undefined, + }); + return { success: result.code === "SUCCESS", itemCode: lot.itemCode }; }); - + const results = await Promise.all(submitPromises); - const successCount = results.filter(r => r.success).length; - - console.log(` Batch submit completed: ${successCount}/${scannedLots.length} items submitted`); - + const successCount = results.filter((r) => r.success).length; + console.log(`Batch submit completed: ${successCount}/${uniqueLots.length}`); await fetchJobOrderData(); - - if (successCount > 0) { - setQrScanSuccess(true); - setTimeout(() => { - setQrScanSuccess(false); - // 添加:提交成功后返回到列表 - if (onBack) { - onBack(); - } - }, 2000); - } - - } catch (error: any) { - console.error("Error submitting all scanned items:", error); - - const isAuthError = error?.status === 401 || - error?.status === 403 || - error?.message?.toLowerCase().includes('unauthorized') || - error?.message?.toLowerCase().includes('token'); - - if (isAuthError) { - console.log("🔒 Authentication error in submit, unassigning pick order"); - await handleUnassign(currentPickOrderId); - } - - setQrScanError(true); } finally { setIsSubmittingAll(false); } - }, [combinedLotData, fetchJobOrderData, currentPickOrderId, handleUnassign, onBack]); - + }, [combinedLotData, currentUserId, fetchJobOrderData]); const scannedItemsCount = useMemo(() => { return combinedLotData.filter(lot => lot.matchStatus === 'scanned').length; }, [combinedLotData]);