| @@ -0,0 +1,91 @@ | |||||
| "use client"; | |||||
| import React, { useState } from 'react'; | |||||
| import { | |||||
| Box, | |||||
| Typography, | |||||
| FormControl, | |||||
| InputLabel, | |||||
| Select, | |||||
| MenuItem, | |||||
| Card, | |||||
| CardContent, | |||||
| Stack, | |||||
| } from '@mui/material'; | |||||
| import { useTranslation } from 'react-i18next'; | |||||
| import dayjs from 'dayjs'; | |||||
| const FGPickOrderTicketReleaseTable: React.FC = () => { | |||||
| const { t } = useTranslation("pickOrder"); | |||||
| const [selectedDate, setSelectedDate] = useState<string>("today"); | |||||
| const [selectedFloor, setSelectedFloor] = useState<string>(""); | |||||
| const getDateLabel = (offset: number) => { | |||||
| return dayjs().add(offset, 'day').format('YYYY-MM-DD'); | |||||
| }; | |||||
| return ( | |||||
| <Card sx={{ mb: 2 }}> | |||||
| <CardContent> | |||||
| {/* Title */} | |||||
| <Typography variant="h5" sx={{ mb: 3, fontWeight: 600 }}> | |||||
| Ticket Release Table | |||||
| </Typography> | |||||
| {/* Dropdown Menus */} | |||||
| <Stack direction="row" spacing={2} sx={{ mb: 3 }}> | |||||
| {/* Date Selection Dropdown */} | |||||
| <FormControl sx={{ minWidth: 250 }} size="small"> | |||||
| <InputLabel id="date-select-label">{t("Select Date")}</InputLabel> | |||||
| <Select | |||||
| labelId="date-select-label" | |||||
| id="date-select" | |||||
| value={selectedDate} | |||||
| label={t("Select Date")} | |||||
| onChange={(e) => setSelectedDate(e.target.value)} | |||||
| > | |||||
| <MenuItem value="today"> | |||||
| {t("Today")} ({getDateLabel(0)}) | |||||
| </MenuItem> | |||||
| <MenuItem value="tomorrow"> | |||||
| {t("Tomorrow")} ({getDateLabel(1)}) | |||||
| </MenuItem> | |||||
| <MenuItem value="dayAfterTomorrow"> | |||||
| {t("Day After Tomorrow")} ({getDateLabel(2)}) | |||||
| </MenuItem> | |||||
| </Select> | |||||
| </FormControl> | |||||
| {/* Floor Selection Dropdown */} | |||||
| <FormControl sx={{ minWidth: 150 }} size="small"> | |||||
| <InputLabel id="floor-select-label">{t("Floor")}</InputLabel> | |||||
| <Select | |||||
| labelId="floor-select-label" | |||||
| id="floor-select" | |||||
| value={selectedFloor} | |||||
| label={t("Floor")} | |||||
| onChange={(e) => setSelectedFloor(e.target.value)} | |||||
| displayEmpty | |||||
| > | |||||
| <MenuItem value=""> | |||||
| <em>{t("All Floors")}</em> | |||||
| </MenuItem> | |||||
| <MenuItem value="2F">2/F</MenuItem> | |||||
| <MenuItem value="4F">4/F</MenuItem> | |||||
| </Select> | |||||
| </FormControl> | |||||
| </Stack> | |||||
| {/* Table content will go here */} | |||||
| <Box sx={{ mt: 2 }}> | |||||
| <Typography variant="body2" color="text.secondary"> | |||||
| {/* Add your table component here */} | |||||
| Table content goes here... | |||||
| </Typography> | |||||
| </Box> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ); | |||||
| }; | |||||
| export default FGPickOrderTicketReleaseTable; | |||||
| @@ -38,6 +38,7 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; | |||||
| import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; | import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; | ||||
| import { DatePicker } from '@mui/x-date-pickers/DatePicker'; | import { DatePicker } from '@mui/x-date-pickers/DatePicker'; | ||||
| import dayjs, { Dayjs } from 'dayjs'; | import dayjs, { Dayjs } from 'dayjs'; | ||||
| import FGPickOrderTicketReleaseTable from "./FGPickOrderTicketReleaseTable"; | |||||
| interface Props { | interface Props { | ||||
| pickOrders: PickOrderResult[]; | pickOrders: PickOrderResult[]; | ||||
| @@ -217,228 +218,7 @@ const PickOrderSearch: React.FC<Props> = ({ pickOrders }) => { | |||||
| },[t]); | },[t]); | ||||
| const handleDN = useCallback(async () =>{ | |||||
| const askNumofCarton = await Swal.fire({ | |||||
| title: t("Enter the number of cartons: "), | |||||
| icon: "info", | |||||
| input: "number", | |||||
| inputPlaceholder: t("Number of cartons"), | |||||
| inputAttributes:{ | |||||
| min: "1", | |||||
| step: "1" | |||||
| }, | |||||
| inputValidator: (value) => { | |||||
| if(!value){ | |||||
| return t("You need to enter a number") | |||||
| } | |||||
| if(parseInt(value) < 1){ | |||||
| return t("Number must be at least 1"); | |||||
| } | |||||
| return null | |||||
| }, | |||||
| showCancelButton: true, | |||||
| confirmButtonText: t("Confirm"), | |||||
| cancelButtonText: t("Cancel"), | |||||
| confirmButtonColor: "#8dba00", | |||||
| cancelButtonColor: "#F04438", | |||||
| showLoaderOnConfirm: true, | |||||
| allowOutsideClick: () => !Swal.isLoading() | |||||
| }); | |||||
| if (askNumofCarton.isConfirmed) { | |||||
| const numOfCartons = askNumofCarton.value; | |||||
| try{ | |||||
| if (fgPickOrdersData.length === 0) { | |||||
| console.error("No FG Pick order data available"); | |||||
| return; | |||||
| } | |||||
| const currentFgOrder = fgPickOrdersData[0]; | |||||
| const printRequest = { | |||||
| printerId: 1, | |||||
| printQty: 1, | |||||
| isDraft: false, | |||||
| numOfCarton: numOfCartons, | |||||
| deliveryOrderId: currentFgOrder.deliveryOrderId, | |||||
| pickOrderId: currentFgOrder.pickOrderId | |||||
| }; | |||||
| console.log("Printing Delivery Note with request: ", printRequest); | |||||
| const response = await printDN(printRequest); | |||||
| console.log("Print Delivery Note response: ", response); | |||||
| if(response.success){ | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "success", | |||||
| text: t("Printed Successfully."), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| } else { | |||||
| console.error("Print failed: ", response.message); | |||||
| } | |||||
| } catch(error){ | |||||
| console.error("error: ", error) | |||||
| } | |||||
| } | |||||
| },[t, fgPickOrdersData]); | |||||
| const handleDNandLabel = useCallback(async () =>{ | |||||
| const askNumofCarton = await Swal.fire({ | |||||
| title: t("Enter the number of cartons: "), | |||||
| icon: "info", | |||||
| input: "number", | |||||
| inputPlaceholder: t("Number of cartons"), | |||||
| inputAttributes:{ | |||||
| min: "1", | |||||
| step: "1" | |||||
| }, | |||||
| inputValidator: (value) => { | |||||
| if(!value){ | |||||
| return t("You need to enter a number") | |||||
| } | |||||
| if(parseInt(value) < 1){ | |||||
| return t("Number must be at least 1"); | |||||
| } | |||||
| return null | |||||
| }, | |||||
| showCancelButton: true, | |||||
| confirmButtonText: t("Confirm"), | |||||
| cancelButtonText: t("Cancel"), | |||||
| confirmButtonColor: "#8dba00", | |||||
| cancelButtonColor: "#F04438", | |||||
| showLoaderOnConfirm: true, | |||||
| allowOutsideClick: () => !Swal.isLoading() | |||||
| }); | |||||
| if (askNumofCarton.isConfirmed) { | |||||
| const numOfCartons = askNumofCarton.value; | |||||
| try{ | |||||
| if (fgPickOrdersData.length === 0) { | |||||
| console.error("No FG Pick order data available"); | |||||
| return; | |||||
| } | |||||
| const currentFgOrder = fgPickOrdersData[0]; | |||||
| const printDNRequest = { | |||||
| printerId: 1, | |||||
| printQty: 1, | |||||
| isDraft: false, | |||||
| numOfCarton: numOfCartons, | |||||
| deliveryOrderId: currentFgOrder.deliveryOrderId, | |||||
| pickOrderId: currentFgOrder.pickOrderId | |||||
| }; | |||||
| const printDNLabelsRequest = { | |||||
| printerId: 1, | |||||
| printQty: 1, | |||||
| numOfCarton: numOfCartons, | |||||
| deliveryOrderId: currentFgOrder.deliveryOrderId | |||||
| }; | |||||
| console.log("Printing Labels with request: ", printDNLabelsRequest); | |||||
| console.log("Printing DN with request: ", printDNRequest); | |||||
| const LabelsResponse = await printDNLabels(printDNLabelsRequest); | |||||
| const DNResponse = await printDN(printDNRequest); | |||||
| console.log("Print Labels response: ", LabelsResponse); | |||||
| console.log("Print DN response: ", DNResponse); | |||||
| if(LabelsResponse.success && DNResponse.success){ | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "success", | |||||
| text: t("Printed Successfully."), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| } else { | |||||
| if(!LabelsResponse.success){ | |||||
| console.error("Print failed: ", LabelsResponse.message); | |||||
| } | |||||
| else{ | |||||
| console.error("Print failed: ", DNResponse.message); | |||||
| } | |||||
| } | |||||
| } catch(error){ | |||||
| console.error("error: ", error) | |||||
| } | |||||
| } | |||||
| },[t, fgPickOrdersData]); | |||||
| const handleLabel = useCallback(async () =>{ | |||||
| const askNumofCarton = await Swal.fire({ | |||||
| title: t("Enter the number of cartons: "), | |||||
| icon: "info", | |||||
| input: "number", | |||||
| inputPlaceholder: t("Number of cartons"), | |||||
| inputAttributes:{ | |||||
| min: "1", | |||||
| step: "1" | |||||
| }, | |||||
| inputValidator: (value) => { | |||||
| if(!value){ | |||||
| return t("You need to enter a number") | |||||
| } | |||||
| if(parseInt(value) < 1){ | |||||
| return t("Number must be at least 1"); | |||||
| } | |||||
| return null | |||||
| }, | |||||
| showCancelButton: true, | |||||
| confirmButtonText: t("Confirm"), | |||||
| cancelButtonText: t("Cancel"), | |||||
| confirmButtonColor: "#8dba00", | |||||
| cancelButtonColor: "#F04438", | |||||
| showLoaderOnConfirm: true, | |||||
| allowOutsideClick: () => !Swal.isLoading() | |||||
| }); | |||||
| if (askNumofCarton.isConfirmed) { | |||||
| const numOfCartons = askNumofCarton.value; | |||||
| try{ | |||||
| if (fgPickOrdersData.length === 0) { | |||||
| console.error("No FG Pick order data available"); | |||||
| return; | |||||
| } | |||||
| const currentFgOrder = fgPickOrdersData[0]; | |||||
| const printRequest = { | |||||
| printerId: 1, | |||||
| printQty: 1, | |||||
| numOfCarton: numOfCartons, | |||||
| deliveryOrderId: currentFgOrder.deliveryOrderId, | |||||
| }; | |||||
| console.log("Printing Labels with request: ", printRequest); | |||||
| const response = await printDNLabels(printRequest); | |||||
| console.log("Print Labels response: ", response); | |||||
| if(response.success){ | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "success", | |||||
| text: t("Printed Successfully."), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| } else { | |||||
| console.error("Print failed: ", response.message); | |||||
| } | |||||
| } catch(error){ | |||||
| console.error("error: ", error) | |||||
| } | |||||
| } | |||||
| },[t, fgPickOrdersData]); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| fetchReleasedOrderCount(); | fetchReleasedOrderCount(); | ||||
| @@ -776,7 +556,6 @@ const handleAssignByLane = useCallback(async ( | |||||
| > | > | ||||
| <Button | <Button | ||||
| variant="contained" | variant="contained" | ||||
| size="small" | |||||
| sx={{ | sx={{ | ||||
| py: 0.5, // 增加垂直padding | py: 0.5, // 增加垂直padding | ||||
| px: 1.25, // 增加水平padding | px: 1.25, // 增加水平padding | ||||
| @@ -796,7 +575,6 @@ const handleAssignByLane = useCallback(async ( | |||||
| </Button> | </Button> | ||||
| <Button | <Button | ||||
| variant="contained" | variant="contained" | ||||
| size="small" | |||||
| sx={{ | sx={{ | ||||
| py: 0.5, | py: 0.5, | ||||
| px: 1.25, | px: 1.25, | ||||
| @@ -815,72 +593,6 @@ const handleAssignByLane = useCallback(async ( | |||||
| > | > | ||||
| {t("Print Draft")} | {t("Print Draft")} | ||||
| </Button> | </Button> | ||||
| <Button | |||||
| variant="contained" | |||||
| disabled={!printButtonsEnabled} | |||||
| size="small" | |||||
| sx={{ | |||||
| py: 0.5, | |||||
| px: 1.25, | |||||
| height: '40px', | |||||
| fontSize: '0.75rem', | |||||
| lineHeight: 1.2, | |||||
| display: 'flex', | |||||
| alignItems: 'center', | |||||
| justifyContent: 'center', | |||||
| '&.Mui-disabled': { | |||||
| height: '40px' | |||||
| } | |||||
| }} | |||||
| title={!printButtonsEnabled ? t("All lots must be completed before printing") : ""} | |||||
| onClick={handleDNandLabel} | |||||
| > | |||||
| {t("Print Pick Order and DN Label")} | |||||
| </Button> | |||||
| <Button | |||||
| variant="contained" | |||||
| disabled={!printButtonsEnabled} | |||||
| size="small" | |||||
| sx={{ | |||||
| py: 0.5, | |||||
| px: 1.25, | |||||
| height: '40px', | |||||
| fontSize: '0.75rem', | |||||
| lineHeight: 1.2, | |||||
| display: 'flex', | |||||
| alignItems: 'center', | |||||
| justifyContent: 'center', | |||||
| '&.Mui-disabled': { | |||||
| height: '40px' | |||||
| } | |||||
| }} | |||||
| title={!printButtonsEnabled ? t("All lots must be completed before printing") : ""} | |||||
| onClick={handleDN} | |||||
| > | |||||
| {t("Print Pick Order")} | |||||
| </Button> | |||||
| <Button | |||||
| variant="contained" | |||||
| disabled={!printButtonsEnabled} | |||||
| size="small" | |||||
| sx={{ | |||||
| py: 0.5, | |||||
| px: 1.25, | |||||
| height: '40px', | |||||
| fontSize: '0.75rem', | |||||
| lineHeight: 1.2, | |||||
| display: 'flex', | |||||
| alignItems: 'center', | |||||
| justifyContent: 'center', | |||||
| '&.Mui-disabled': { | |||||
| height: '40px' | |||||
| } | |||||
| }} | |||||
| title={!printButtonsEnabled ? t("All lots must be completed before printing") : ""} | |||||
| onClick={handleLabel} | |||||
| > | |||||
| {t("Print DN Label")} | |||||
| </Button> | |||||
| </Stack> | </Stack> | ||||
| </Box> | </Box> | ||||
| </Grid> | </Grid> | ||||
| @@ -895,6 +607,7 @@ const handleAssignByLane = useCallback(async ( | |||||
| <Tab label={t("Pick Order Detail")} iconPosition="end" /> | <Tab label={t("Pick Order Detail")} iconPosition="end" /> | ||||
| <Tab label={t("Finished Good Detail")} iconPosition="end" /> | <Tab label={t("Finished Good Detail")} iconPosition="end" /> | ||||
| <Tab label={t("Finished Good Record")} iconPosition="end" /> | <Tab label={t("Finished Good Record")} iconPosition="end" /> | ||||
| <Tab label={t("Ticket Release Table")} iconPosition="end" /> | |||||
| </Tabs> | </Tabs> | ||||
| </Box> | </Box> | ||||
| @@ -906,6 +619,7 @@ const handleAssignByLane = useCallback(async ( | |||||
| {tabIndex === 0 && <PickExecution filterArgs={filterArgs} onFgPickOrdersChange={setFgPickOrdersData}/>} | {tabIndex === 0 && <PickExecution filterArgs={filterArgs} onFgPickOrdersChange={setFgPickOrdersData}/>} | ||||
| {tabIndex === 1 && <PickExecutionDetail filterArgs={filterArgs} />} | {tabIndex === 1 && <PickExecutionDetail filterArgs={filterArgs} />} | ||||
| {tabIndex === 2 && <GoodPickExecutionRecord filterArgs={filterArgs} />} | {tabIndex === 2 && <GoodPickExecutionRecord filterArgs={filterArgs} />} | ||||
| {tabIndex === 3 && <FGPickOrderTicketReleaseTable/>} | |||||
| </Box> | </Box> | ||||
| </Box> | </Box> | ||||
| ); | ); | ||||
| @@ -41,10 +41,10 @@ import { | |||||
| checkPickOrderCompletion, | checkPickOrderCompletion, | ||||
| PickOrderCompletionResponse, | PickOrderCompletionResponse, | ||||
| checkAndCompletePickOrderByConsoCode, | checkAndCompletePickOrderByConsoCode, | ||||
| fetchCompletedDoPickOrders, // ✅ 新增:使用新的 API | |||||
| fetchCompletedDoPickOrders, | |||||
| CompletedDoPickOrderResponse, | CompletedDoPickOrderResponse, | ||||
| CompletedDoPickOrderSearchParams, | CompletedDoPickOrderSearchParams, | ||||
| fetchLotDetailsByPickOrderId // ✅ 修复:导入类型 | |||||
| fetchLotDetailsByPickOrderId | |||||
| } from "@/app/api/pickOrder/actions"; | } from "@/app/api/pickOrder/actions"; | ||||
| import { fetchNameList, NameList } from "@/app/api/user/actions"; | import { fetchNameList, NameList } from "@/app/api/user/actions"; | ||||
| import { | import { | ||||
| @@ -63,6 +63,9 @@ import GoodPickExecutionForm from "./GoodPickExecutionForm"; | |||||
| import FGPickOrderCard from "./FGPickOrderCard"; | import FGPickOrderCard from "./FGPickOrderCard"; | ||||
| import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
| import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | ||||
| import { printDN, printDNLabels } from "@/app/api/do/actions"; | |||||
| import Swal from "sweetalert2"; | |||||
| interface Props { | interface Props { | ||||
| filterArgs: Record<string, any>; | filterArgs: Record<string, any>; | ||||
| @@ -108,6 +111,205 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| const formProps = useForm(); | const formProps = useForm(); | ||||
| const errors = formProps.formState.errors; | const errors = formProps.formState.errors; | ||||
| // ✅ Print handler functions | |||||
| const handleDN = useCallback(async (deliveryOrderId: number, pickOrderId: number) => { | |||||
| const askNumofCarton = await Swal.fire({ | |||||
| title: t("Enter the number of cartons: "), | |||||
| icon: "info", | |||||
| input: "number", | |||||
| inputPlaceholder: t("Number of cartons"), | |||||
| inputAttributes:{ | |||||
| min: "1", | |||||
| step: "1" | |||||
| }, | |||||
| inputValidator: (value) => { | |||||
| if(!value){ | |||||
| return t("You need to enter a number") | |||||
| } | |||||
| if(parseInt(value) < 1){ | |||||
| return t("Number must be at least 1"); | |||||
| } | |||||
| return null | |||||
| }, | |||||
| showCancelButton: true, | |||||
| confirmButtonText: t("Confirm"), | |||||
| cancelButtonText: t("Cancel"), | |||||
| confirmButtonColor: "#8dba00", | |||||
| cancelButtonColor: "#F04438", | |||||
| showLoaderOnConfirm: true, | |||||
| allowOutsideClick: () => !Swal.isLoading() | |||||
| }); | |||||
| if (askNumofCarton.isConfirmed) { | |||||
| const numOfCartons = askNumofCarton.value; | |||||
| try{ | |||||
| const printRequest = { | |||||
| printerId: 1, | |||||
| printQty: 1, | |||||
| isDraft: false, | |||||
| numOfCarton: numOfCartons, | |||||
| deliveryOrderId: deliveryOrderId, | |||||
| pickOrderId: pickOrderId | |||||
| }; | |||||
| console.log("Printing Delivery Note with request: ", printRequest); | |||||
| const response = await printDN(printRequest); | |||||
| console.log("Print Delivery Note response: ", response); | |||||
| if(response.success){ | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "success", | |||||
| text: t("Printed Successfully."), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| } else { | |||||
| console.error("Print failed: ", response.message); | |||||
| } | |||||
| } catch(error){ | |||||
| console.error("error: ", error) | |||||
| } | |||||
| } | |||||
| }, [t]); | |||||
| const handleDNandLabel = useCallback(async (deliveryOrderId: number, pickOrderId: number) => { | |||||
| const askNumofCarton = await Swal.fire({ | |||||
| title: t("Enter the number of cartons: "), | |||||
| icon: "info", | |||||
| input: "number", | |||||
| inputPlaceholder: t("Number of cartons"), | |||||
| inputAttributes:{ | |||||
| min: "1", | |||||
| step: "1" | |||||
| }, | |||||
| inputValidator: (value) => { | |||||
| if(!value){ | |||||
| return t("You need to enter a number") | |||||
| } | |||||
| if(parseInt(value) < 1){ | |||||
| return t("Number must be at least 1"); | |||||
| } | |||||
| return null | |||||
| }, | |||||
| showCancelButton: true, | |||||
| confirmButtonText: t("Confirm"), | |||||
| cancelButtonText: t("Cancel"), | |||||
| confirmButtonColor: "#8dba00", | |||||
| cancelButtonColor: "#F04438", | |||||
| showLoaderOnConfirm: true, | |||||
| allowOutsideClick: () => !Swal.isLoading() | |||||
| }); | |||||
| if (askNumofCarton.isConfirmed) { | |||||
| const numOfCartons = askNumofCarton.value; | |||||
| try{ | |||||
| const printDNRequest = { | |||||
| printerId: 1, | |||||
| printQty: 1, | |||||
| isDraft: false, | |||||
| numOfCarton: numOfCartons, | |||||
| deliveryOrderId: deliveryOrderId, | |||||
| pickOrderId: pickOrderId | |||||
| }; | |||||
| const printDNLabelsRequest = { | |||||
| printerId: 1, | |||||
| printQty: 1, | |||||
| numOfCarton: numOfCartons, | |||||
| deliveryOrderId: deliveryOrderId | |||||
| }; | |||||
| console.log("Printing Labels with request: ", printDNLabelsRequest); | |||||
| console.log("Printing DN with request: ", printDNRequest); | |||||
| const LabelsResponse = await printDNLabels(printDNLabelsRequest); | |||||
| const DNResponse = await printDN(printDNRequest); | |||||
| console.log("Print Labels response: ", LabelsResponse); | |||||
| console.log("Print DN response: ", DNResponse); | |||||
| if(LabelsResponse.success && DNResponse.success){ | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "success", | |||||
| text: t("Printed Successfully."), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| } else { | |||||
| if(!LabelsResponse.success){ | |||||
| console.error("Print failed: ", LabelsResponse.message); | |||||
| } | |||||
| else{ | |||||
| console.error("Print failed: ", DNResponse.message); | |||||
| } | |||||
| } | |||||
| } catch(error){ | |||||
| console.error("error: ", error) | |||||
| } | |||||
| } | |||||
| }, [t]); | |||||
| const handleLabel = useCallback(async (deliveryOrderId: number) => { | |||||
| const askNumofCarton = await Swal.fire({ | |||||
| title: t("Enter the number of cartons: "), | |||||
| icon: "info", | |||||
| input: "number", | |||||
| inputPlaceholder: t("Number of cartons"), | |||||
| inputAttributes:{ | |||||
| min: "1", | |||||
| step: "1" | |||||
| }, | |||||
| inputValidator: (value) => { | |||||
| if(!value){ | |||||
| return t("You need to enter a number") | |||||
| } | |||||
| if(parseInt(value) < 1){ | |||||
| return t("Number must be at least 1"); | |||||
| } | |||||
| return null | |||||
| }, | |||||
| showCancelButton: true, | |||||
| confirmButtonText: t("Confirm"), | |||||
| cancelButtonText: t("Cancel"), | |||||
| confirmButtonColor: "#8dba00", | |||||
| cancelButtonColor: "#F04438", | |||||
| showLoaderOnConfirm: true, | |||||
| allowOutsideClick: () => !Swal.isLoading() | |||||
| }); | |||||
| if (askNumofCarton.isConfirmed) { | |||||
| const numOfCartons = askNumofCarton.value; | |||||
| try{ | |||||
| const printRequest = { | |||||
| printerId: 1, | |||||
| printQty: 1, | |||||
| numOfCarton: numOfCartons, | |||||
| deliveryOrderId: deliveryOrderId, | |||||
| }; | |||||
| console.log("Printing Labels with request: ", printRequest); | |||||
| const response = await printDNLabels(printRequest); | |||||
| console.log("Print Labels response: ", response); | |||||
| if(response.success){ | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "success", | |||||
| text: t("Printed Successfully."), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| } else { | |||||
| console.error("Print failed: ", response.message); | |||||
| } | |||||
| } catch(error){ | |||||
| console.error("error: ", error) | |||||
| } | |||||
| } | |||||
| }, [t]); | |||||
| // ✅ 修改:使用新的 API 获取已完成的 DO Pick Orders | // ✅ 修改:使用新的 API 获取已完成的 DO Pick Orders | ||||
| const fetchCompletedDoPickOrdersData = useCallback(async (searchParams?: CompletedDoPickOrderSearchParams) => { | const fetchCompletedDoPickOrdersData = useCallback(async (searchParams?: CompletedDoPickOrderSearchParams) => { | ||||
| if (!currentUserId) return; | if (!currentUserId) return; | ||||
| @@ -406,6 +608,37 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| > | > | ||||
| {t("View Details")} | {t("View Details")} | ||||
| </Button> | </Button> | ||||
| {doPickOrder.fgPickOrders && doPickOrder.fgPickOrders.length > 0 && ( | |||||
| <> | |||||
| <Button | |||||
| variant="contained" | |||||
| onClick={() => handleDN( | |||||
| doPickOrder.fgPickOrders[0].deliveryOrderId, | |||||
| doPickOrder.fgPickOrders[0].pickOrderId | |||||
| )} | |||||
| > | |||||
| {t("Print Pick Order")} | |||||
| </Button> | |||||
| <Button | |||||
| variant="contained" | |||||
| onClick={() => handleDNandLabel( | |||||
| doPickOrder.fgPickOrders[0].deliveryOrderId, | |||||
| doPickOrder.fgPickOrders[0].pickOrderId | |||||
| )} | |||||
| > | |||||
| {t("Print DN & Label")} | |||||
| </Button> | |||||
| <Button | |||||
| variant="contained" | |||||
| onClick={() => handleLabel( | |||||
| doPickOrder.fgPickOrders[0].deliveryOrderId | |||||
| )} | |||||
| > | |||||
| {t("Print Label")} | |||||
| </Button> | |||||
| </> | |||||
| )} | |||||
| </CardActions> | </CardActions> | ||||
| </Card> | </Card> | ||||
| ))} | ))} | ||||
| @@ -275,9 +275,9 @@ | |||||
| "Confirm":"確認", | "Confirm":"確認", | ||||
| "Update your suggested lot to the this scanned lot":"更新您的建議批次為此掃描的批次", | "Update your suggested lot to the this scanned lot":"更新您的建議批次為此掃描的批次", | ||||
| "Print Draft":"列印草稿", | "Print Draft":"列印草稿", | ||||
| "Print Pick Order and DN Label":"列印提料單和送貨單標貼", | |||||
| "Print Pick Order and DN Label":"列印提料單和送貨單標籤", | |||||
| "Print Pick Order":"列印提料單", | "Print Pick Order":"列印提料單", | ||||
| "Print DN Label":"列印送貨單標貼", | |||||
| "Print DN Label":"列印送貨單標籤", | |||||
| "Print All Draft" : "列印全部草稿", | "Print All Draft" : "列印全部草稿", | ||||
| "If you confirm, the system will:":"如果您確認,系統將:", | "If you confirm, the system will:":"如果您確認,系統將:", | ||||
| "QR code verified.":"QR 碼驗證成功。", | "QR code verified.":"QR 碼驗證成功。", | ||||
| @@ -289,7 +289,6 @@ | |||||
| "Completed DO pick orders: ":"已完成送貨單提料單:", | "Completed DO pick orders: ":"已完成送貨單提料單:", | ||||
| "No completed DO pick orders found":"沒有已完成送貨單提料單", | "No completed DO pick orders found":"沒有已完成送貨單提料單", | ||||
| "Print DN Label":"列印送貨單標貼", | |||||
| "Enter the number of cartons: ": "請輸入總箱數", | "Enter the number of cartons: ": "請輸入總箱數", | ||||
| "Number of cartons": "箱數", | "Number of cartons": "箱數", | ||||
| "Select an action for the assigned pick orders.": "選擇分配提料單的動作。", | "Select an action for the assigned pick orders.": "選擇分配提料單的動作。", | ||||
| @@ -387,5 +386,8 @@ | |||||
| "Today": "是日", | "Today": "是日", | ||||
| "Tomorrow": "翌日", | "Tomorrow": "翌日", | ||||
| "Day After Tomorrow": "後日", | "Day After Tomorrow": "後日", | ||||
| "Select Date": "請選擇日期" | |||||
| "Select Date": "請選擇日期", | |||||
| "Print DN & Label": "列印提料單和送貨單標籤", | |||||
| "Print Label": "列印送貨單標籤", | |||||
| "Ticket Release Table": "查看提貨情況" | |||||
| } | } | ||||