"use client"; import { Autocomplete, Box, Button, CircularProgress, FormControl, Grid, Paper, Stack, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Checkbox, FormControlLabel, Select, MenuItem, InputLabel, TablePagination, } from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { ByItemsSummary, ConsoPickOrderResult, PickOrderLine, PickOrderResult, } from "@/app/api/pickOrder"; import { useRouter } from "next/navigation"; import { GridInputRowSelectionModel } from "@mui/x-data-grid"; import { fetchConsoDetail, fetchConsoPickOrderClient, releasePickOrder, ReleasePickOrderInputs, fetchPickOrderDetails, fetchAllPickOrderDetails, GetPickOrderInfoResponse, GetPickOrderLineInfo, createStockOutLine, updateStockOutLineStatus, resuggestPickOrder, } from "@/app/api/pickOrder/actions"; import { EditNote } from "@mui/icons-material"; import { fetchNameList, NameList } from "@/app/api/user/actions"; import { FormProvider, SubmitErrorHandler, SubmitHandler, useForm, } from "react-hook-form"; import { pickOrderStatusMap } from "@/app/utils/formatUtil"; import { QcItemWithChecks } from "@/app/api/qc"; import { fetchQcItemCheck, fetchPickOrderQcResult } from "@/app/api/qc/actions"; import { PurchaseQcResult } from "@/app/api/po/actions"; import PickQcStockInModalVer2 from "./PickQcStockInModalVer3"; import { fetchPickOrderLineLotDetails, PickOrderLotDetailResponse } from "@/app/api/pickOrder/actions"; import SearchResults, { Column } from "../SearchResults/SearchResults"; import { defaultPagingController } from "../SearchResults/SearchResults"; import SearchBox, { Criterion } from "../SearchBox"; import dayjs from "dayjs"; import { dummyQCData } from "../PoDetail/dummyQcTemplate"; import { CreateStockOutLine } from "@/app/api/pickOrder/actions"; import LotTable from './LotTable'; import { updateInventoryLotLineStatus, updateInventoryStatus, updateInventoryLotLineQuantities } from "@/app/api/inventory/actions"; interface Props { filterArgs: Record; } interface LotPickData { id: number; lotId: number; lotNo: string; expiryDate: string; location: string; stockUnit: string; availableQty: number; requiredQty: number; actualPickQty: number; lotStatus: string; lotAvailability: 'available' | 'insufficient_stock' | 'expired' | 'status_unavailable'; stockOutLineId?: number; stockOutLineStatus?: string; stockOutLineQty?: number; } interface PickQtyData { [lineId: number]: { [lotId: number]: number; }; } const PickExecution: React.FC = ({ filterArgs }) => { const { t } = useTranslation("pickOrder"); const router = useRouter(); const [filteredPickOrders, setFilteredPickOrders] = useState( [] as ConsoPickOrderResult[], ); const [isLoading, setIsLoading] = useState(false); const [selectedConsoCode, setSelectedConsoCode] = useState(); const [revertIds, setRevertIds] = useState([]); const [totalCount, setTotalCount] = useState(); const [usernameList, setUsernameList] = useState([]); const [byPickOrderRows, setByPickOrderRows] = useState< Omit[] | undefined >(undefined); const [byItemsRows, setByItemsRows] = useState( undefined, ); const [disableRelease, setDisableRelease] = useState(true); const [selectedRowId, setSelectedRowId] = useState(null); const [pickOrderDetails, setPickOrderDetails] = useState(null); const [detailLoading, setDetailLoading] = useState(false); const [pickQtyData, setPickQtyData] = useState({}); const [lotData, setLotData] = useState([]); const [qcItems, setQcItems] = useState([]); const [qcModalOpen, setQcModalOpen] = useState(false); const [selectedItemForQc, setSelectedItemForQc] = useState(null); const [selectedLotForQc, setSelectedLotForQc] = useState(null); // ✅ Add lot selection state variables const [selectedLotRowId, setSelectedLotRowId] = useState(null); const [selectedLotId, setSelectedLotId] = useState(null); // 新增:分页控制器 const [mainTablePagingController, setMainTablePagingController] = useState({ pageNum: 0, pageSize: 10, }); const [lotTablePagingController, setLotTablePagingController] = useState({ pageNum: 0, pageSize: 10, }); // Add missing search state variables const [searchQuery, setSearchQuery] = useState>({}); const [originalPickOrderData, setOriginalPickOrderData] = useState(null); const formProps = useForm(); const errors = formProps.formState.errors; const onDetailClick = useCallback( (pickOrder: any) => { console.log(pickOrder); const status = pickOrder.status; if (pickOrderStatusMap[status] >= 3) { router.push(`/pickOrder/detail?consoCode=${pickOrder.consoCode}`); } else { setSelectedConsoCode(pickOrder.consoCode); } }, [router], ); const fetchNewPageConsoPickOrder = useCallback( async ( pagingController: Record, filterArgs: Record, ) => { setIsLoading(true); const params = { ...pagingController, ...filterArgs, }; const res = await fetchConsoPickOrderClient(params); if (res) { console.log(res); setFilteredPickOrders(res.records); setTotalCount(res.total); } setIsLoading(false); }, [], ); useEffect(() => { fetchNewPageConsoPickOrder({ limit: 10, offset: 0 }, filterArgs); }, [fetchNewPageConsoPickOrder, filterArgs]); const handleUpdateStockOutLineStatus = useCallback(async ( stockOutLineId: number, status: string, qty?: number ) => { try { const updateData = { id: stockOutLineId, status: status, qty: qty }; console.log("Updating stock out line status:", updateData); const result = await updateStockOutLineStatus(updateData); if (result) { console.log("Stock out line status updated successfully:", result); // Refresh lot data to show updated status if (selectedRowId) { handleRowSelect(selectedRowId); } } } catch (error) { console.error("Error updating stock out line status:", error); } }, [selectedRowId]); const isReleasable = useCallback((itemList: ByItemsSummary[]): boolean => { let isReleasable = true; for (const item of itemList) { isReleasable = item.requiredQty >= item.availableQty; if (!isReleasable) return isReleasable; } return isReleasable; }, []); const fetchConso = useCallback( async (consoCode: string) => { const res = await fetchConsoDetail(consoCode); const nameListRes = await fetchNameList(); if (res) { console.log(res); setByPickOrderRows(res.pickOrders); setByItemsRows(res.items); setDisableRelease(isReleasable(res.items)); } else { console.log("error"); console.log(res); } if (nameListRes) { console.log(nameListRes); setUsernameList(nameListRes); } }, [isReleasable], ); const handleFetchAllPickOrderDetails = useCallback(async () => { setDetailLoading(true); try { const data = await fetchAllPickOrderDetails(); setPickOrderDetails(data); setOriginalPickOrderData(data); // Store original data for filtering console.log("All Pick Order Details:", data); const initialPickQtyData: PickQtyData = {}; data.pickOrders.forEach((pickOrder: any) => { pickOrder.pickOrderLines.forEach((line: any) => { initialPickQtyData[line.id] = {}; }); }); setPickQtyData(initialPickQtyData); } catch (error) { console.error("Error fetching all pick order details:", error); } finally { setDetailLoading(false); } }, []); useEffect(() => { handleFetchAllPickOrderDetails(); }, [handleFetchAllPickOrderDetails]); const onChange = useCallback( (event: React.SyntheticEvent, newValue: NameList) => { console.log(newValue); formProps.setValue("assignTo", newValue.id); }, [formProps], ); const onSubmit = useCallback>( async (data, event) => { console.log(data); try { const res = await releasePickOrder(data); console.log(res); if (res.consoCode.length > 0) { console.log(res); router.push(`/pickOrder/detail?consoCode=${res.consoCode}`); } else { console.log(res); } } catch (error) { console.log(error); } }, [router], ); const onSubmitError = useCallback>( (errors) => {}, [], ); const handleConsolidate_revert = useCallback(() => { console.log(revertIds); }, [revertIds]); useEffect(() => { if (selectedConsoCode) { fetchConso(selectedConsoCode); formProps.setValue("consoCode", selectedConsoCode); } }, [selectedConsoCode, fetchConso, formProps]); const handlePickQtyChange = useCallback((lineId: number, lotId: number, value: number | string) => { console.log("Changing pick qty:", { lineId, lotId, value }); // ✅ Handle both number and string values const numericValue = typeof value === 'string' ? (value === '' ? 0 : parseInt(value, 10)) : value; setPickQtyData(prev => { const newData = { ...prev, [lineId]: { ...prev[lineId], [lotId]: numericValue } }; console.log("New pick qty data:", newData); return newData; }); }, []); const handleSubmitPickQty = useCallback(async (lineId: number, lotId: number) => { const qty = pickQtyData[lineId]?.[lotId] || 0; console.log(`提交拣货数量: Line ${lineId}, Lot ${lotId}, Qty ${qty}`); // ✅ Find the stock out line for this lot const selectedLot = lotData.find(lot => lot.lotId === lotId); if (!selectedLot?.stockOutLineId) { return; } try { // ✅ Only two statuses: partially_completed or completed let newStatus = 'partially_completed'; // Default status if (qty >= selectedLot.requiredQty) { newStatus = 'completed'; // Full quantity picked } // If qty < requiredQty, stays as 'partially_completed' // ✅ Function 1: Update stock out line with new status and quantity try { // ✅ Function 1: Update stock out line with new status and quantity const stockOutLineUpdate = await updateStockOutLineStatus({ id: selectedLot.stockOutLineId, status: newStatus, qty: qty }); console.log("✅ Stock out line updated:", stockOutLineUpdate); } catch (error) { console.error("❌ Error updating stock out line:", error); return; // Stop execution if this fails } // ✅ Function 2: Update inventory lot line (balance hold_qty and out_qty) if (qty > 0) { const inventoryLotLineUpdate = await updateInventoryLotLineQuantities({ inventoryLotLineId: lotId, qty: qty, status: 'available', operation: 'pick' }); console.log("Inventory lot line updated:", inventoryLotLineUpdate); } // ✅ Function 3: Handle inventory table onhold if needed if (newStatus === 'completed') { // All required quantity picked - might need to update inventory status // Note: We'll handle inventory update in a separate function or after selectedRow is available console.log("Completed status - inventory update needed but selectedRow not available yet"); } console.log("All updates completed successfully"); // ✅ Refresh lot data to show updated quantities if (selectedRowId) { await handleRowSelect(selectedRowId, true); // Note: We'll handle refresh after the function is properly defined console.log("Data refresh needed but handleRowSelect not available yet"); } await handleFetchAllPickOrderDetails(); } catch (error) { console.error("Error updating pick quantity:", error); } }, [pickQtyData, lotData, selectedRowId]); const getTotalPickedQty = useCallback((lineId: number) => { const lineData = pickQtyData[lineId]; if (!lineData) return 0; return Object.values(lineData).reduce((sum, qty) => sum + qty, 0); }, [pickQtyData]); const handleQcCheck = useCallback(async (line: GetPickOrderLineInfo, pickOrderCode: string) => { // ✅ Get the selected lot for QC if (!selectedLotId) { return; } const selectedLot = lotData.find(lot => lot.lotId === selectedLotId); if (!selectedLot) { //alert("Selected lot not found in lot data"); return; } // ✅ Check if stock out line exists if (!selectedLot.stockOutLineId) { //alert("Please create a stock out line first before performing QC check"); return; } setSelectedLotForQc(selectedLot); // ✅ ALWAYS use dummy data for consistent behavior const transformedDummyData = dummyQCData.map(item => ({ id: item.id, code: item.code, name: item.name, itemId: line.itemId, lowerLimit: undefined, upperLimit: undefined, description: item.qcDescription, // ✅ Always reset QC result properties to undefined for fresh start qcPassed: undefined, failQty: undefined, remarks: undefined })); setQcItems(transformedDummyData as QcItemWithChecks[]); // ✅ Get existing QC results if any (for display purposes only) let qcResult: any[] = []; try { const rawQcResult = await fetchPickOrderQcResult(line.id); qcResult = rawQcResult.map((result: any) => ({ ...result, isPassed: result.isPassed || false })); } catch (error) { // No existing QC result found - this is normal } setSelectedItemForQc({ ...line, pickOrderCode, qcResult }); setQcModalOpen(true); }, [lotData, selectedLotId, setQcItems]); const handleCloseQcModal = useCallback(() => { console.log("Closing QC modal"); setQcModalOpen(false); setSelectedItemForQc(null); }, []); const handleSetItemDetail = useCallback((item: any) => { setSelectedItemForQc(item); }, []); // 新增:处理分页变化 const handleMainTablePageChange = useCallback((event: unknown, newPage: number) => { setMainTablePagingController(prev => ({ ...prev, pageNum: newPage, })); }, []); const handleMainTablePageSizeChange = useCallback((event: React.ChangeEvent) => { const newPageSize = parseInt(event.target.value, 10); setMainTablePagingController({ pageNum: 0, pageSize: newPageSize, }); }, []); const handleLotTablePageChange = useCallback((event: unknown, newPage: number) => { setLotTablePagingController(prev => ({ ...prev, pageNum: newPage, })); }, []); const handleLotTablePageSizeChange = useCallback((event: React.ChangeEvent) => { const newPageSize = parseInt(event.target.value, 10); setLotTablePagingController({ pageNum: 0, pageSize: newPageSize, }); }, []); // ✅ Fix lot selection logic const handleLotSelection = useCallback((uniqueLotId: string, lotId: number) => { // If clicking the same lot, unselect it if (selectedLotRowId === uniqueLotId) { setSelectedLotRowId(null); setSelectedLotId(null); } else { // Select the new lot setSelectedLotRowId(uniqueLotId); setSelectedLotId(lotId); } }, [selectedLotRowId]); // ✅ Add function to handle row selection that resets lot selection const handleRowSelect = useCallback(async (lineId: number, preserveLotSelection: boolean = false) => { setSelectedRowId(lineId); // ✅ Only reset lot selection if not preserving if (!preserveLotSelection) { setSelectedLotRowId(null); setSelectedLotId(null); } try { const lotDetails = await fetchPickOrderLineLotDetails(lineId); console.log("Lot details from API:", lotDetails); const realLotData: LotPickData[] = lotDetails.map((lot: any) => ({ id: lot.id, // This should be the unique row ID for the table lotId: lot.lotId, // This is the inventory lot line ID lotNo: lot.lotNo, expiryDate: lot.expiryDate ? new Date(lot.expiryDate).toLocaleDateString() : 'N/A', location: lot.location, stockUnit: lot.stockUnit, availableQty: lot.availableQty, requiredQty: lot.requiredQty, actualPickQty: lot.actualPickQty || 0, lotStatus: lot.lotStatus, lotAvailability: lot.lotAvailability, stockOutLineId: lot.stockOutLineId, stockOutLineStatus: lot.stockOutLineStatus, stockOutLineQty: lot.stockOutLineQty })); setLotData(realLotData); } catch (error) { console.error("Error fetching lot details:", error); setLotData([]); } }, []); const prepareMainTableData = useMemo(() => { if (!pickOrderDetails) return []; return pickOrderDetails.pickOrders.flatMap((pickOrder) => pickOrder.pickOrderLines.map((line) => { // 修复:处理 availableQty 可能为 null 的情况 const availableQty = line.availableQty ?? 0; const balanceToPick = availableQty - line.requiredQty; // ✅ 使用 dayjs 进行一致的日期格式化 const formattedTargetDate = pickOrder.targetDate ? dayjs(pickOrder.targetDate).format('YYYY-MM-DD') : 'N/A'; return { ...line, pickOrderCode: pickOrder.code, targetDate: formattedTargetDate, // ✅ 使用 dayjs 格式化的日期 balanceToPick: balanceToPick, pickedQty: line.pickedQty, // 确保 availableQty 不为 null availableQty: availableQty, }; }) ); }, [pickOrderDetails]); const prepareLotTableData = useMemo(() => { return lotData.map((lot) => ({ ...lot, id: lot.lotId, })); }, [lotData]); // 新增:分页数据 const paginatedMainTableData = useMemo(() => { const startIndex = mainTablePagingController.pageNum * mainTablePagingController.pageSize; const endIndex = startIndex + mainTablePagingController.pageSize; return prepareMainTableData.slice(startIndex, endIndex); }, [prepareMainTableData, mainTablePagingController]); const paginatedLotTableData = useMemo(() => { const startIndex = lotTablePagingController.pageNum * lotTablePagingController.pageSize; const endIndex = startIndex + lotTablePagingController.pageSize; return prepareLotTableData.slice(startIndex, endIndex); }, [prepareLotTableData, lotTablePagingController]); const selectedRow = useMemo(() => { if (!selectedRowId || !pickOrderDetails) return null; for (const pickOrder of pickOrderDetails.pickOrders) { const foundLine = pickOrder.pickOrderLines.find(line => line.id === selectedRowId); if (foundLine) { return { ...foundLine, pickOrderCode: pickOrder.code }; } } return null; }, [selectedRowId, pickOrderDetails]); const handleInventoryUpdate = useCallback(async (itemId: number, lotId: number, qty: number) => { try { const inventoryUpdate = await updateInventoryStatus({ itemId: itemId, lotId: lotId, status: 'reserved', qty: qty }); console.log("Inventory status updated:", inventoryUpdate); } catch (error) { console.error("Error updating inventory status:", error); } }, []); // ✅ Add this function after handleRowSelect is defined const handleDataRefresh = useCallback(async () => { if (selectedRowId) { try { await handleRowSelect(selectedRowId, true); } catch (error) { console.error("Error refreshing data:", error); } } }, [selectedRowId, handleRowSelect]); const handleInsufficientStock = useCallback(async () => { console.log("Insufficient stock - testing resuggest API"); if (!selectedRowId || !pickOrderDetails) { // alert("Please select a pick order line first"); return; } // Find the pick order ID from the selected row let pickOrderId: number | null = null; for (const pickOrder of pickOrderDetails.pickOrders) { const foundLine = pickOrder.pickOrderLines.find(line => line.id === selectedRowId); if (foundLine) { pickOrderId = pickOrder.id; break; } } if (!pickOrderId) { // alert("Could not find pick order ID for selected line"); return; } try { console.log(`Calling resuggest API for pick order ID: ${pickOrderId}`); // Call the resuggest API const result = await resuggestPickOrder(pickOrderId); console.log("Resuggest API result:", result); if (result.code === "SUCCESS") { //alert(`✅ Resuggest successful!\n\nMessage: ${result.message}\n\nRemoved: ${result.message?.includes('Removed') ? 'Yes' : 'No'}\nCreated: ${result.message?.includes('created') ? 'Yes' : 'No'}`); // Refresh the lot data to show the new suggestions if (selectedRowId) { await handleRowSelect(selectedRowId); } // Also refresh the main pick order details await handleFetchAllPickOrderDetails(); } else { //alert(`❌ Resuggest failed!\n\nError: ${result.message}`); } } catch (error) { console.error("Error calling resuggest API:", error); //alert(`❌ Error calling resuggest API:\n\n${error instanceof Error ? error.message : 'Unknown error'}`); } }, [selectedRowId, pickOrderDetails, handleRowSelect, handleFetchAllPickOrderDetails]); // Add this function (around line 350) const hasSelectedLots = useCallback((lineId: number) => { return selectedLotRowId !== null; }, [selectedLotRowId]); // Add state for showing input body const [showInputBody, setShowInputBody] = useState(false); const [selectedLotForInput, setSelectedLotForInput] = useState(null); // Add function to handle lot selection for input body display const handleLotSelectForInput = useCallback((lot: LotPickData) => { setSelectedLotForInput(lot); setShowInputBody(true); }, []); // Add function to generate input body const generateInputBody = useCallback((): CreateStockOutLine | null => { if (!selectedLotForInput || !selectedRowId || !selectedRow || !pickOrderDetails?.consoCode) { return null; } return { consoCode: pickOrderDetails.consoCode, pickOrderLineId: selectedRowId, inventoryLotLineId: selectedLotForInput.lotId, qty: 0.0 }; }, [selectedLotForInput, selectedRowId, selectedRow, pickOrderDetails?.consoCode]); // Add function to handle create stock out line const handleCreateStockOutLine = useCallback(async (inventoryLotLineId: number) => { if (!selectedRowId || !pickOrderDetails?.consoCode) { console.error("Missing required data for creating stock out line."); return; } try { // ✅ Store current lot selection before refresh const currentSelectedLotRowId = selectedLotRowId; const currentSelectedLotId = selectedLotId; const stockOutLineData: CreateStockOutLine = { consoCode: pickOrderDetails.consoCode, pickOrderLineId: selectedRowId, inventoryLotLineId: inventoryLotLineId, qty: 0.0 }; console.log("=== STOCK OUT LINE CREATION DEBUG ==="); console.log("Input Body:", JSON.stringify(stockOutLineData, null, 2)); // ✅ Use the correct API function const result = await createStockOutLine(stockOutLineData); console.log("Stock Out Line created:", result); if (result) { console.log("Stock out line created successfully:", result); // ✅ Auto-refresh data after successful creation console.log("🔄 Refreshing data after stock out line creation..."); try { // ✅ Refresh lot data for the selected row (maintains selection) if (selectedRowId) { await handleRowSelect(selectedRowId, true); // ✅ Preserve lot selection } // ✅ Refresh main pick order details await handleFetchAllPickOrderDetails(); console.log("✅ Data refresh completed - lot selection maintained!"); } catch (refreshError) { console.error("❌ Error refreshing data:", refreshError); } setShowInputBody(false); // Hide preview after successful creation } else { console.error("Failed to create stock out line: No response"); } } catch (error) { console.error("Error creating stock out line:", error); } }, [selectedRowId, pickOrderDetails?.consoCode, handleRowSelect, handleFetchAllPickOrderDetails, selectedLotRowId, selectedLotId]); // ✅ New function to refresh data while preserving lot selection const handleRefreshDataPreserveSelection = useCallback(async () => { if (!selectedRowId) return; // ✅ Store current lot selection const currentSelectedLotRowId = selectedLotRowId; const currentSelectedLotId = selectedLotId; try { // ✅ Refresh lot data await handleRowSelect(selectedRowId, true); // ✅ Preserve selection // ✅ Refresh main pick order details await handleFetchAllPickOrderDetails(); // ✅ Restore lot selection setSelectedLotRowId(currentSelectedLotRowId); setSelectedLotId(currentSelectedLotId); console.log("✅ Data refreshed with selection preserved"); } catch (error) { console.error("❌ Error refreshing data:", error); } }, [selectedRowId, selectedLotRowId, selectedLotId, handleRowSelect, handleFetchAllPickOrderDetails]); // 自定义主表格组件 const CustomMainTable = () => { return ( <> {t("Selected")} {t("Pick Order Code")} {t("Item Code")} {t("Item Name")} {t("Order Quantity")} {t("Current Stock")} {t("Qty Already Picked")} {t("Stock Unit")} {t("Target Date")} {paginatedMainTableData.length === 0 ? ( {t("No data available")} ) : ( paginatedMainTableData.map((line) => { // 修复:处理 availableQty 可能为 null 的情况,并确保负值显示为 0 const availableQty = line.availableQty ?? 0; const balanceToPick = Math.max(0, availableQty - line.requiredQty); // 确保不为负数 const totalPickedQty = getTotalPickedQty(line.id); const actualPickedQty = line.pickedQty ?? 0; return ( *": { borderBottom: "unset" }, color: "black", backgroundColor: selectedRowId === line.id ? "action.selected" : "inherit", cursor: "pointer", "&:hover": { backgroundColor: "action.hover", }, }} > { if (e.target.checked) { handleRowSelect(line.id); } else { setSelectedRowId(null); setLotData([]); } }} onClick={(e) => e.stopPropagation()} /> {line.pickOrderCode} {line.itemCode} {line.itemName} {line.requiredQty} = line.requiredQty ? 'success.main' : 'error.main', }}> {availableQty.toLocaleString()} {/* 添加千位分隔符 */} {actualPickedQty} {line.uomDesc} {line.targetDate} ); }) )}
`${from}-${to} of ${count !== -1 ? count : `more than ${to}`}` } /> ); }; // Add search criteria const searchCriteria: Criterion[] = useMemo( () => [ { label: t("Item Code"), paramName: "itemCode", type: "text", }, { label: t("Pick Order Code"), paramName: "pickOrderCode", type: "text", }, { label: t("Item Name"), paramName: "itemName", type: "text", }, { label: t("Target Date From"), label2: t("Target Date To"), paramName: "targetDate", type: "dateRange", }, ], [t], ); // Add search handler const handleSearch = useCallback((query: Record) => { setSearchQuery({ ...query }); console.log("Search query:", query); if (!originalPickOrderData) return; const filtered = originalPickOrderData.pickOrders.filter((pickOrder) => { // Check if any line in this pick order matches the search criteria return pickOrder.pickOrderLines.some((line) => { const itemCodeMatch = !query.itemCode || line.itemCode?.toLowerCase().includes((query.itemCode || "").toLowerCase()); const itemNameMatch = !query.itemName || line.itemName?.toLowerCase().includes((query.itemName || "").toLowerCase()); const pickOrderCodeMatch = !query.pickOrderCode || pickOrder.code?.toLowerCase().includes((query.pickOrderCode || "").toLowerCase()); return itemCodeMatch && itemNameMatch && pickOrderCodeMatch ; }); }); // Create filtered data structure const filteredData: GetPickOrderInfoResponse = { ...originalPickOrderData, pickOrders: filtered }; setPickOrderDetails(filteredData); console.log("Filtered pick orders count:", filtered.length); }, [originalPickOrderData, t]); // Add reset handler const handleReset = useCallback(() => { setSearchQuery({}); if (originalPickOrderData) { setPickOrderDetails(originalPickOrderData); } }, [originalPickOrderData]); // Add this to debug the lot data useEffect(() => { console.log("Lot data:", lotData); console.log("Pick Qty Data:", pickQtyData); }, [lotData, pickQtyData]); return ( {/* Search Box */} {/* 主表格 */} {t("Pick Order Details")} {detailLoading ? ( ) : pickOrderDetails ? ( ) : ( 正在載入數據... )} {/* 批次表格 - 放在主表格下方 */} {selectedRow && ( Item lot to be Pick: {selectedRow.pickOrderCode} - {selectedRow.itemName} {/* 检查是否有可用的批次数据 */} {lotData.length > 0 ? ( ) : ( {selectedRow.availableQty === null || selectedRow.availableQty === 0 ? t("No available stock for this item") : t("No lot details available for this item") } {selectedRow.availableQty === null || selectedRow.availableQty === 0 ? t("Current stock is insufficient or unavailable") : t("Please check inventory status") } )} {/* Action buttons below the lot table */} )} {/* Action Buttons */} {selectedRow && ( )} {/* QC Modal */} {selectedItemForQc && qcModalOpen && ( { if (selectedRowId) { handleRowSelect(selectedRowId); } }} lotData={lotData} /> )} ); }; export default PickExecution;