|
|
|
@@ -48,8 +48,10 @@ import { |
|
|
|
batchQrSubmit, |
|
|
|
batchSubmitList, // 添加:导入 batchSubmitList |
|
|
|
batchSubmitListRequest, // 添加:导入类型 |
|
|
|
batchSubmitListLineRequest |
|
|
|
|
|
|
|
batchSubmitListLineRequest, |
|
|
|
batchScan, |
|
|
|
BatchScanRequest, |
|
|
|
BatchScanLineRequest, |
|
|
|
} from "@/app/api/pickOrder/actions"; |
|
|
|
|
|
|
|
import FGPickOrderInfoCard from "./FGPickOrderInfoCard"; |
|
|
|
@@ -1834,6 +1836,62 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
// Special case: If submitQty is 0 and all values are 0, mark as completed with qty: 0 |
|
|
|
if (submitQty === 0) { |
|
|
|
console.log(`=== SUBMITTING ALL ZEROS CASE ===`); |
|
|
|
console.log(`Lot: ${lot.lotNo}`); |
|
|
|
console.log(`Stock Out Line ID: ${lot.stockOutLineId}`); |
|
|
|
console.log(`Setting status to 'completed' with qty: 0`); |
|
|
|
|
|
|
|
const updateResult = await updateStockOutLineStatus({ |
|
|
|
id: lot.stockOutLineId, |
|
|
|
status: 'completed', |
|
|
|
qty: 0 |
|
|
|
}); |
|
|
|
|
|
|
|
console.log('Update result:', updateResult); |
|
|
|
const r: any = updateResult as any; |
|
|
|
const updateOk = |
|
|
|
r?.code === 'SUCCESS' || |
|
|
|
r?.type === 'completed' || |
|
|
|
typeof r?.id === 'number' || |
|
|
|
typeof r?.entity?.id === 'number' || |
|
|
|
(r?.message && r.message.includes('successfully')); |
|
|
|
if (!updateResult || !updateOk) { |
|
|
|
console.error('Failed to update stock out line status:', updateResult); |
|
|
|
throw new Error('Failed to update stock out line status'); |
|
|
|
} |
|
|
|
|
|
|
|
// Check if pick order is completed |
|
|
|
if (lot.pickOrderConsoCode) { |
|
|
|
console.log(` Lot ${lot.lotNo} completed (all zeros), checking if pick order ${lot.pickOrderConsoCode} is complete...`); |
|
|
|
|
|
|
|
try { |
|
|
|
const completionResponse = await checkAndCompletePickOrderByConsoCode(lot.pickOrderConsoCode); |
|
|
|
console.log(` Pick order completion check result:`, completionResponse); |
|
|
|
|
|
|
|
if (completionResponse.code === "SUCCESS") { |
|
|
|
console.log(` Pick order ${lot.pickOrderConsoCode} completed successfully!`); |
|
|
|
} else if (completionResponse.message === "not completed") { |
|
|
|
console.log(`⏳ Pick order not completed yet, more lines remaining`); |
|
|
|
} else { |
|
|
|
console.error(` Error checking completion: ${completionResponse.message}`); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error("Error checking pick order completion:", error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
await fetchAllCombinedLotData(); |
|
|
|
console.log("All zeros submission completed successfully!"); |
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
checkAndAutoAssignNext(); |
|
|
|
}, 1000); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// FIXED: Calculate cumulative quantity correctly |
|
|
|
const currentActualPickQty = lot.actualPickQty || 0; |
|
|
|
const cumulativeQty = currentActualPickQty + submitQty; |
|
|
|
@@ -1882,7 +1940,7 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe |
|
|
|
console.log(` Pick order completion check result:`, completionResponse); |
|
|
|
|
|
|
|
if (completionResponse.code === "SUCCESS") { |
|
|
|
console.log(`�� Pick order ${lot.pickOrderConsoCode} completed successfully!`); |
|
|
|
console.log(` Pick order ${lot.pickOrderConsoCode} completed successfully!`); |
|
|
|
} else if (completionResponse.message === "not completed") { |
|
|
|
console.log(`⏳ Pick order not completed yet, more lines remaining`); |
|
|
|
} else { |
|
|
|
@@ -1905,8 +1963,14 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe |
|
|
|
} |
|
|
|
}, [fetchAllCombinedLotData, checkAndAutoAssignNext]); |
|
|
|
|
|
|
|
|
|
|
|
// Add these functions after line 395 |
|
|
|
const handleSkip = useCallback(async (lot: any) => { |
|
|
|
try { |
|
|
|
console.log("Skip clicked, submit 0 qty for lot:", lot.lotNo); |
|
|
|
await handleSubmitPickQtyWithQty(lot, 0); |
|
|
|
} catch (err) { |
|
|
|
console.error("Error in Skip:", err); |
|
|
|
} |
|
|
|
}, [handleSubmitPickQtyWithQty]); |
|
|
|
const handleStartScan = useCallback(() => { |
|
|
|
console.log(" Starting manual QR scan..."); |
|
|
|
setIsManualScanning(true); |
|
|
|
@@ -2001,7 +2065,86 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe |
|
|
|
console.error(" Error in handlelotnull:", error); |
|
|
|
} |
|
|
|
}, [fetchAllCombinedLotData, session, currentUserId, fgPickOrders]); |
|
|
|
// ... existing code ... |
|
|
|
const handleBatchScan = useCallback(async () => { |
|
|
|
const startTime = performance.now(); |
|
|
|
console.log(`⏱️ [BATCH SCAN START]`); |
|
|
|
console.log(`⏰ Start time: ${new Date().toISOString()}`); |
|
|
|
|
|
|
|
// 获取所有活跃批次(未扫描的) |
|
|
|
const activeLots = combinedLotData.filter(lot => { |
|
|
|
return ( |
|
|
|
lot.lotAvailability !== 'rejected' && |
|
|
|
lot.stockOutLineStatus !== 'rejected' && |
|
|
|
lot.stockOutLineStatus !== 'completed' && |
|
|
|
lot.stockOutLineStatus !== 'checked' && // ✅ 只处理未扫描的 |
|
|
|
lot.processingStatus !== 'completed' && |
|
|
|
lot.noLot !== true && |
|
|
|
lot.lotNo // ✅ 必须有 lotNo |
|
|
|
); |
|
|
|
}); |
|
|
|
|
|
|
|
if (activeLots.length === 0) { |
|
|
|
console.log("No active lots to scan"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
console.log(`📦 Batch scanning ${activeLots.length} active lots using batch API...`); |
|
|
|
|
|
|
|
try { |
|
|
|
// ✅ 转换为批量扫描 API 所需的格式 |
|
|
|
const lines: BatchScanLineRequest[] = activeLots.map((lot) => ({ |
|
|
|
pickOrderLineId: Number(lot.pickOrderLineId), |
|
|
|
inventoryLotLineId: lot.lotId ? Number(lot.lotId) : null, |
|
|
|
pickOrderConsoCode: String(lot.pickOrderConsoCode || ''), |
|
|
|
lotNo: lot.lotNo || null, |
|
|
|
itemId: Number(lot.itemId), |
|
|
|
itemCode: String(lot.itemCode || ''), |
|
|
|
stockOutLineId: lot.stockOutLineId ? Number(lot.stockOutLineId) : null, // ✅ 新增 |
|
|
|
})); |
|
|
|
|
|
|
|
const request: BatchScanRequest = { |
|
|
|
userId: currentUserId || 0, |
|
|
|
lines: lines |
|
|
|
}; |
|
|
|
|
|
|
|
console.log(`📤 Sending batch scan request with ${lines.length} lines`); |
|
|
|
console.log(`📋 Request data:`, JSON.stringify(request, null, 2)); |
|
|
|
|
|
|
|
const scanStartTime = performance.now(); |
|
|
|
|
|
|
|
// ✅ 使用新的批量扫描 API(一次性处理所有请求) |
|
|
|
const result = await batchScan(request); |
|
|
|
|
|
|
|
const scanTime = performance.now() - scanStartTime; |
|
|
|
console.log(`⏱️ Batch scan API call completed in ${scanTime.toFixed(2)}ms (${(scanTime / 1000).toFixed(3)}s)`); |
|
|
|
console.log(`📥 Batch scan result:`, result); |
|
|
|
|
|
|
|
// ✅ 刷新数据以获取最新的状态 |
|
|
|
const refreshStartTime = performance.now(); |
|
|
|
await fetchAllCombinedLotData(); |
|
|
|
const refreshTime = performance.now() - refreshStartTime; |
|
|
|
console.log(`⏱️ Data refresh time: ${refreshTime.toFixed(2)}ms (${(refreshTime / 1000).toFixed(3)}s)`); |
|
|
|
|
|
|
|
const totalTime = performance.now() - startTime; |
|
|
|
console.log(`⏱️ [BATCH SCAN END]`); |
|
|
|
console.log(`⏱️ Total time: ${totalTime.toFixed(2)}ms (${(totalTime / 1000).toFixed(3)}s)`); |
|
|
|
console.log(`⏰ End time: ${new Date().toISOString()}`); |
|
|
|
|
|
|
|
if (result && result.code === "SUCCESS") { |
|
|
|
setQrScanSuccess(true); |
|
|
|
setQrScanError(false); |
|
|
|
} else { |
|
|
|
console.error("❌ Batch scan failed:", result); |
|
|
|
setQrScanError(true); |
|
|
|
setQrScanSuccess(false); |
|
|
|
} |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error("❌ Error in batch scan:", error); |
|
|
|
setQrScanError(true); |
|
|
|
setQrScanSuccess(false); |
|
|
|
} |
|
|
|
}, [combinedLotData, fetchAllCombinedLotData, currentUserId]); |
|
|
|
const handleSubmitAllScanned = useCallback(async () => { |
|
|
|
const startTime = performance.now(); |
|
|
|
console.log(`⏱️ [BATCH SUBMIT START]`); |
|
|
|
@@ -2174,6 +2317,7 @@ const handleSubmitAllScanned = useCallback(async () => { |
|
|
|
<TestQrCodeProvider |
|
|
|
lotData={combinedLotData} |
|
|
|
onScanLot={handleQrCodeSubmit} |
|
|
|
onBatchScan={handleBatchScan} |
|
|
|
filterActive={(lot) => ( |
|
|
|
lot.lotAvailability !== 'rejected' && |
|
|
|
lot.stockOutLineStatus !== 'rejected' && |
|
|
|
@@ -2542,6 +2686,15 @@ paginatedData.map((lot, index) => { |
|
|
|
> |
|
|
|
{t("Issue")} |
|
|
|
</Button> |
|
|
|
<Button |
|
|
|
variant="outlined" |
|
|
|
size="small" |
|
|
|
onClick={() => handleSkip(lot)} |
|
|
|
disabled={lot.stockOutLineStatus === 'completed'} |
|
|
|
sx={{ fontSize: '0.7rem', py: 0.5, minHeight: '28px', minWidth: '60px' }} |
|
|
|
> |
|
|
|
{t("Skip")} |
|
|
|
</Button> |
|
|
|
</Stack> |
|
|
|
); |
|
|
|
})()} |
|
|
|
|