| @@ -299,7 +299,8 @@ export async function fetchDoSearch( | |||
| estArrStartDate: string, | |||
| estArrEndDate: string, | |||
| pageNum?: number, | |||
| pageSize?: number | |||
| pageSize?: number, | |||
| truckLanceCode?: string | |||
| ): Promise<DoSearchLiteResponse> { | |||
| // 构建请求体 | |||
| const requestBody: any = { | |||
| @@ -307,6 +308,7 @@ export async function fetchDoSearch( | |||
| shopName: shopName || null, | |||
| status: status || null, | |||
| estimatedArrivalDate: estArrStartDate || null, // 使用单个日期字段 | |||
| truckLanceCode: truckLanceCode || null, | |||
| pageNum: pageNum || 1, | |||
| pageSize: pageSize || 10, | |||
| }; | |||
| @@ -436,7 +438,8 @@ export async function fetchAllDoSearch( | |||
| code: string, | |||
| shopName: string, | |||
| status: string, | |||
| estArrStartDate: string | |||
| estArrStartDate: string, | |||
| truckLanceCode?: string // 添加这个参数 | |||
| ): Promise<DoSearchAll[]> { | |||
| // 使用一个很大的 pageSize 来获取所有匹配的记录 | |||
| const requestBody: any = { | |||
| @@ -444,6 +447,7 @@ export async function fetchAllDoSearch( | |||
| shopName: shopName || null, | |||
| status: status || null, | |||
| estimatedArrivalDate: estArrStartDate || null, | |||
| truckLanceCode: truckLanceCode || null, // 添加这个字段 | |||
| pageNum: 1, | |||
| pageSize: 10000, // 使用一个很大的值来获取所有记录 | |||
| }; | |||
| @@ -886,7 +886,7 @@ export const updateSecondQrScanStatus = cache(async (pickOrderId: number, itemId | |||
| export const submitSecondScanQuantity = cache(async ( | |||
| pickOrderId: number, | |||
| itemId: number, | |||
| data: { qty: number; isMissing?: boolean; isBad?: boolean; reason?: string } | |||
| data: { qty: number; isMissing?: boolean; isBad?: boolean; reason?: string; userId?: number } | |||
| ) => { | |||
| return serverFetchJson<any>( | |||
| `${BASE_API_URL}/jo/second-scan-submit/${pickOrderId}/${itemId}`, | |||
| @@ -39,7 +39,7 @@ type Props = { | |||
| searchQuery?: Record<string, any>; | |||
| onDeliveryOrderSearch: () => void; | |||
| }; | |||
| type SearchBoxInputs = Record<"code" | "status" | "estimatedArrivalDate" | "orderDate" | "supplierName" | "shopName" | "deliveryOrderLines" | "codeTo" | "statusTo" | "estimatedArrivalDateTo" | "orderDateTo" | "supplierNameTo" | "shopNameTo" | "deliveryOrderLinesTo" , string>; | |||
| type SearchBoxInputs = Record<"code" | "status" | "estimatedArrivalDate" | "orderDate" | "supplierName" | "shopName" | "deliveryOrderLines" | "truckLanceCode" | "codeTo" | "statusTo" | "estimatedArrivalDateTo" | "orderDateTo" | "supplierNameTo" | "shopNameTo" | "deliveryOrderLinesTo" | "truckLanceCodeTo", string>; | |||
| type SearchParamNames = keyof SearchBoxInputs; | |||
| // put all this into a new component | |||
| @@ -87,13 +87,15 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||
| supplierName: "", | |||
| shopName: "", | |||
| deliveryOrderLines: "", | |||
| truckLanceCode: "", // 添加这个字段 | |||
| codeTo: "", | |||
| statusTo: "", | |||
| estimatedArrivalDateTo: "", | |||
| orderDateTo: "", | |||
| supplierNameTo: "", | |||
| shopNameTo: "", | |||
| deliveryOrderLinesTo: "" | |||
| deliveryOrderLinesTo: "", | |||
| truckLanceCodeTo: "" // 这个字段已经存在,但需要确保在类型定义中 | |||
| }); | |||
| const [hasSearched, setHasSearched] = useState(false); | |||
| @@ -112,6 +114,7 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||
| () => [ | |||
| { label: t("Code"), paramName: "code", type: "text" }, | |||
| { label: t("Shop Name"), paramName: "shopName", type: "text" }, | |||
| { label: t("Truck Lance Code"), paramName: "truckLanceCode", type: "text" }, | |||
| { | |||
| label: t("Estimated Arrival"), | |||
| paramName: "estimatedArrivalDate", | |||
| @@ -199,6 +202,11 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||
| headerName: t("Supplier Name"), | |||
| flex: 1, | |||
| }, | |||
| { | |||
| field: "truckLanceCode", | |||
| headerName: t("Truck Lance Code"), | |||
| flex: 1, | |||
| }, | |||
| { | |||
| field: "orderDate", | |||
| headerName: t("Order Date"), | |||
| @@ -244,51 +252,52 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||
| ); | |||
| //SEARCH FUNCTION | |||
| const handleSearch = useCallback(async (query: SearchBoxInputs) => { | |||
| try { | |||
| setCurrentSearchParams(query); | |||
| const handleSearch = useCallback(async (query: SearchBoxInputs) => { | |||
| try { | |||
| setCurrentSearchParams(query); | |||
| let estArrStartDate = query.estimatedArrivalDate; | |||
| const time = "T00:00:00"; | |||
| if(estArrStartDate != ""){ | |||
| estArrStartDate = query.estimatedArrivalDate + time; | |||
| } | |||
| let status = ""; | |||
| if(query.status == "All"){ | |||
| status = ""; | |||
| } | |||
| else{ | |||
| status = query.status; | |||
| } | |||
| // 调用新的 API,传入分页参数 | |||
| const response = await fetchDoSearch( | |||
| query.code || "", | |||
| query.shopName || "", | |||
| status, | |||
| "", // orderStartDate - 不再使用 | |||
| "", // orderEndDate - 不再使用 | |||
| estArrStartDate, | |||
| "", // estArrEndDate - 不再使用 | |||
| pagingController.pageNum, // 传入当前页码 | |||
| pagingController.pageSize // 传入每页大小 | |||
| ); | |||
| let estArrStartDate = query.estimatedArrivalDate; | |||
| const time = "T00:00:00"; | |||
| setSearchAllDos(response.records); | |||
| setTotalCount(response.total); // 设置总记录数 | |||
| setHasSearched(true); | |||
| setHasResults(response.records.length > 0); | |||
| } catch (error) { | |||
| console.error("Error: ", error); | |||
| setSearchAllDos([]); | |||
| setTotalCount(0); | |||
| setHasSearched(true); | |||
| setHasResults(false); | |||
| if(estArrStartDate != ""){ | |||
| estArrStartDate = query.estimatedArrivalDate + time; | |||
| } | |||
| let status = ""; | |||
| if(query.status == "All"){ | |||
| status = ""; | |||
| } | |||
| else{ | |||
| status = query.status; | |||
| } | |||
| }, [pagingController]); | |||
| // 调用新的 API,传入分页参数和 truckLanceCode | |||
| const response = await fetchDoSearch( | |||
| query.code || "", | |||
| query.shopName || "", | |||
| status, | |||
| "", // orderStartDate - 不再使用 | |||
| "", // orderEndDate - 不再使用 | |||
| estArrStartDate, | |||
| "", // estArrEndDate - 不再使用 | |||
| pagingController.pageNum, // 传入当前页码 | |||
| pagingController.pageSize, // 传入每页大小 | |||
| query.truckLanceCode || "" // 添加 truckLanceCode 参数 | |||
| ); | |||
| setSearchAllDos(response.records); | |||
| setTotalCount(response.total); // 设置总记录数 | |||
| setHasSearched(true); | |||
| setHasResults(response.records.length > 0); | |||
| } catch (error) { | |||
| console.error("Error: ", error); | |||
| setSearchAllDos([]); | |||
| setTotalCount(0); | |||
| setHasSearched(true); | |||
| setHasResults(false); | |||
| } | |||
| }, [pagingController]); | |||
| useEffect(() => { | |||
| if (typeof window !== 'undefined') { | |||
| @@ -372,7 +381,8 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||
| estArrStartDate, | |||
| "", | |||
| newPagingController.pageNum, | |||
| newPagingController.pageSize | |||
| newPagingController.pageSize, | |||
| currentSearchParams.truckLanceCode || "" // 添加这个参数 | |||
| ); | |||
| setSearchAllDos(response.records); | |||
| @@ -420,7 +430,8 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||
| estArrStartDate, | |||
| "", | |||
| 1, // 重置到第一页 | |||
| newPageSize | |||
| newPageSize, | |||
| currentSearchParams.truckLanceCode || "" // 添加这个参数 | |||
| ); | |||
| setSearchAllDos(response.records); | |||
| @@ -468,7 +479,8 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||
| currentSearchParams.code || "", | |||
| currentSearchParams.shopName || "", | |||
| status, | |||
| estArrStartDate | |||
| estArrStartDate, | |||
| currentSearchParams.truckLanceCode || "" | |||
| ); | |||
| Swal.close(); | |||
| @@ -35,7 +35,7 @@ import { PrinterCombo } from "@/app/api/settings/printer"; | |||
| import JobPickExecutionsecondscan from "../Jodetail/JobPickExecutionsecondscan"; | |||
| interface ProductProcessListProps { | |||
| onSelectProcess: (jobOrderId: number|undefined, productProcessId: number|undefined) => void; | |||
| onSelectMatchingStock: (jobOrderId: number|undefined, productProcessId: number|undefined) => void; | |||
| onSelectMatchingStock: (jobOrderId: number|undefined, productProcessId: number|undefined,pickOrderId: number|undefined) => void; | |||
| printerCombo: PrinterCombo[]; | |||
| } | |||
| @@ -76,7 +76,7 @@ const ProductProcessList: React.FC<ProductProcessListProps> = ({ onSelectProcess | |||
| // 分配成功后,导航到 second scan 页面 | |||
| if (onSelectMatchingStock && jobOrderId) { | |||
| onSelectMatchingStock(jobOrderId, productProcessId); | |||
| onSelectMatchingStock(jobOrderId, productProcessId,pickOrderId); | |||
| } else { | |||
| alert(t("Assignment successful")); | |||
| } | |||
| @@ -41,6 +41,7 @@ const ProductionProcessPage: React.FC<ProductionProcessPageProps> = ({ printerCo | |||
| const [selectedMatchingStock, setSelectedMatchingStock] = useState<{ | |||
| jobOrderId: number; | |||
| productProcessId: number; | |||
| pickOrderId: number; | |||
| } | null>(null); | |||
| const [tabIndex, setTabIndex] = useState(0); | |||
| const { data: session } = useSession() as { data: SessionWithTokens | null }; | |||
| @@ -97,8 +98,11 @@ const ProductionProcessPage: React.FC<ProductionProcessPageProps> = ({ printerCo | |||
| if (selectedMatchingStock) { | |||
| return ( | |||
| <JobPickExecutionsecondscan | |||
| filterArgs={{ jobOrderId: selectedMatchingStock.jobOrderId }} | |||
| <JobPickExecutionsecondscan | |||
| filterArgs={{ | |||
| jobOrderId: selectedMatchingStock.jobOrderId, | |||
| pickOrderId: selectedMatchingStock.pickOrderId, | |||
| }} | |||
| onBack={handleBackFromSecondScan} | |||
| /> | |||
| ); | |||
| @@ -181,10 +185,11 @@ const ProductionProcessPage: React.FC<ProductionProcessPageProps> = ({ printerCo | |||
| setSelectedProcessId(id); | |||
| } | |||
| }} | |||
| onSelectMatchingStock={(jobOrderId, productProcessId) => { | |||
| onSelectMatchingStock={(jobOrderId, productProcessId,pickOrderId) => { | |||
| setSelectedMatchingStock({ | |||
| jobOrderId: jobOrderId || 0, | |||
| productProcessId: productProcessId || 0 | |||
| productProcessId: productProcessId || 0 , | |||
| pickOrderId: pickOrderId || 0 | |||
| }); | |||
| }} | |||
| /> | |||
| @@ -615,7 +615,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro | |||
| <TableRow sx={{ bgcolor: 'warning.50' }}> | |||
| <TableCell> | |||
| <Typography fontWeight={500} color="warning.dark">{t("Defect")}</Typography> | |||
| <Typography fontWeight={500} color="warning.dark">{t("Defect")}{t("(1)")}</Typography> | |||
| </TableCell> | |||
| <TableCell> | |||
| <Typography>{lineDetail.defectQty}</Typography> | |||
| @@ -629,7 +629,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro | |||
| </TableRow> | |||
| <TableRow sx={{ bgcolor: 'warning.50' }}> | |||
| <TableCell> | |||
| <Typography fontWeight={500} color="warning.dark">{t("Defect")}{t("(3)")}</Typography> | |||
| <Typography fontWeight={500} color="warning.dark">{t("Defect")}{t("(2)")}</Typography> | |||
| </TableCell> | |||
| <TableCell> | |||
| <Typography>{lineDetail.defectQty2}</Typography> | |||
| @@ -643,7 +643,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro | |||
| </TableRow> | |||
| <TableRow sx={{ bgcolor: 'warning.50' }}> | |||
| <TableCell> | |||
| <Typography fontWeight={500} color="warning.dark">{t("Defect")}{t("(2)")}</Typography> | |||
| <Typography fontWeight={500} color="warning.dark">{t("Defect")}{t("(3)")}</Typography> | |||
| </TableCell> | |||
| <TableCell> | |||
| <Typography>{lineDetail.defectQty3}</Typography> | |||
| @@ -37,7 +37,7 @@ const SearchPage: React.FC<Props> = ({ dataList: initialDataList }) => { | |||
| const [loading, setLoading] = useState(false); | |||
| const [filterArgs, setFilterArgs] = useState<Record<string, any>>({}); | |||
| const isInitialMount = useRef(true); | |||
| const [searchTrigger, setSearchTrigger] = useState(0); | |||
| // 添加分页状态 | |||
| const [page, setPage] = useState(0); | |||
| const [pageSize, setPageSize] = useState<number | string>(10); | |||
| @@ -214,22 +214,21 @@ const newPageFetch = useCallback( | |||
| return; | |||
| } | |||
| // 检查是否真的变化了 | |||
| const pagingChanged = | |||
| prevPagingControllerRef.current.pageNum !== pagingController.pageNum || | |||
| prevPagingControllerRef.current.pageSize !== pagingController.pageSize; | |||
| const filterChanged = JSON.stringify(prevFilterArgsRef.current) !== JSON.stringify(filterArgs); | |||
| // 如果是第一次有效搜索,或者条件/分页发生变化,则调用 API | |||
| if (!hasSearchedRef.current || pagingChanged || filterChanged) { | |||
| newPageFetch(pagingController, filterArgs); | |||
| prevPagingControllerRef.current = pagingController; | |||
| prevFilterArgsRef.current = filterArgs; | |||
| hasSearchedRef.current = true; | |||
| isInitialMount.current = false; | |||
| } | |||
| }, [newPageFetch, pagingController, filterArgs]); | |||
| prevPagingControllerRef.current.pageNum !== pagingController.pageNum || | |||
| prevPagingControllerRef.current.pageSize !== pagingController.pageSize; | |||
| const filterChanged = JSON.stringify(prevFilterArgsRef.current) !== JSON.stringify(filterArgs); | |||
| // 如果是第一次有效搜索,或者条件/分页发生变化,或者有新的搜索触发,则调用 API | |||
| if (!hasSearchedRef.current || pagingChanged || filterChanged || searchTrigger > 0) { | |||
| newPageFetch(pagingController, filterArgs); | |||
| prevPagingControllerRef.current = pagingController; | |||
| prevFilterArgsRef.current = filterArgs; | |||
| hasSearchedRef.current = true; | |||
| isInitialMount.current = false; | |||
| } | |||
| }, [newPageFetch, pagingController, filterArgs, searchTrigger]); | |||
| // 分页处理函数 | |||
| const handleChangePage = useCallback((event: unknown, newPage: number) => { | |||
| @@ -377,7 +376,7 @@ const newPageFetch = useCallback( | |||
| startDate: startDate || undefined, | |||
| endDate: endDate || undefined, | |||
| }); | |||
| setSearchTrigger(prev => prev + 1); | |||
| // 重置分页 | |||
| setPage(0); | |||
| setPagingController(prev => ({ ...prev, pageNum: 1 })); | |||
| @@ -180,17 +180,18 @@ const ApproverStockTake: React.FC<ApproverStockTakeProps> = ({ | |||
| let finalBadQty: number; | |||
| if (selection === "first") { | |||
| if (!detail.firstStockTakeQty || detail.firstStockTakeQty === 0) { | |||
| if (detail.firstStockTakeQty == null) { | |||
| onSnackbar(t("First QTY is not available"), "error"); | |||
| return; | |||
| } | |||
| finalQty = detail.firstStockTakeQty; | |||
| finalBadQty = detail.firstBadQty || 0; | |||
| } else if (selection === "second") { | |||
| if (!detail.secondStockTakeQty || detail.secondStockTakeQty === 0) { | |||
| if (detail.secondStockTakeQty == null) { | |||
| onSnackbar(t("Second QTY is not available"), "error"); | |||
| return; | |||
| } | |||
| finalQty = detail.secondStockTakeQty; | |||
| finalBadQty = detail.secondBadQty || 0; | |||
| } else { | |||
| @@ -11,7 +11,7 @@ | |||
| "Status": "來貨狀態", | |||
| "Order Date From": "訂單日期", | |||
| "Delivery Order Code": "送貨訂單編號", | |||
| "Truck Lance Code": "車線號碼", | |||
| "Select Remark": "選擇備註", | |||
| "Confirm Assignment": "確認分配", | |||
| "Required Date": "所需日期", | |||
| @@ -30,6 +30,8 @@ | |||
| "ReStockTake": "重新盤點", | |||
| "Stock Taker": "盤點員", | |||
| "Total Item Number": "貨品數量", | |||
| "Please enter QTY and Bad QTY": "請輸入盤點數量和不良數量", | |||
| "Available QTY cannot be negative": "可用數量不能為負數", | |||
| "Start Time": "開始時間", | |||
| "Difference": "差異", | |||
| "stockTaking": "盤點中", | |||