From b7b3f637f936588b5481e2a462d9f7801bc6a640 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Mon, 15 Sep 2025 15:04:25 +0800 Subject: [PATCH] update --- src/app/api/pickOrder/actions.ts | 16 +- .../FinishedGoodSearch/GoodPickExecution.tsx | 148 ++++++++++-------- src/components/PickOrderSearch/LotTable.tsx | 3 +- 3 files changed, 98 insertions(+), 69 deletions(-) diff --git a/src/app/api/pickOrder/actions.ts b/src/app/api/pickOrder/actions.ts index 54050b9..c3d302a 100644 --- a/src/app/api/pickOrder/actions.ts +++ b/src/app/api/pickOrder/actions.ts @@ -244,7 +244,21 @@ export interface PickOrderCompletionResponse { }>; }; } - +export interface UpdateSuggestedLotLineIdRequest { + newLotLineId: number; +} +export const updateSuggestedLotLineId = async (suggestedPickLotId: number, newLotLineId: number) => { + const response = await serverFetchJson>( + `${BASE_API_URL}/suggestedPickLot/update-suggested-lot/${suggestedPickLotId}`, + { + method: "POST", + body: JSON.stringify({ newLotLineId }), + headers: { "Content-Type": "application/json" }, + }, + ); + revalidateTag("pickorder"); + return response; +}; export const autoAssignAndReleasePickOrder = async (userId: number): Promise => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/auto-assign-release/${userId}`, diff --git a/src/components/FinishedGoodSearch/GoodPickExecution.tsx b/src/components/FinishedGoodSearch/GoodPickExecution.tsx index c38a5c6..cc7c541 100644 --- a/src/components/FinishedGoodSearch/GoodPickExecution.tsx +++ b/src/components/FinishedGoodSearch/GoodPickExecution.tsx @@ -59,7 +59,8 @@ const QrCodeModal: React.FC<{ onClose: () => void; lot: any | null; onQrCodeSubmit: (lotNo: string) => void; -}> = ({ open, onClose, lot, onQrCodeSubmit }) => { + combinedLotData: any[]; // ✅ Add this prop +}> = ({ open, onClose, lot, onQrCodeSubmit, combinedLotData }) => { const { t } = useTranslation("pickOrder"); const { values: qrValues, isScanning, startScan, stopScan, resetScan } = useQrCodeScannerContext(); const [manualInput, setManualInput] = useState(''); @@ -398,11 +399,15 @@ const PickExecution: React.FC = ({ filterArgs }) => { // const handleAutoAssignAndRelease = useCallback(async () => { ... }); // 删除这个函数 // ✅ Handle QR code submission for matched lot (external scanning) - const handleQrCodeSubmit = useCallback(async (lotNo: string) => { + // ✅ Handle QR code submission for matched lot (external scanning) + const handleQrCodeSubmit = useCallback(async (lotNo: string) => { console.log(`✅ Processing QR Code for lot: ${lotNo}`); - console.log(`🔍 Available lots:`, combinedLotData.map(lot => lot.lotNo)); - const matchingLots = combinedLotData.filter(lot => + // ✅ Use current data without refreshing to avoid infinite loop + const currentLotData = combinedLotData; + console.log(`🔍 Available lots:`, currentLotData.map(lot => lot.lotNo)); + + const matchingLots = currentLotData.filter(lot => lot.lotNo === lotNo || lot.lotNo?.toLowerCase() === lotNo.toLowerCase() ); @@ -430,7 +435,7 @@ const PickExecution: React.FC = ({ filterArgs }) => { existsCount++; } else { const stockOutLineData: CreateStockOutLine = { - consoCode: matchingLot.pickOrderConsoCode, // ✅ Use pickOrderConsoCode instead of pickOrderCode + consoCode: matchingLot.pickOrderConsoCode, pickOrderLineId: matchingLot.pickOrderLineId, inventoryLotLineId: matchingLot.lotId, qty: 0.0 @@ -447,40 +452,56 @@ const PickExecution: React.FC = ({ filterArgs }) => { console.log(`✅ Stock out line created successfully for line ${matchingLot.pickOrderLineId}`); successCount++; } else { - console.error(`❌ Unexpected response for line ${matchingLot.pickOrderLineId}:`, result); + console.error(`❌ Failed to create stock out line for line ${matchingLot.pickOrderLineId}:`, result); errorCount++; } } - - const lotKey = `${matchingLot.pickOrderLineId}-${matchingLot.lotId}`; - setPickQtyData(prev => ({ - ...prev, - [lotKey]: matchingLot.requiredQty - })); } + // ✅ Always refresh data after processing (success or failure) + console.log("🔄 Refreshing data after QR code processing..."); + await fetchAllCombinedLotData(); + if (successCount > 0 || existsCount > 0) { + console.log(`✅ QR Code processing completed: ${successCount} created, ${existsCount} already existed`); setQrScanSuccess(true); - setQrScanError(false); - console.log(`✅ QR Code processing completed: ${successCount} created, ${existsCount} already existed, ${errorCount} errors`); + setQrScanInput(''); // Clear input after successful processing + + // ✅ Clear success state after a delay + setTimeout(() => { + setQrScanSuccess(false); + }, 2000); } else { + console.error(`❌ QR Code processing failed: ${errorCount} errors`); setQrScanError(true); setQrScanSuccess(false); - console.error(`❌ All operations failed for lot ${lotNo}`); - return; + + // ✅ Clear error state after a delay + setTimeout(() => { + setQrScanError(false); + }, 3000); } - - await fetchAllCombinedLotData(); - setQrScanInput(''); - - console.log("Stock out line process completed successfully!"); } catch (error) { - console.error("Error creating stock out line:", error); + console.error("❌ Error processing QR code:", error); setQrScanError(true); setQrScanSuccess(false); + + // ✅ Still refresh data even on error + await fetchAllCombinedLotData(); + + // ✅ Clear error state after a delay + setTimeout(() => { + setQrScanError(false); + }, 3000); } }, [combinedLotData, fetchAllCombinedLotData]); + const handleManualInputSubmit = useCallback(() => { + if (qrScanInput.trim() !== '') { + handleQrCodeSubmit(qrScanInput.trim()); + } + }, [qrScanInput, handleQrCodeSubmit]); + // ✅ Handle QR code submission from modal (internal scanning) const handleQrCodeSubmitFromModal = useCallback(async (lotNo: string) => { if (selectedLotForQr && selectedLotForQr.lotNo === lotNo) { @@ -523,22 +544,44 @@ const PickExecution: React.FC = ({ filterArgs }) => { } }, [selectedLotForQr, fetchAllCombinedLotData]); - // ✅ External QR scanning - process QR codes from outside the page + // ✅ Outside QR scanning - process QR codes from outside the page automatically useEffect(() => { if (qrValues.length > 0 && combinedLotData.length > 0) { const latestQr = qrValues[qrValues.length - 1]; - const qrContent = latestQr.replace(/[{}]/g, ''); - setQrScanInput(qrContent); - handleQrCodeSubmit(qrContent); + // Extract lot number from QR code + let lotNo = ''; + try { + const qrData = JSON.parse(latestQr); + if (qrData.stockInLineId && qrData.itemId) { + // For JSON QR codes, we need to fetch the lot number + fetchStockInLineInfo(qrData.stockInLineId) + .then((stockInLineInfo) => { + console.log("Outside QR scan - Stock in line info:", stockInLineInfo); + const extractedLotNo = stockInLineInfo.lotNo; + if (extractedLotNo) { + console.log(`Outside QR scan detected (JSON): ${extractedLotNo}`); + handleQrCodeSubmit(extractedLotNo); + } + }) + .catch((error) => { + console.error("Outside QR scan - Error fetching stock in line info:", error); + }); + return; // Exit early for JSON QR codes + } + } catch (error) { + // Not JSON format, treat as direct lot number + lotNo = latestQr.replace(/[{}]/g, ''); + } + + // For direct lot number QR codes + if (lotNo) { + console.log(`Outside QR scan detected (direct): ${lotNo}`); + handleQrCodeSubmit(lotNo); + } } }, [qrValues, combinedLotData, handleQrCodeSubmit]); - const handleManualInputSubmit = useCallback(() => { - if (qrScanInput.trim() !== '') { - handleQrCodeSubmit(qrScanInput.trim()); - } - }, [qrScanInput, handleQrCodeSubmit]); const handlePickQtyChange = useCallback((lotKey: string, value: number | string) => { if (value === '' || value === null || value === undefined) { @@ -836,41 +879,8 @@ const PickExecution: React.FC = ({ filterArgs }) => { {t("All Pick Order Lots")} - {/* ✅ External QR scan input - for scanning from outside the page */} - - setQrScanInput(e.target.value)} - onKeyPress={(e) => { - if (e.key === 'Enter') { - handleManualInputSubmit(); - } - }} - error={qrScanError} - color={qrScanSuccess ? 'success' : undefined} - helperText={ - qrScanError - ? t("Lot number not found") - : qrScanSuccess - ? t("Lot processed successfully") - : t("Enter lot number or scan QR code") - } - placeholder={t("Enter lot number...")} - sx={{ minWidth: '250px' }} - InputProps={{ - startAdornment: , - }} - /> - - + + @@ -923,7 +933,9 @@ const PickExecution: React.FC = ({ filterArgs }) => { }} > {lot.lotNo} + + {/* {lot.lotAvailability !== 'available' && ( ({lot.lotAvailability === 'expired' ? 'Expired' : @@ -931,7 +943,8 @@ const PickExecution: React.FC = ({ filterArgs }) => { lot.lotAvailability === 'rejected' ? 'Rejected' : 'Unavailable'}) - )} + + )*/} {lot.pickOrderTargetDate} @@ -1091,6 +1104,7 @@ const PickExecution: React.FC = ({ filterArgs }) => { resetScan(); }} lot={selectedLotForQr} + combinedLotData={combinedLotData} // ✅ Add this prop onQrCodeSubmit={handleQrCodeSubmitFromModal} /> diff --git a/src/components/PickOrderSearch/LotTable.tsx b/src/components/PickOrderSearch/LotTable.tsx index d0e1d29..cd41138 100644 --- a/src/components/PickOrderSearch/LotTable.tsx +++ b/src/components/PickOrderSearch/LotTable.tsx @@ -620,6 +620,7 @@ const LotTable: React.FC = ({ > {lot.lotNo} + {/* {lot.lotAvailability !== 'available' && ( ({lot.lotAvailability === 'expired' ? 'Expired' : @@ -627,7 +628,7 @@ const LotTable: React.FC = ({ lot.lotAvailability === 'rejected' ? 'Rejected' : // ✅ 添加 rejected 显示 'Unavailable'}) - )} + )} */} {lot.expiryDate}