|
|
|
@@ -966,6 +966,14 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
let newLotLineId = scannedLotData?.inventoryLotLineId; |
|
|
|
if (!newLotLineId && scannedLotData?.stockInLineId) { |
|
|
|
try { |
|
|
|
if (currentUserId && selectedLotForQr.pickOrderId && selectedLotForQr.itemId) { |
|
|
|
try { |
|
|
|
await updateHandledBy(selectedLotForQr.pickOrderId, selectedLotForQr.itemId); |
|
|
|
console.log(`✅ [LOT CONFIRM] Handler updated for itemId ${selectedLotForQr.itemId}`); |
|
|
|
} catch (error) { |
|
|
|
console.error(`❌ [LOT CONFIRM] Error updating handler (non-critical):`, error); |
|
|
|
} |
|
|
|
} |
|
|
|
console.log(`🔍 [LOT CONFIRM] Fetching lot detail for stockInLineId: ${scannedLotData.stockInLineId}`); |
|
|
|
const ld = await fetchLotDetail(scannedLotData.stockInLineId); |
|
|
|
newLotLineId = ld.inventoryLotLineId; |
|
|
|
@@ -1083,7 +1091,7 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
} finally { |
|
|
|
setIsConfirmingLot(false); |
|
|
|
} |
|
|
|
}, [expectedLotData, scannedLotData, selectedLotForQr, fetchJobOrderData]); |
|
|
|
}, [expectedLotData, scannedLotData, selectedLotForQr, fetchJobOrderData,currentUserId, updateHandledBy ]); |
|
|
|
|
|
|
|
const processOutsideQrCode = useCallback(async (latestQr: string) => { |
|
|
|
// ✅ Only JSON QR supported for outside scanner (avoid false positive with lotNo) |
|
|
|
@@ -1249,6 +1257,14 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
|
|
|
|
console.log(`✅ [QR PROCESS] Processing exact match: lotNo=${exactMatch.lotNo}, stockOutLineId=${exactMatch.stockOutLineId}`); |
|
|
|
try { |
|
|
|
if (currentUserId && exactMatch.pickOrderId && exactMatch.itemId) { |
|
|
|
try { |
|
|
|
await updateHandledBy(exactMatch.pickOrderId, exactMatch.itemId); |
|
|
|
console.log(`✅ [QR PROCESS] Handler updated for itemId ${exactMatch.itemId}`); |
|
|
|
} catch (error) { |
|
|
|
console.error(`❌ [QR PROCESS] Error updating handler (non-critical):`, error); |
|
|
|
} |
|
|
|
} |
|
|
|
const res = await updateStockOutLineStatusByQRCodeAndLotNo({ |
|
|
|
pickOrderLineId: exactMatch.pickOrderLineId, |
|
|
|
inventoryLotNo: exactMatch.lotNo, |
|
|
|
@@ -1383,7 +1399,7 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
return newMap; |
|
|
|
}); |
|
|
|
} |
|
|
|
}, [filterArgs?.pickOrderId, fetchJobOrderData, handleLotMismatch, lotDataIndexes, processedQrCombinations, combinedLotData, fetchStockInLineInfoCached]); |
|
|
|
}, [filterArgs?.pickOrderId, fetchJobOrderData, handleLotMismatch, lotDataIndexes, processedQrCombinations, combinedLotData, fetchStockInLineInfoCached,currentUserId, updateHandledBy ]); |
|
|
|
|
|
|
|
// Store in refs for immediate access in qrValues effect |
|
|
|
processOutsideQrCodeRef.current = processOutsideQrCode; |
|
|
|
@@ -1649,6 +1665,14 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
if (currentUserId && lot.pickOrderId && lot.itemId) { |
|
|
|
try { |
|
|
|
await updateHandledBy(lot.pickOrderId, lot.itemId); |
|
|
|
} catch (error) { |
|
|
|
console.error("❌ Error updating handler (non-critical):", error); |
|
|
|
// Continue even if handler update fails |
|
|
|
} |
|
|
|
} |
|
|
|
// 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 ===`); |
|
|
|
@@ -1810,6 +1834,22 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
console.log(`📦 Submitting ${scannedLots.length} scanned items using batchSubmitList...`); |
|
|
|
|
|
|
|
try { |
|
|
|
// ✅ 批量更新所有相关行的 handler(在提交前) |
|
|
|
if (currentUserId) { |
|
|
|
const uniqueItemIds = new Set(scannedLots.map(lot => lot.itemId)); |
|
|
|
const updatePromises = Array.from(uniqueItemIds).map(itemId => { |
|
|
|
const lot = scannedLots.find(l => l.itemId === itemId); |
|
|
|
if (lot && lot.pickOrderId) { |
|
|
|
return updateHandledBy(lot.pickOrderId, itemId).catch(err => { |
|
|
|
console.error(`❌ Error updating handler for itemId ${itemId}:`, err); |
|
|
|
}); |
|
|
|
} |
|
|
|
return Promise.resolve(); |
|
|
|
}); |
|
|
|
await Promise.all(updatePromises); |
|
|
|
console.log(`✅ Updated handlers for ${uniqueItemIds.size} unique items`); |
|
|
|
} |
|
|
|
|
|
|
|
// ✅ 转换为 batchSubmitList 所需的格式 |
|
|
|
const lines: batchSubmitListLineRequest[] = scannedLots.map((lot) => { |
|
|
|
const submitQty = lot.requiredQty || lot.pickOrderLineRequiredQty || 0; |
|
|
|
@@ -1866,9 +1906,7 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
} finally { |
|
|
|
setIsSubmittingAll(false); |
|
|
|
} |
|
|
|
}, [combinedLotData, fetchJobOrderData, checkAndAutoAssignNext, currentUserId, filterArgs?.pickOrderId, onBackToList]) |
|
|
|
|
|
|
|
// Calculate scanned items count |
|
|
|
}, [combinedLotData, fetchJobOrderData, checkAndAutoAssignNext, currentUserId, filterArgs?.pickOrderId, onBackToList, updateHandledBy]) |
|
|
|
const scannedItemsCount = useMemo(() => { |
|
|
|
return combinedLotData.filter(lot => lot.stockOutLineStatus === 'checked').length; |
|
|
|
}, [combinedLotData]); |
|
|
|
@@ -1936,6 +1974,14 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
|
|
|
|
const handlePickExecutionFormSubmit = useCallback(async (data: any) => { |
|
|
|
try { |
|
|
|
if (currentUserId && selectedLotForExecutionForm?.pickOrderId && selectedLotForExecutionForm?.itemId) { |
|
|
|
try { |
|
|
|
await updateHandledBy(selectedLotForExecutionForm.pickOrderId, selectedLotForExecutionForm.itemId); |
|
|
|
console.log(`✅ [ISSUE FORM] Handler updated for itemId ${selectedLotForExecutionForm.itemId}`); |
|
|
|
} catch (error) { |
|
|
|
console.error(`❌ [ISSUE FORM] Error updating handler (non-critical):`, error); |
|
|
|
} |
|
|
|
} |
|
|
|
console.log("Pick execution form submitted:", data); |
|
|
|
const issueData = { |
|
|
|
...data, |
|
|
|
@@ -2357,12 +2403,12 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
<Stack direction="row" spacing={1} alignItems="center"> |
|
|
|
<Button |
|
|
|
variant="contained" |
|
|
|
onClick={() => { |
|
|
|
onClick={async () => { |
|
|
|
const lotKey = `${lot.pickOrderLineId}-${lot.lotId}`; |
|
|
|
const submitQty = lot.requiredQty || lot.pickOrderLineRequiredQty; |
|
|
|
handlePickQtyChange(lotKey, submitQty); |
|
|
|
handleSubmitPickQtyWithQty(lot, submitQty); |
|
|
|
updateHandledBy(lot.pickOrderId, lot.itemId); |
|
|
|
|
|
|
|
await handleSubmitPickQtyWithQty(lot, submitQty); |
|
|
|
}} |
|
|
|
disabled={ |
|
|
|
(lot.lotAvailability === 'expired' || |
|
|
|
@@ -2403,7 +2449,17 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => { |
|
|
|
<Button |
|
|
|
variant="outlined" |
|
|
|
size="small" |
|
|
|
onClick={() => handleSubmitPickQtyWithQty(lot, lot.requiredQty || lot.pickOrderLineRequiredQty || 0)} |
|
|
|
onClick={async () => { |
|
|
|
// ✅ 更新 handler 后再提交 |
|
|
|
if (currentUserId && lot.pickOrderId && lot.itemId) { |
|
|
|
try { |
|
|
|
await updateHandledBy(lot.pickOrderId, lot.itemId); |
|
|
|
} catch (error) { |
|
|
|
console.error("❌ Error updating handler (non-critical):", error); |
|
|
|
} |
|
|
|
} |
|
|
|
await handleSubmitPickQtyWithQty(lot, lot.requiredQty || lot.pickOrderLineRequiredQty || 0); |
|
|
|
}} |
|
|
|
disabled={lot.stockOutLineStatus === 'completed'} |
|
|
|
sx={{ fontSize: '0.7rem', py: 0.5, minHeight: '28px', minWidth: '90px' }} |
|
|
|
> |
|
|
|
|