| @@ -279,38 +279,50 @@ const PickOrderSearch: React.FC<Props> = ({ pickOrders }) => { | |||||
| overflow: 'auto' // Single scrollbar for the whole page | overflow: 'auto' // Single scrollbar for the whole page | ||||
| }}> | }}> | ||||
| {/* Header section */} | {/* Header section */} | ||||
| <Box sx={{ | |||||
| p: 2, | |||||
| borderBottom: '1px solid #e0e0e0' | |||||
| }}> | |||||
| <Stack rowGap={2}> | |||||
| <Grid container alignItems="center"> | |||||
| <Grid item xs={8}> | |||||
| <Typography variant="h4" marginInlineEnd={2}> | |||||
| {t("Finished Good Order")} | |||||
| </Typography> | |||||
| </Grid> | |||||
| <Grid item xs={4} display="flex" justifyContent="end" alignItems="center"> | |||||
| <Stack direction="row" spacing={1}> | |||||
| <Button | |||||
| variant="contained" | |||||
| onClick={() => handleAssignByStore("2/F")} | |||||
| disabled={isAssigning} | |||||
| > | |||||
| {isAssigning ? t("Assigning pick order...") : t("Pick Execution 2/F")} | |||||
| </Button> | |||||
| <Button | |||||
| variant="contained" | |||||
| onClick={() => handleAssignByStore("4/F")} | |||||
| disabled={isAssigning} | |||||
| > | |||||
| {isAssigning ? t("Assigning pick order...") : t("Pick Execution 4/F")} | |||||
| </Button> | |||||
| </Stack> | |||||
| <Box sx={{ p: 2, borderBottom: '1px solid #e0e0e0' }}> | |||||
| <Stack rowGap={2}> | |||||
| <Grid container alignItems="center"> | |||||
| <Grid item xs={8}> | |||||
| <Box mb={2}> | |||||
| <Typography variant="h4" marginInlineEnd={2}> | |||||
| {t("Finished Good Order")} | |||||
| </Typography> | |||||
| </Box> | |||||
| </Grid> | </Grid> | ||||
| </Grid> | |||||
| {/* First 4 buttons aligned left */} | |||||
| <Grid item xs={6}> | |||||
| <Stack direction="row" spacing={1}> | |||||
| <Button variant="contained">{t("Print Draft")}</Button> | |||||
| <Button variant="contained">{t("Print Pick Order and DN Label")}</Button> | |||||
| <Button variant="contained">{t("Print Pick Order")}</Button> | |||||
| <Button variant="contained">{t("Print DN Label")}</Button> | |||||
| </Stack> | </Stack> | ||||
| </Box> | |||||
| </Grid> | |||||
| {/* Last 2 buttons aligned right */} | |||||
| <Grid item xs={6} display="flex" justifyContent="flex-end"> | |||||
| <Stack direction="row" spacing={1}> | |||||
| <Button | |||||
| variant="contained" | |||||
| onClick={() => handleAssignByStore("2/F")} | |||||
| disabled={isAssigning} | |||||
| > | |||||
| {isAssigning ? t("Assigning pick order...") : t("Pick Execution 2/F")} | |||||
| </Button> | |||||
| <Button | |||||
| variant="contained" | |||||
| onClick={() => handleAssignByStore("4/F")} | |||||
| disabled={isAssigning} | |||||
| > | |||||
| {isAssigning ? t("Assigning pick order...") : t("Pick Execution 4/F")} | |||||
| </Button> | |||||
| </Stack> | |||||
| </Grid> | |||||
| </Grid> | |||||
| </Stack> | |||||
| </Box> | |||||
| {/* Tabs section - ✅ Move the click handler here */} | {/* Tabs section - ✅ Move the click handler here */} | ||||
| <Box sx={{ | <Box sx={{ | ||||
| @@ -514,8 +514,18 @@ const [isConfirmingLot, setIsConfirmingLot] = useState(false); | |||||
| qty: 0 | qty: 0 | ||||
| }); | }); | ||||
| console.log(`Update stock out line result for line ${matchingLot.pickOrderLineId}:`, stockOutLineUpdate); | console.log(`Update stock out line result for line ${matchingLot.pickOrderLineId}:`, stockOutLineUpdate); | ||||
| if (stockOutLineUpdate && stockOutLineUpdate.code === "SUCCESS") { | |||||
| // Treat multiple backend shapes as success (type-safe via any) | |||||
| const r: any = stockOutLineUpdate as any; | |||||
| const updateOk = | |||||
| r?.code === 'SUCCESS' || | |||||
| typeof r?.id === 'number' || | |||||
| r?.type === 'checked' || | |||||
| r?.status === 'checked' || | |||||
| typeof r?.entity?.id === 'number' || | |||||
| r?.entity?.status === 'checked'; | |||||
| if (updateOk) { | |||||
| successCount++; | successCount++; | ||||
| } else { | } else { | ||||
| errorCount++; | errorCount++; | ||||
| @@ -570,8 +580,11 @@ const [isConfirmingLot, setIsConfirmingLot] = useState(false); | |||||
| if (successCount > 0) { | if (successCount > 0) { | ||||
| console.log(`✅ QR Code processing completed: ${successCount} updated/created`); | console.log(`✅ QR Code processing completed: ${successCount} updated/created`); | ||||
| setQrScanSuccess(true); | setQrScanSuccess(true); | ||||
| setQrScanError(false); | |||||
| setQrScanInput(''); // Clear input after successful processing | setQrScanInput(''); // Clear input after successful processing | ||||
| setIsManualScanning(false); | |||||
| stopScan(); | |||||
| resetScan(); | |||||
| // ✅ Clear success state after a delay | // ✅ Clear success state after a delay | ||||
| //setTimeout(() => { | //setTimeout(() => { | ||||
| @@ -778,7 +791,9 @@ const [isConfirmingLot, setIsConfirmingLot] = useState(false); | |||||
| qty: selectedLotForQr.stockOutLineQty || 0 | qty: selectedLotForQr.stockOutLineQty || 0 | ||||
| }); | }); | ||||
| console.log("Stock out line updated successfully!"); | console.log("Stock out line updated successfully!"); | ||||
| setQrScanSuccess(true); | |||||
| setQrScanError(false); | |||||
| // Close modal | // Close modal | ||||
| setQrModalOpen(false); | setQrModalOpen(false); | ||||
| setSelectedLotForQr(null); | setSelectedLotForQr(null); | ||||
| @@ -1276,7 +1291,7 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe | |||||
| </Box> | </Box> | ||||
| </Box> | </Box> | ||||
| {qrScanError && ( | |||||
| {qrScanError && !qrScanSuccess && ( | |||||
| <Alert severity="error" sx={{ mb: 2 }}> | <Alert severity="error" sx={{ mb: 2 }}> | ||||
| {t("QR code does not match any item in current orders.")} | {t("QR code does not match any item in current orders.")} | ||||
| </Alert> | </Alert> | ||||
| @@ -1444,6 +1459,7 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe | |||||
| </Table> | </Table> | ||||
| </TableContainer> | </TableContainer> | ||||
| {/* ✅ Status Messages Display - Move here, outside the table */} | {/* ✅ Status Messages Display - Move here, outside the table */} | ||||
| {/* | |||||
| {paginatedData.length > 0 && ( | {paginatedData.length > 0 && ( | ||||
| <Box sx={{ mt: 2, p: 2, backgroundColor: 'grey.50', borderRadius: 1 }}> | <Box sx={{ mt: 2, p: 2, backgroundColor: 'grey.50', borderRadius: 1 }}> | ||||
| {paginatedData.map((lot, index) => ( | {paginatedData.map((lot, index) => ( | ||||
| @@ -1455,6 +1471,7 @@ const handleSubmitPickQtyWithQty = useCallback(async (lot: any, submitQty: numbe | |||||
| ))} | ))} | ||||
| </Box> | </Box> | ||||
| )} | )} | ||||
| */} | |||||
| <TablePagination | <TablePagination | ||||
| component="div" | component="div" | ||||
| count={combinedLotData.length} | count={combinedLotData.length} | ||||
| @@ -94,9 +94,7 @@ const LotConfirmationModal: React.FC<LotConfirmationModalProps> = ({ | |||||
| <Alert severity="info"> | <Alert severity="info"> | ||||
| {t("If you proceed, the system will:")} | {t("If you proceed, the system will:")} | ||||
| <ul style={{ margin: '8px 0 0 16px' }}> | <ul style={{ margin: '8px 0 0 16px' }}> | ||||
| <li>{t("Update the stock out line to use the scanned lot")}</li> | |||||
| <li>{t("Put the original suggested lot on hold")}</li> | |||||
| <li>{t("Update inventory lot line for the new lot")}</li> | |||||
| <li>{t("Update your suggested lot to the this scanned lot")}</li> | |||||
| </ul> | </ul> | ||||
| </Alert> | </Alert> | ||||
| </Stack> | </Stack> | ||||
| @@ -40,6 +40,6 @@ | |||||
| "Edit": "編輯", | "Edit": "編輯", | ||||
| "Delete": "刪除", | "Delete": "刪除", | ||||
| "Release": "放單", | "Release": "放單", | ||||
| "Back": "返回" | |||||
| "Back": "返回", | |||||
| "Edit Delivery Order Detail": "編輯交貨單詳情" | |||||
| } | } | ||||
| @@ -262,7 +262,20 @@ | |||||
| "Stop QR Scan":"停止QR掃描", | "Stop QR Scan":"停止QR掃描", | ||||
| "Scanning...":"掃描中...", | "Scanning...":"掃描中...", | ||||
| "Print DN/Label":"列印送貨單/標籤", | "Print DN/Label":"列印送貨單/標籤", | ||||
| "Store ID":"店鋪編號", | |||||
| "QR code does not match any item in current orders.":"QR 碼不符合當前訂單中的任何貨品。" | |||||
| "Store ID":"儲存編號", | |||||
| "QR code does not match any item in current orders.":"QR 碼不符合當前訂單中的任何貨品。", | |||||
| "Lot Number Mismatch":"批次號碼不符", | |||||
| "The scanned item matches the expected item, but the lot number is different. Do you want to proceed with this different lot?":"掃描的貨品與預期的貨品相同,但批次號碼不同。您是否要繼續使用不同的批次?", | |||||
| "Expected Lot:":"預期批次:", | |||||
| "Scanned Lot:":"掃描批次:", | |||||
| "Confirm":"確認", | |||||
| "Update your suggested lot to the this scanned lot":"更新您的建議批次為此掃描的批次", | |||||
| "Print Draft":"列印草稿", | |||||
| "Print Pick Order and DN Label":"列印提料單和送貨單標貼", | |||||
| "Print Pick Order":"列印提料單", | |||||
| "Print DN Label":"列印送貨單標貼" | |||||
| } | } | ||||