|
|
@@ -458,7 +458,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
|
|
|
|
|
|
// ✅ Use current data without refreshing to avoid infinite loop |
|
|
// ✅ Use current data without refreshing to avoid infinite loop |
|
|
const currentLotData = combinedLotData; |
|
|
const currentLotData = combinedLotData; |
|
|
console.log(`�� Available lots:`, currentLotData.map(lot => lot.lotNo)); |
|
|
|
|
|
|
|
|
console.log(` Available lots:`, currentLotData.map(lot => lot.lotNo)); |
|
|
|
|
|
|
|
|
const matchingLots = currentLotData.filter(lot => |
|
|
const matchingLots = currentLotData.filter(lot => |
|
|
lot.lotNo === lotNo || |
|
|
lot.lotNo === lotNo || |
|
|
@@ -477,18 +477,17 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
let successCount = 0; |
|
|
let successCount = 0; |
|
|
let existsCount = 0; |
|
|
|
|
|
let errorCount = 0; |
|
|
let errorCount = 0; |
|
|
|
|
|
|
|
|
for (const matchingLot of matchingLots) { |
|
|
for (const matchingLot of matchingLots) { |
|
|
console.log(`🔄 Processing pick order line ${matchingLot.pickOrderLineId} for lot ${lotNo}`); |
|
|
console.log(`🔄 Processing pick order line ${matchingLot.pickOrderLineId} for lot ${lotNo}`); |
|
|
|
|
|
|
|
|
if (matchingLot.stockOutLineId) { |
|
|
if (matchingLot.stockOutLineId) { |
|
|
// ✅ FIXED: Use matchingLot.stockOutLineId instead of selectedLotForQr.stockOutLineId |
|
|
|
|
|
|
|
|
// ✅ FIXED: Only update status to 'checked', keep qty at 0 |
|
|
const stockOutLineUpdate = await updateStockOutLineStatus({ |
|
|
const stockOutLineUpdate = await updateStockOutLineStatus({ |
|
|
id: matchingLot.stockOutLineId, // ✅ Use the correct ID |
|
|
|
|
|
|
|
|
id: matchingLot.stockOutLineId, |
|
|
status: 'checked', |
|
|
status: 'checked', |
|
|
qty: matchingLot.stockOutLineQty || matchingLot.requiredQty || 0 |
|
|
|
|
|
|
|
|
qty: 0 // ✅ Keep qty at 0 until user actually submits |
|
|
}); |
|
|
}); |
|
|
console.log(`Update stock out line result for line ${matchingLot.pickOrderLineId}:`, stockOutLineUpdate); |
|
|
console.log(`Update stock out line result for line ${matchingLot.pickOrderLineId}:`, stockOutLineUpdate); |
|
|
|
|
|
|
|
|
@@ -500,12 +499,12 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
errorCount++; |
|
|
errorCount++; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
// ✅ If no stock out line exists, create one |
|
|
|
|
|
|
|
|
// ✅ If no stock out line exists, create one with qty = 0 |
|
|
const createStockOutLineData = { |
|
|
const createStockOutLineData = { |
|
|
consoCode: matchingLot.pickOrderConsoCode, |
|
|
consoCode: matchingLot.pickOrderConsoCode, |
|
|
pickOrderLineId: matchingLot.pickOrderLineId, |
|
|
pickOrderLineId: matchingLot.pickOrderLineId, |
|
|
inventoryLotLineId: matchingLot.lotId, |
|
|
inventoryLotLineId: matchingLot.lotId, |
|
|
qty: matchingLot.requiredQty || 0 |
|
|
|
|
|
|
|
|
qty: 0 // ✅ Create with qty = 0 |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const createResult = await createStockOutLine(createStockOutLineData); |
|
|
const createResult = await createStockOutLine(createStockOutLineData); |
|
|
@@ -719,13 +718,19 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
|
|
|
// ✅ FIXED: Calculate cumulative quantity correctly |
|
|
const currentActualPickQty = lot.actualPickQty || 0; |
|
|
const currentActualPickQty = lot.actualPickQty || 0; |
|
|
const cumulativeQty = currentActualPickQty + newQty; |
|
|
const cumulativeQty = currentActualPickQty + newQty; |
|
|
|
|
|
|
|
|
|
|
|
// ✅ FIXED: Determine status based on cumulative quantity vs required quantity |
|
|
let newStatus = 'partially_completed'; |
|
|
let newStatus = 'partially_completed'; |
|
|
|
|
|
|
|
|
if (cumulativeQty >= lot.requiredQty) { |
|
|
if (cumulativeQty >= lot.requiredQty) { |
|
|
newStatus = 'completed'; |
|
|
newStatus = 'completed'; |
|
|
|
|
|
} else if (cumulativeQty > 0) { |
|
|
|
|
|
newStatus = 'partially_completed'; |
|
|
|
|
|
} else { |
|
|
|
|
|
newStatus = 'checked'; // QR scanned but no quantity submitted yet |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
console.log(`=== PICK QUANTITY SUBMISSION DEBUG ===`); |
|
|
console.log(`=== PICK QUANTITY SUBMISSION DEBUG ===`); |
|
|
@@ -740,7 +745,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
await updateStockOutLineStatus({ |
|
|
await updateStockOutLineStatus({ |
|
|
id: lot.stockOutLineId, |
|
|
id: lot.stockOutLineId, |
|
|
status: newStatus, |
|
|
status: newStatus, |
|
|
qty: cumulativeQty |
|
|
|
|
|
|
|
|
qty: cumulativeQty // ✅ Use cumulative quantity |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
if (newQty > 0) { |
|
|
if (newQty > 0) { |
|
|
@@ -752,12 +757,11 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// ✅ FIXED: Use the proper API function instead of direct fetch |
|
|
|
|
|
|
|
|
// ✅ Check if pick order is completed when lot status becomes 'completed' |
|
|
if (newStatus === 'completed' && lot.pickOrderConsoCode) { |
|
|
if (newStatus === 'completed' && lot.pickOrderConsoCode) { |
|
|
console.log(`✅ Lot ${lot.lotNo} completed, checking if pick order ${lot.pickOrderConsoCode} is complete...`); |
|
|
console.log(`✅ Lot ${lot.lotNo} completed, checking if pick order ${lot.pickOrderConsoCode} is complete...`); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
// ✅ Use the imported API function instead of direct fetch |
|
|
|
|
|
const completionResponse = await checkAndCompletePickOrderByConsoCode(lot.pickOrderConsoCode); |
|
|
const completionResponse = await checkAndCompletePickOrderByConsoCode(lot.pickOrderConsoCode); |
|
|
console.log(`✅ Pick order completion check result:`, completionResponse); |
|
|
console.log(`✅ Pick order completion check result:`, completionResponse); |
|
|
|
|
|
|
|
|
@@ -937,7 +941,83 @@ const paginatedData = useMemo(() => { |
|
|
const endIndex = startIndex + paginationController.pageSize; |
|
|
const endIndex = startIndex + paginationController.pageSize; |
|
|
return combinedLotData.slice(startIndex, endIndex); // ✅ No sorting needed |
|
|
return combinedLotData.slice(startIndex, endIndex); // ✅ No sorting needed |
|
|
}, [combinedLotData, paginationController]); |
|
|
}, [combinedLotData, paginationController]); |
|
|
|
|
|
|
|
|
|
|
|
const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: number) => { |
|
|
|
|
|
if (!lot.stockOutLineId) { |
|
|
|
|
|
console.error("No stock out line found for this lot"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
// ✅ FIXED: Calculate cumulative quantity correctly |
|
|
|
|
|
const currentActualPickQty = lot.actualPickQty || 0; |
|
|
|
|
|
const cumulativeQty = currentActualPickQty + submitQty; |
|
|
|
|
|
|
|
|
|
|
|
// ✅ FIXED: Determine status based on cumulative quantity vs required quantity |
|
|
|
|
|
let newStatus = 'partially_completed'; |
|
|
|
|
|
|
|
|
|
|
|
if (cumulativeQty >= lot.requiredQty) { |
|
|
|
|
|
newStatus = 'completed'; |
|
|
|
|
|
} else if (cumulativeQty > 0) { |
|
|
|
|
|
newStatus = 'partially_completed'; |
|
|
|
|
|
} else { |
|
|
|
|
|
newStatus = 'checked'; // QR scanned but no quantity submitted yet |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log(`=== PICK QUANTITY SUBMISSION DEBUG ===`); |
|
|
|
|
|
console.log(`Lot: ${lot.lotNo}`); |
|
|
|
|
|
console.log(`Required Qty: ${lot.requiredQty}`); |
|
|
|
|
|
console.log(`Current Actual Pick Qty: ${currentActualPickQty}`); |
|
|
|
|
|
console.log(`New Submitted Qty: ${submitQty}`); |
|
|
|
|
|
console.log(`Cumulative Qty: ${cumulativeQty}`); |
|
|
|
|
|
console.log(`New Status: ${newStatus}`); |
|
|
|
|
|
console.log(`=====================================`); |
|
|
|
|
|
|
|
|
|
|
|
await updateStockOutLineStatus({ |
|
|
|
|
|
id: lot.stockOutLineId, |
|
|
|
|
|
status: newStatus, |
|
|
|
|
|
qty: cumulativeQty // ✅ Use cumulative quantity |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (submitQty > 0) { |
|
|
|
|
|
await updateInventoryLotLineQuantities({ |
|
|
|
|
|
inventoryLotLineId: lot.lotId, |
|
|
|
|
|
qty: submitQty, |
|
|
|
|
|
status: 'available', |
|
|
|
|
|
operation: 'pick' |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ✅ Check if pick order is completed when lot status becomes 'completed' |
|
|
|
|
|
if (newStatus === 'completed' && lot.pickOrderConsoCode) { |
|
|
|
|
|
console.log(`✅ Lot ${lot.lotNo} completed, 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("Pick quantity submitted successfully!"); |
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
checkAndAutoAssignNext(); |
|
|
|
|
|
}, 1000); |
|
|
|
|
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error("Error submitting pick quantity:", error); |
|
|
|
|
|
} |
|
|
|
|
|
}, [fetchAllCombinedLotData, checkAndAutoAssignNext]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Add these functions after line 395 |
|
|
// ✅ Add these functions after line 395 |
|
|
@@ -1117,8 +1197,10 @@ const paginatedData = useMemo(() => { |
|
|
<TableCell align="right"> |
|
|
<TableCell align="right"> |
|
|
{(() => { |
|
|
{(() => { |
|
|
const inQty = lot.inQty || 0; |
|
|
const inQty = lot.inQty || 0; |
|
|
|
|
|
const requiredQty = lot.requiredQty || 0; |
|
|
|
|
|
const actualPickQty = lot.actualPickQty || 0; |
|
|
const outQty = lot.outQty || 0; |
|
|
const outQty = lot.outQty || 0; |
|
|
const result = inQty - outQty; |
|
|
|
|
|
|
|
|
const result = requiredQty; |
|
|
return result.toLocaleString()+'('+lot.uomShortDesc+')'; |
|
|
return result.toLocaleString()+'('+lot.uomShortDesc+')'; |
|
|
})()} |
|
|
})()} |
|
|
</TableCell> |
|
|
</TableCell> |
|
|
@@ -1143,10 +1225,12 @@ const paginatedData = useMemo(() => { |
|
|
<Button |
|
|
<Button |
|
|
variant="contained" |
|
|
variant="contained" |
|
|
onClick={() => { |
|
|
onClick={() => { |
|
|
// Submit with default lot required pick qty |
|
|
|
|
|
const lotKey = `${lot.pickOrderLineId}-${lot.lotId}`; |
|
|
const lotKey = `${lot.pickOrderLineId}-${lot.lotId}`; |
|
|
handlePickQtyChange(lotKey, lot.requiredQty || lot.pickOrderLineRequiredQty); |
|
|
|
|
|
handleSubmitPickQty(lot); |
|
|
|
|
|
|
|
|
const submitQty = lot.requiredQty || lot.pickOrderLineRequiredQty; |
|
|
|
|
|
// Submit with default lot required pick qty |
|
|
|
|
|
|
|
|
|
|
|
handlePickQtyChange(lotKey, submitQty); |
|
|
|
|
|
handleSubmitPickQtyWithQty(lot, submitQty); |
|
|
}} |
|
|
}} |
|
|
disabled={ |
|
|
disabled={ |
|
|
(lot.lotAvailability === 'expired' || |
|
|
(lot.lotAvailability === 'expired' || |
|
|
|