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