| @@ -26,7 +26,7 @@ const jo: React.FC = async () => { | |||||
| {t("Job Order")} | {t("Job Order")} | ||||
| </Typography> | </Typography> | ||||
| </Stack> | </Stack> | ||||
| <I18nProvider namespaces={["jo", "common", "purchaseOrder", "dashboard"]}> {/* TODO: Improve */} | |||||
| <I18nProvider namespaces={["jo", "common", "purchaseOrder", "dashboard","common"]}> {/* TODO: Improve */} | |||||
| <Suspense fallback={<JoSearch.Loading />}> | <Suspense fallback={<JoSearch.Loading />}> | ||||
| <JoSearch /> | <JoSearch /> | ||||
| </Suspense> | </Suspense> | ||||
| @@ -17,7 +17,7 @@ const PurchaseOrder: React.FC = async () => { | |||||
| // preloadClaims(); | // preloadClaims(); | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <I18nProvider namespaces={["purchaseOrder", "common", "items"]}> | |||||
| <I18nProvider namespaces={["purchaseOrder", "common", "items","dashboard"]}> | |||||
| <Stack | <Stack | ||||
| direction="row" | direction="row" | ||||
| justifyContent="space-between" | justifyContent="space-between" | ||||
| @@ -16,7 +16,7 @@ import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerP | |||||
| import { fetchStockInLineInfo } from "@/app/api/po/actions"; | import { fetchStockInLineInfo } from "@/app/api/po/actions"; | ||||
| import JoRelease from "./JoRelease"; | import JoRelease from "./JoRelease"; | ||||
| import { submitDialog } from "../Swal/CustomAlerts"; | import { submitDialog } from "../Swal/CustomAlerts"; | ||||
| import ProductionProcessJobOrderDetail from "../ProductionProcess/ProductionProcessJobOrderDetail"; | |||||
| type Props = { | type Props = { | ||||
| id?: number; | id?: number; | ||||
| defaultValues: Partial<JoDetail> | undefined; | defaultValues: Partial<JoDetail> | undefined; | ||||
| @@ -192,10 +192,16 @@ const JoSave: React.FC<Props> = ({ | |||||
| {serverError} | {serverError} | ||||
| </Typography> | </Typography> | ||||
| )} | )} | ||||
| {/* | |||||
| <ActionButtons handleRelease={handleRelease} handleStart={handleStart}/> | <ActionButtons handleRelease={handleRelease} handleStart={handleStart}/> | ||||
| <InfoCard /> | <InfoCard /> | ||||
| <JoRelease pickLines={pickLines} handleRelease={handleRelease}/> | <JoRelease pickLines={pickLines} handleRelease={handleRelease}/> | ||||
| <PickTable /> | <PickTable /> | ||||
| */} | |||||
| {id ? ( | |||||
| <ProductionProcessJobOrderDetail jobOrderId={id} onBack={handleBack} fromJosave={true}/> | |||||
| ) : null} | |||||
| {/* | |||||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | <Stack direction="row" justifyContent="flex-end" gap={1}> | ||||
| <Button | <Button | ||||
| variant="outlined" | variant="outlined" | ||||
| @@ -205,6 +211,7 @@ const JoSave: React.FC<Props> = ({ | |||||
| {t("Back")} | {t("Back")} | ||||
| </Button> | </Button> | ||||
| </Stack> | </Stack> | ||||
| */} | |||||
| </Stack> | </Stack> | ||||
| </FormProvider> | </FormProvider> | ||||
| </> | </> | ||||
| @@ -33,6 +33,8 @@ import { | |||||
| fetchCompletedJobOrderPickOrders, | fetchCompletedJobOrderPickOrders, | ||||
| fetchCompletedJobOrderPickOrderRecords | fetchCompletedJobOrderPickOrderRecords | ||||
| } from "@/app/api/jo/actions"; | } from "@/app/api/jo/actions"; | ||||
| import { fetchPrinterCombo } from "@/app/api/settings/printer"; | |||||
| import { PrinterCombo } from "@/app/api/settings/printer"; | |||||
| interface Props { | interface Props { | ||||
| pickOrders: PickOrderResult[]; | pickOrders: PickOrderResult[]; | ||||
| } | } | ||||
| @@ -63,6 +65,7 @@ const [hasAssignedJobOrders, setHasAssignedJobOrders] = useState(false); | |||||
| const [hasDataTab0, setHasDataTab0] = useState(false); | const [hasDataTab0, setHasDataTab0] = useState(false); | ||||
| const [hasDataTab1, setHasDataTab1] = useState(false); | const [hasDataTab1, setHasDataTab1] = useState(false); | ||||
| const hasAnyAssignedData = hasDataTab0 || hasDataTab1; | const hasAnyAssignedData = hasDataTab0 || hasDataTab1; | ||||
| const [printers, setPrinters] = useState<PrinterCombo[]>([]); | |||||
| const [hideCompletedUntilNext, setHideCompletedUntilNext] = useState<boolean>( | const [hideCompletedUntilNext, setHideCompletedUntilNext] = useState<boolean>( | ||||
| typeof window !== 'undefined' && localStorage.getItem('hideCompletedUntilNext') === 'true' | typeof window !== 'undefined' && localStorage.getItem('hideCompletedUntilNext') === 'true' | ||||
| ); | ); | ||||
| @@ -92,6 +95,19 @@ const hasAnyAssignedData = hasDataTab0 || hasDataTab1; | |||||
| window.removeEventListener('jobOrderDataStatus', handleJobOrderDataChange as EventListener); | window.removeEventListener('jobOrderDataStatus', handleJobOrderDataChange as EventListener); | ||||
| }; | }; | ||||
| }, []); | }, []); | ||||
| useEffect(() => { | |||||
| const fetchPrinters = async () => { | |||||
| try { | |||||
| // 需要创建一个客户端版本的 fetchPrinterCombo | |||||
| // 或者使用 API 路由 | |||||
| // const printersData = await fetch('/api/printers/combo').then(r => r.json()); | |||||
| // setPrinters(printersData); | |||||
| } catch (error) { | |||||
| console.error("Error fetching printers:", error); | |||||
| } | |||||
| }; | |||||
| fetchPrinters(); | |||||
| }, []); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| const onAssigned = () => { | const onAssigned = () => { | ||||
| localStorage.removeItem('hideCompletedUntilNext'); | localStorage.removeItem('hideCompletedUntilNext'); | ||||
| @@ -466,7 +482,7 @@ const hasAnyAssignedData = hasDataTab0 || hasDataTab1; | |||||
| p: 2 | p: 2 | ||||
| }}> | }}> | ||||
| {tabIndex === 0 && <JobPickExecution filterArgs={filterArgs} />} | {tabIndex === 0 && <JobPickExecution filterArgs={filterArgs} />} | ||||
| {tabIndex === 1 && <CompleteJobOrderRecord filterArgs={filterArgs} />} | |||||
| {tabIndex === 1 && <CompleteJobOrderRecord filterArgs={filterArgs} printerCombo={printers} />} | |||||
| {tabIndex === 2 && <JobPickExecutionsecondscan filterArgs={filterArgs} />} | {tabIndex === 2 && <JobPickExecutionsecondscan filterArgs={filterArgs} />} | ||||
| {/* {tabIndex === 3 && <FInishedJobOrderRecord filterArgs={filterArgs} />} */} | {/* {tabIndex === 3 && <FInishedJobOrderRecord filterArgs={filterArgs} />} */} | ||||
| </Box> | </Box> | ||||
| @@ -25,6 +25,7 @@ import { | |||||
| AccordionSummary, | AccordionSummary, | ||||
| AccordionDetails, | AccordionDetails, | ||||
| Checkbox, | Checkbox, | ||||
| Autocomplete, | |||||
| } from "@mui/material"; | } from "@mui/material"; | ||||
| import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; | import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; | ||||
| import { useCallback, useEffect, useState, useRef, useMemo } from "react"; | import { useCallback, useEffect, useState, useRef, useMemo } from "react"; | ||||
| @@ -44,9 +45,10 @@ import SearchBox, { Criterion } from "../SearchBox"; | |||||
| import { useSession } from "next-auth/react"; | import { useSession } from "next-auth/react"; | ||||
| import { SessionWithTokens } from "@/config/authConfig"; | import { SessionWithTokens } from "@/config/authConfig"; | ||||
| import Swal from "sweetalert2"; | import Swal from "sweetalert2"; | ||||
| import { PrinterCombo } from "@/app/api/settings/printer"; | |||||
| interface Props { | interface Props { | ||||
| filterArgs: Record<string, any>; | filterArgs: Record<string, any>; | ||||
| printerCombo: PrinterCombo[]; | |||||
| } | } | ||||
| // 修改:已完成的 Job Order Pick Order 接口 | // 修改:已完成的 Job Order Pick Order 接口 | ||||
| @@ -99,7 +101,7 @@ interface LotDetail { | |||||
| uomDesc: string; | uomDesc: string; | ||||
| } | } | ||||
| const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs ,printerCombo=[]}) => { | |||||
| const { t } = useTranslation("jo"); | const { t } = useTranslation("jo"); | ||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const { data: session } = useSession() as { data: SessionWithTokens | null }; | const { data: session } = useSession() as { data: SessionWithTokens | null }; | ||||
| @@ -119,7 +121,24 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| // 修改:搜索状态 | // 修改:搜索状态 | ||||
| const [searchQuery, setSearchQuery] = useState<Record<string, any>>({}); | const [searchQuery, setSearchQuery] = useState<Record<string, any>>({}); | ||||
| const [filteredJobOrderPickOrders, setFilteredJobOrderPickOrders] = useState<CompletedJobOrderPickOrder[]>([]); | const [filteredJobOrderPickOrders, setFilteredJobOrderPickOrders] = useState<CompletedJobOrderPickOrder[]>([]); | ||||
| //const [selectedPrinter, setSelectedPrinter] = useState(printerCombo[0]); | |||||
| const defaultDemoPrinter: PrinterCombo = { | |||||
| id: 2, | |||||
| value: 2, | |||||
| name: "2fi", | |||||
| label: "2fi", | |||||
| code: "2fi" | |||||
| }; | |||||
| const availablePrinters = useMemo(() => { | |||||
| if (printerCombo.length === 0) { | |||||
| return [defaultDemoPrinter]; | |||||
| } | |||||
| return printerCombo; | |||||
| }, [printerCombo]); | |||||
| const [selectedPrinter, setSelectedPrinter] = useState<PrinterCombo | null>( | |||||
| printerCombo && printerCombo.length > 0 ? printerCombo[0] : null | |||||
| ); | |||||
| const [printQty, setPrintQty] = useState<number>(1); | |||||
| // 修改:分页状态 | // 修改:分页状态 | ||||
| const [paginationController, setPaginationController] = useState({ | const [paginationController, setPaginationController] = useState({ | ||||
| pageNum: 0, | pageNum: 0, | ||||
| @@ -297,44 +316,84 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| })); | })); | ||||
| }, []); | }, []); | ||||
| const handlePickRecord = useCallback(async () =>{ | |||||
| try{ | |||||
| if (!selectedJobOrderPickOrder) { | |||||
| const handlePickRecord = useCallback(async (jobOrderPickOrder: CompletedJobOrderPickOrder) => { | |||||
| try { | |||||
| if (!jobOrderPickOrder) { | |||||
| console.error("No selected job order pick order available"); | console.error("No selected job order pick order available"); | ||||
| return; | return; | ||||
| } | } | ||||
| const pickOrderId = selectedJobOrderPickOrder.pickOrderId; | |||||
| console.log("Pick Order ID:", pickOrderId); | |||||
| const printRequest = { | |||||
| pickOrderId: pickOrderId, | |||||
| printerId: 2, | |||||
| printQty: 1 | |||||
| }; | |||||
| // 检查是否已选择打印机 | |||||
| if (!selectedPrinter) { | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "warning", | |||||
| text: t("Please select a printer first"), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| return; | |||||
| } | |||||
| // 检查打印数量是否有效 | |||||
| if (!printQty || printQty < 1) { | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "warning", | |||||
| text: t("Please enter a valid print quantity (at least 1)"), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| return; | |||||
| } | |||||
| const pickOrderId = jobOrderPickOrder.pickOrderId; | |||||
| console.log("Pick Order ID:", pickOrderId); | |||||
| console.log("Printing Pick Record with request: ", printRequest); | |||||
| // 使用已选择的打印机和数量 | |||||
| const printerId = selectedPrinter.id; | |||||
| const response = await PrintPickRecord(printRequest) | |||||
| const printRequest = { | |||||
| pickOrderId: pickOrderId, | |||||
| printerId: printerId, | |||||
| printQty: printQty | |||||
| }; | |||||
| console.log("Print Pick Record response: ", response); | |||||
| console.log("Printing Pick Record with request: ", printRequest); | |||||
| if(response.success){ | |||||
| Swal.fire({ | |||||
| const response = await PrintPickRecord(printRequest); | |||||
| console.log("Print Pick Record response: ", response); | |||||
| if (response.success) { | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | position: "bottom-end", | ||||
| icon: "success", | icon: "success", | ||||
| text: t("Printed Successfully."), | text: t("Printed Successfully."), | ||||
| showConfirmButton: false, | showConfirmButton: false, | ||||
| timer: 1500 | timer: 1500 | ||||
| }); | |||||
| } else { | |||||
| console.error("Print failed: ", response.message); | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "error", | |||||
| text: response.message || t("Print failed"), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| } | |||||
| } catch (error) { | |||||
| console.error("error: ", error); | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "error", | |||||
| text: t("An error occurred while printing"), | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | }); | ||||
| } else { | |||||
| console.error("Print failed: ", response.message); | |||||
| } | |||||
| }catch(error){ | |||||
| console.error("error: ", error) | |||||
| } | } | ||||
| },[t, selectedJobOrderPickOrder]); | |||||
| }, [t, selectedPrinter, printQty]); | |||||
| // 修改:如果显示详情视图,渲染 Job Order 详情和 Lot 信息 | // 修改:如果显示详情视图,渲染 Job Order 详情和 Lot 信息 | ||||
| if (showDetailView && selectedJobOrderPickOrder) { | if (showDetailView && selectedJobOrderPickOrder) { | ||||
| return ( | return ( | ||||
| @@ -373,16 +432,18 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| <strong>{t("Required Qty")}:</strong> {selectedJobOrderPickOrder.reqQty} {selectedJobOrderPickOrder.uom} | <strong>{t("Required Qty")}:</strong> {selectedJobOrderPickOrder.reqQty} {selectedJobOrderPickOrder.uom} | ||||
| </Typography> | </Typography> | ||||
| </Stack> | </Stack> | ||||
| {/* | |||||
| <Stack direction="row" spacing={4} useFlexGap flexWrap="wrap" sx={{ mt: 2 }}> | <Stack direction="row" spacing={4} useFlexGap flexWrap="wrap" sx={{ mt: 2 }}> | ||||
| <Button | <Button | ||||
| variant="contained" | variant="contained" | ||||
| color="primary" | color="primary" | ||||
| onClick={handlePickRecord} | |||||
| onClick={() => handlePickRecord(selectedJobOrderPickOrder)} | |||||
| sx={{ mt: 1 }} | sx={{ mt: 1 }} | ||||
| > | > | ||||
| {t("Print Pick Record")} | {t("Print Pick Record")} | ||||
| </Button> | </Button> | ||||
| </Stack> | </Stack> | ||||
| */} | |||||
| </CardContent> | </CardContent> | ||||
| </Card> | </Card> | ||||
| @@ -538,26 +599,56 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}> | <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}> | ||||
| {t("Total")}: {filteredJobOrderPickOrders.length} {t("completed Job Order pick orders with matching")} | {t("Total")}: {filteredJobOrderPickOrders.length} {t("completed Job Order pick orders with matching")} | ||||
| </Typography> | </Typography> | ||||
| <Box sx={{ mb: 2, p: 2, border: '1px solid #e0e0e0', borderRadius: 1, bgcolor: 'background.paper' }}> | |||||
| <Stack direction="row" spacing={2} alignItems="center" flexWrap="wrap"> | |||||
| <Typography variant="subtitle1" sx={{ minWidth: 'fit-content' }}> | |||||
| {t("Select Printer")}: | |||||
| </Typography> | |||||
| <Autocomplete | |||||
| options={availablePrinters} | |||||
| getOptionLabel={(option) => option.name || option.label || option.code || `Printer ${option.id}`} | |||||
| value={selectedPrinter} | |||||
| onChange={(_, newValue) => setSelectedPrinter(newValue)} | |||||
| sx={{ minWidth: 250 }} | |||||
| size="small" | |||||
| renderInput={(params) => <TextField {...params} label={t("Printer")} />} | |||||
| /> | |||||
| <Typography variant="subtitle1" sx={{ minWidth: 'fit-content' }}> | |||||
| {t("Print Quantity")}: | |||||
| </Typography> | |||||
| <TextField | |||||
| type="number" | |||||
| label={t("Print Quantity")} | |||||
| value={printQty} | |||||
| onChange={(e) => { | |||||
| const value = parseInt(e.target.value) || 1; | |||||
| setPrintQty(Math.max(1, value)); | |||||
| }} | |||||
| inputProps={{ min: 1, step: 1 }} | |||||
| sx={{ width: 120 }} | |||||
| size="small" | |||||
| /> | |||||
| </Stack> | |||||
| </Box> | |||||
| {/* 列表 */} | {/* 列表 */} | ||||
| {filteredJobOrderPickOrders.length === 0 ? ( | {filteredJobOrderPickOrders.length === 0 ? ( | ||||
| <Box sx={{ p: 3, textAlign: 'center' }}> | |||||
| <Typography variant="body2" color="text.secondary"> | |||||
| {t("No completed Job Order pick orders with matching found")} | |||||
| </Typography> | |||||
| </Box> | |||||
| ) : ( | |||||
| <Stack spacing={2}> | |||||
| {paginatedData.map((jobOrderPickOrder) => ( | |||||
| <Box sx={{ p: 3, textAlign: 'center' }}> | |||||
| <Typography variant="body2" color="text.secondary"> | |||||
| {t("No completed Job Order pick orders with matching found")} | |||||
| </Typography> | |||||
| </Box> | |||||
| ) : ( | |||||
| <Stack spacing={2}> | |||||
| {paginatedData.map((jobOrderPickOrder) => ( | |||||
| <Card key={jobOrderPickOrder.id}> | <Card key={jobOrderPickOrder.id}> | ||||
| <CardContent> | <CardContent> | ||||
| <Stack direction="row" justifyContent="space-between" alignItems="center"> | <Stack direction="row" justifyContent="space-between" alignItems="center"> | ||||
| <Box> | <Box> | ||||
| <Typography variant="h6"> | <Typography variant="h6"> | ||||
| {jobOrderPickOrder.pickOrderCode} | |||||
| {jobOrderPickOrder.jobOrderCode} | |||||
| </Typography> | </Typography> | ||||
| <Typography variant="body2" color="text.secondary"> | <Typography variant="body2" color="text.secondary"> | ||||
| {jobOrderPickOrder.jobOrderName} - {jobOrderPickOrder.jobOrderCode} | |||||
| {jobOrderPickOrder.jobOrderName} - {jobOrderPickOrder.pickOrderCode} | |||||
| </Typography> | </Typography> | ||||
| <Typography variant="body2" color="text.secondary"> | <Typography variant="body2" color="text.secondary"> | ||||
| {t("Completed")}: {new Date(jobOrderPickOrder.completedDate).toLocaleString()} | {t("Completed")}: {new Date(jobOrderPickOrder.completedDate).toLocaleString()} | ||||
| @@ -566,6 +657,7 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| {t("Target Date")}: {jobOrderPickOrder.pickOrderTargetDate} | {t("Target Date")}: {jobOrderPickOrder.pickOrderTargetDate} | ||||
| </Typography> | </Typography> | ||||
| </Box> | </Box> | ||||
| <Box> | <Box> | ||||
| <Chip | <Chip | ||||
| label={t(jobOrderPickOrder.pickOrderStatus) } | label={t(jobOrderPickOrder.pickOrderStatus) } | ||||
| @@ -592,6 +684,16 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| > | > | ||||
| {t("View Details")} | {t("View Details")} | ||||
| </Button> | </Button> | ||||
| <Button | |||||
| variant="contained" | |||||
| color="primary" | |||||
| onClick={() => handlePickRecord(jobOrderPickOrder)} | |||||
| sx={{ mt: 1 }} | |||||
| > | |||||
| {t("Print Pick Record")} | |||||
| </Button> | |||||
| </CardActions> | </CardActions> | ||||
| </Card> | </Card> | ||||
| ))} | ))} | ||||
| @@ -101,7 +101,7 @@ const PoSearchList: React.FC<{ | |||||
| selectedPoId: number; | selectedPoId: number; | ||||
| onSelect: (po: PoResult) => void; | onSelect: (po: PoResult) => void; | ||||
| }> = ({ poList, selectedPoId, onSelect }) => { | }> = ({ poList, selectedPoId, onSelect }) => { | ||||
| const { t } = useTranslation("purchaseOrder"); | |||||
| const { t } = useTranslation(["purchaseOrder", "dashboard"]); | |||||
| const [searchTerm, setSearchTerm] = useState(''); | const [searchTerm, setSearchTerm] = useState(''); | ||||
| const filteredPoList = useMemo(() => { | const filteredPoList = useMemo(() => { | ||||
| @@ -963,7 +963,7 @@ const closeNewModal = useCallback(() => { | |||||
| ); | ); | ||||
| } | } | ||||
| const NoRowsOverlay: React.FC = () => { | const NoRowsOverlay: React.FC = () => { | ||||
| const { t } = useTranslation("home"); | |||||
| const { t } = useTranslation("purchaseOrder"); | |||||
| return ( | return ( | ||||
| <Box | <Box | ||||
| display="flex" | display="flex" | ||||
| @@ -112,7 +112,7 @@ function InputDataGrid<T, V, E>({ | |||||
| const { | const { | ||||
| t, | t, | ||||
| // i18n: { language }, | // i18n: { language }, | ||||
| } = useTranslation("purchaseOrder"); | |||||
| } = useTranslation(["purchaseOrder","dashboard"]); | |||||
| const formKey = _formKey.toString(); | const formKey = _formKey.toString(); | ||||
| const { setValue, getValues } = useFormContext(); | const { setValue, getValues } = useFormContext(); | ||||
| const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | ||||
| @@ -380,7 +380,7 @@ const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => { | |||||
| return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>; | return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>; | ||||
| }; | }; | ||||
| const NoRowsOverlay: React.FC = () => { | const NoRowsOverlay: React.FC = () => { | ||||
| const { t } = useTranslation("home"); | |||||
| const { t } = useTranslation("purchaseOrder"); | |||||
| return ( | return ( | ||||
| <Box | <Box | ||||
| display="flex" | display="flex" | ||||
| @@ -39,7 +39,7 @@ const PoSearch: React.FC<Props> = ({ | |||||
| const [selectAll, setSelectAll] = useState(false); | const [selectAll, setSelectAll] = useState(false); | ||||
| const [filteredPo, setFilteredPo] = useState<PoResult[]>(po); | const [filteredPo, setFilteredPo] = useState<PoResult[]>(po); | ||||
| const [filterArgs, setFilterArgs] = useState<Record<string, any>>({estimatedArrivalDate : dayjsToDateString(dayjs(), "input")}); | const [filterArgs, setFilterArgs] = useState<Record<string, any>>({estimatedArrivalDate : dayjsToDateString(dayjs(), "input")}); | ||||
| const { t } = useTranslation("purchaseOrder"); | |||||
| const { t } = useTranslation(["purchaseOrder", "dashboard"]); | |||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const [pagingController, setPagingController] = useState( | const [pagingController, setPagingController] = useState( | ||||
| defaultPagingController, | defaultPagingController, | ||||
| @@ -489,10 +489,25 @@ const ProductionProcessDetail: React.FC<ProductProcessDetailProps> = ({ | |||||
| <TableCell>{t("Description")}</TableCell> | <TableCell>{t("Description")}</TableCell> | ||||
| <TableCell>{t("Equipment Type/Code")}</TableCell> | <TableCell>{t("Equipment Type/Code")}</TableCell> | ||||
| <TableCell>{t("Operator")}</TableCell> | <TableCell>{t("Operator")}</TableCell> | ||||
| {/*} | |||||
| <TableCell>{t("Processing Time (mins)")}</TableCell> | <TableCell>{t("Processing Time (mins)")}</TableCell> | ||||
| <TableCell>{t("Setup Time (mins)")}</TableCell> | <TableCell>{t("Setup Time (mins)")}</TableCell> | ||||
| <TableCell>{t("Changeover Time (mins)")}</TableCell> | <TableCell>{t("Changeover Time (mins)")}</TableCell> | ||||
| */} | |||||
| <TableCell> | |||||
| <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}> | |||||
| <Typography variant="subtitle2" sx={{ fontWeight: 600 }}> | |||||
| {t("Time Information(mins)")} | |||||
| </Typography> | |||||
| <Typography variant="caption" sx={{ color: 'text.secondary' }}> | |||||
| {t("Processing Time")}- | |||||
| </Typography> | |||||
| <Typography variant="caption" sx={{ color: 'text.secondary' }}> | |||||
| {t("Setup Time")} - {t("Changeover Time")} | |||||
| </Typography> | |||||
| </Box> | |||||
| </TableCell> | |||||
| <TableCell align="center">{t("Status")}</TableCell> | <TableCell align="center">{t("Status")}</TableCell> | ||||
| <TableCell align="center">{t("Action")}</TableCell> | <TableCell align="center">{t("Action")}</TableCell> | ||||
| </TableRow> | </TableRow> | ||||
| @@ -516,10 +531,12 @@ const ProductionProcessDetail: React.FC<ProductProcessDetailProps> = ({ | |||||
| <TableCell><Typography fontWeight={500}>{line.description || "-"}</Typography></TableCell> | <TableCell><Typography fontWeight={500}>{line.description || "-"}</Typography></TableCell> | ||||
| <TableCell><Typography fontWeight={500}>{equipmentName}</Typography></TableCell> | <TableCell><Typography fontWeight={500}>{equipmentName}</Typography></TableCell> | ||||
| <TableCell><Typography fontWeight={500}>{line.operatorName}</Typography></TableCell> | <TableCell><Typography fontWeight={500}>{line.operatorName}</Typography></TableCell> | ||||
| {/* | |||||
| <TableCell><Typography fontWeight={500}>{line.durationInMinutes} </Typography></TableCell> | <TableCell><Typography fontWeight={500}>{line.durationInMinutes} </Typography></TableCell> | ||||
| <TableCell><Typography fontWeight={500}>{line.prepTimeInMinutes} </Typography></TableCell> | <TableCell><Typography fontWeight={500}>{line.prepTimeInMinutes} </Typography></TableCell> | ||||
| <TableCell><Typography fontWeight={500}>{line.postProdTimeInMinutes} </Typography></TableCell> | <TableCell><Typography fontWeight={500}>{line.postProdTimeInMinutes} </Typography></TableCell> | ||||
| */} | |||||
| <TableCell><Typography fontWeight={500}>{line.durationInMinutes} - {line.prepTimeInMinutes} - {line.postProdTimeInMinutes} </Typography></TableCell> | |||||
| <TableCell align="center"> | <TableCell align="center"> | ||||
| {isCompleted ? ( | {isCompleted ? ( | ||||
| <Chip label={t("Completed")} color="success" size="small" | <Chip label={t("Completed")} color="success" size="small" | ||||
| @@ -46,11 +46,13 @@ interface JobOrderLine { | |||||
| interface ProductProcessJobOrderDetailProps { | interface ProductProcessJobOrderDetailProps { | ||||
| jobOrderId: number; | jobOrderId: number; | ||||
| onBack: () => void; | onBack: () => void; | ||||
| fromJosave?: boolean; | |||||
| } | } | ||||
| const ProductionProcessJobOrderDetail: React.FC<ProductProcessJobOrderDetailProps> = ({ | const ProductionProcessJobOrderDetail: React.FC<ProductProcessJobOrderDetailProps> = ({ | ||||
| jobOrderId, | jobOrderId, | ||||
| onBack, | onBack, | ||||
| fromJosave, | |||||
| }) => { | }) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const [loading, setLoading] = useState(false); | const [loading, setLoading] = useState(false); | ||||
| @@ -363,7 +365,7 @@ const handleRelease = useCallback(() => { | |||||
| <Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}> | <Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}> | ||||
| {t("Lines with insufficient stock: ")}<strong style={{ color: "red" }}>{stockCounts.insufficient}</strong> | {t("Lines with insufficient stock: ")}<strong style={{ color: "red" }}>{stockCounts.insufficient}</strong> | ||||
| </Typography> | </Typography> | ||||
| {!fromJosave && ( | |||||
| <Button | <Button | ||||
| variant="contained" | variant="contained" | ||||
| color="primary" | color="primary" | ||||
| @@ -372,6 +374,7 @@ const handleRelease = useCallback(() => { | |||||
| > | > | ||||
| {t("Release")} | {t("Release")} | ||||
| </Button> | </Button> | ||||
| )} | |||||
| </Stack> | </Stack> | ||||
| </CardContent> | </CardContent> | ||||
| </Card> | </Card> | ||||
| @@ -414,9 +417,15 @@ const handleRelease = useCallback(() => { | |||||
| <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | ||||
| <Tab label={t("Job Order Info")} /> | <Tab label={t("Job Order Info")} /> | ||||
| <Tab label={t("BoM Material")} /> | <Tab label={t("BoM Material")} /> | ||||
| <Tab label={t("Production Process")} /> | |||||
| <Tab label={t("Production Process Line Remark")} /> | |||||
| <Tab label={t("Matching Stock")} /> | |||||
| {!fromJosave && ( | |||||
| <Tab label={t("Production Process")} /> | |||||
| )} | |||||
| {!fromJosave && ( | |||||
| <Tab label={t("Production Process Line Remark")} /> | |||||
| )} | |||||
| {!fromJosave && ( | |||||
| <Tab label={t("Matching Stock")} /> | |||||
| )} | |||||
| </Tabs> | </Tabs> | ||||
| </Box> | </Box> | ||||
| @@ -424,6 +433,7 @@ const handleRelease = useCallback(() => { | |||||
| <Box sx={{ p: 2 }}> | <Box sx={{ p: 2 }}> | ||||
| {tabIndex === 0 && <InfoCardContent />} | {tabIndex === 0 && <InfoCardContent />} | ||||
| {tabIndex === 1 && <PickTableContent />} | {tabIndex === 1 && <PickTableContent />} | ||||
| {tabIndex === 2 && ( | {tabIndex === 2 && ( | ||||
| <ProductionProcessDetail | <ProductionProcessDetail | ||||
| jobOrderId={jobOrderId} | jobOrderId={jobOrderId} | ||||
| @@ -435,6 +445,7 @@ const handleRelease = useCallback(() => { | |||||
| )} | )} | ||||
| {tabIndex === 3 && <ProductionProcessesLineRemarkTableContent />} | {tabIndex === 3 && <ProductionProcessesLineRemarkTableContent />} | ||||
| {tabIndex === 4 && <JobPickExecutionsecondscan filterArgs={{ jobOrderId: jobOrderId }} />} | {tabIndex === 4 && <JobPickExecutionsecondscan filterArgs={{ jobOrderId: jobOrderId }} />} | ||||
| </Box> | </Box> | ||||
| </Box> | </Box> | ||||
| ); | ); | ||||
| @@ -347,6 +347,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro | |||||
| </Typography> | </Typography> | ||||
| <Stack direction="row" spacing={2} justifyContent="center" sx={{ mt: 2 }}> | <Stack direction="row" spacing={2} justifyContent="center" sx={{ mt: 2 }}> | ||||
| {/* | |||||
| <Button | <Button | ||||
| variant="contained" | variant="contained" | ||||
| color="error" | color="error" | ||||
| @@ -374,6 +375,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro | |||||
| {t("Continue")} | {t("Continue")} | ||||
| </Button> | </Button> | ||||
| )} | )} | ||||
| */} | |||||
| <Button | <Button | ||||
| sx={{ mt: 2, alignSelf: "flex-end" }} | sx={{ mt: 2, alignSelf: "flex-end" }} | ||||
| variant="outlined" | variant="outlined" | ||||
| @@ -25,9 +25,14 @@ | |||||
| "user": "用戶", | "user": "用戶", | ||||
| "User Group": "用戶群組", | "User Group": "用戶群組", | ||||
| "Items": "物料", | "Items": "物料", | ||||
| "Release": "放單", | |||||
| "Demand Forecast Setting": "需求預測設定", | "Demand Forecast Setting": "需求預測設定", | ||||
| "Equipment Type/Code": "使用設備-編號", | "Equipment Type/Code": "使用設備-編號", | ||||
| "Equipment": "設備", | "Equipment": "設備", | ||||
| "Time Information(mins)": "時間信息(分鐘)", | |||||
| "Processing Time": "生產時間", | |||||
| "Setup Time": "生產前預備時間", | |||||
| "Changeover Time": "生產後轉換時間", | |||||
| "Warehouse": "倉庫", | "Warehouse": "倉庫", | ||||
| "Supplier": "供應商", | "Supplier": "供應商", | ||||
| "Purchase Order":"採購單", | "Purchase Order":"採購單", | ||||
| @@ -127,9 +132,9 @@ | |||||
| "Date": "日期", | "Date": "日期", | ||||
| "Failed to submit scan data. Please try again.": "掃碼數據提交失敗. 請重試.", | "Failed to submit scan data. Please try again.": "掃碼數據提交失敗. 請重試.", | ||||
| "In Progress": "進行中", | "In Progress": "進行中", | ||||
| "Is Dark": "是否黑暗", | |||||
| "Is Dense": "是否密集", | |||||
| "Is Float": "是否浮動", | |||||
| "Is Dark": " 顔色深淺度", | |||||
| "Is Dense": "濃淡", | |||||
| "Is Float": "浮沉", | |||||
| "Job Order Code": "工單編號", | "Job Order Code": "工單編號", | ||||
| "Operator": "操作員", | "Operator": "操作員", | ||||
| "Output Qty": "輸出數量", | "Output Qty": "輸出數量", | ||||
| @@ -152,7 +157,7 @@ | |||||
| "In_Progress": "進行中", | "In_Progress": "進行中", | ||||
| "inProgress": "進行中", | "inProgress": "進行中", | ||||
| "Step Name": "步驟名稱", | |||||
| "Step Name": "名稱", | |||||
| "Stop QR Scan": "停止掃碼", | "Stop QR Scan": "停止掃碼", | ||||
| "Submit & Start": "提交並開始", | "Submit & Start": "提交並開始", | ||||
| "Total Steps": "總步驟數", | "Total Steps": "總步驟數", | ||||
| @@ -161,7 +166,7 @@ | |||||
| "View": "查看", | "View": "查看", | ||||
| "Back": "返回", | "Back": "返回", | ||||
| "BoM Material": "物料清單", | "BoM Material": "物料清單", | ||||
| "Is Dark | Dense | Float": "是否黑暗 | 密集 | 浮動", | |||||
| "Is Dark | Dense | Float": "顔色深淺度 | 濃淡 | 浮沉", | |||||
| "Item Code": "物料編號", | "Item Code": "物料編號", | ||||
| "Item Name": "物料名稱", | "Item Name": "物料名稱", | ||||
| "Job Order Info": "工單信息", | "Job Order Info": "工單信息", | ||||
| @@ -193,6 +198,8 @@ | |||||
| "Production Output Data": "生產輸出數據", | "Production Output Data": "生產輸出數據", | ||||
| "Step Information": "步驟信息", | "Step Information": "步驟信息", | ||||
| "Stop": "停止", | "Stop": "停止", | ||||
| "Putaway Detail": "上架詳情" | |||||
| "Putaway Detail": "上架詳情", | |||||
| "Lines with sufficient stock: ": "足夠庫存:", | |||||
| "Lines with insufficient stock: ": "庫存不足:", | |||||
| "Total lines: ": "總數量:" | |||||
| } | } | ||||
| @@ -7,6 +7,7 @@ | |||||
| "Warehouse temperature record": "倉庫溫度記錄", | "Warehouse temperature record": "倉庫溫度記錄", | ||||
| "Warehouse type": "倉庫類型", | "Warehouse type": "倉庫類型", | ||||
| "Last 6 hours": "過去6小時", | "Last 6 hours": "過去6小時", | ||||
| "Add some entries!": "添加一些物料!", | |||||
| "Last 24 hours": "過去24小時", | "Last 24 hours": "過去24小時", | ||||
| "Cold storage": "冷藏倉", | "Cold storage": "冷藏倉", | ||||
| "Normal temperature storage": "常溫倉", | "Normal temperature storage": "常溫倉", | ||||
| @@ -1,4 +1,5 @@ | |||||
| { | { | ||||
| "Demand Qty": "需求數量" | |||||
| "Demand Qty": "需求數量", | |||||
| "Add some entries!": "添加一些物料!" | |||||
| } | } | ||||
| @@ -1,6 +1,6 @@ | |||||
| { | { | ||||
| "Job Order": "工單", | "Job Order": "工單", | ||||
| "Create Job Order": "創建工單", | |||||
| "Create Job Order": "建立工單", | |||||
| "Edit Job Order Detail": "工單詳情", | "Edit Job Order Detail": "工單詳情", | ||||
| "Details": "細節", | "Details": "細節", | ||||
| "Actions": "操作", | "Actions": "操作", | ||||
| @@ -11,7 +11,7 @@ | |||||
| "UoM": "銷售單位", | "UoM": "銷售單位", | ||||
| "Status": "工單狀態", | "Status": "工單狀態", | ||||
| "Lot No.": "批號", | "Lot No.": "批號", | ||||
| "Bom": "物料清單", | |||||
| "Bom": "半成品/成品編號", | |||||
| "Release": "放單", | "Release": "放單", | ||||
| "Pending": "待掃碼", | "Pending": "待掃碼", | ||||
| "Pending for pick": "待提料", | "Pending for pick": "待提料", | ||||
| @@ -82,7 +82,11 @@ | |||||
| "Lot Availability": "批號可用性", | "Lot Availability": "批號可用性", | ||||
| "Pick Order Id": "提料單編號", | "Pick Order Id": "提料單編號", | ||||
| "Pick Order Code": "提料單編號", | "Pick Order Code": "提料單編號", | ||||
| "Select a printer": "選擇打印機", | |||||
| "Please select a printer": "請選擇打印機", | |||||
| "Next": "下一步", | |||||
| "Pick Order Conso Code": "提料單組合編號", | "Pick Order Conso Code": "提料單組合編號", | ||||
| "Enter the number of cartons": "請輸入箱數", | |||||
| "Pick Order Target Date": "提料單需求日期", | "Pick Order Target Date": "提料單需求日期", | ||||
| "Pick Order Status": "提料單狀態", | "Pick Order Status": "提料單狀態", | ||||
| "Second Scan Status": "對料狀態", | "Second Scan Status": "對料狀態", | ||||
| @@ -244,7 +248,7 @@ | |||||
| "productionDate": "生產日期", | "productionDate": "生產日期", | ||||
| "warehouse": "倉庫", | "warehouse": "倉庫", | ||||
| "Add Record": "添加記錄", | "Add Record": "添加記錄", | ||||
| "Add some entries!": "添加一些條目!", | |||||
| "Add some entries!": "添加一些物料!", | |||||
| "Clean Record": "清空記錄", | "Clean Record": "清空記錄", | ||||
| "Escalation History": "升級歷史", | "Escalation History": "升級歷史", | ||||
| "Escalation Info": "升級信息", | "Escalation Info": "升級信息", | ||||
| @@ -274,5 +278,194 @@ | |||||
| "Estimated Production Date": "預計生產日期及時間", | "Estimated Production Date": "預計生產日期及時間", | ||||
| "Plan Start": "預計生產日期及時間", | "Plan Start": "預計生產日期及時間", | ||||
| "Plan Start From": "預計生產日期及時間", | "Plan Start From": "預計生產日期及時間", | ||||
| "Plan Start To": "預計生產日期及時間至" | |||||
| "Plan Start To": "預計生產日期及時間至", | |||||
| "By-product": "副產品", | |||||
| "Complete Step": "完成步驟", | |||||
| "Defect": "缺陷", | |||||
| "Output from Process": "流程輸出", | |||||
| "Quantity": "數量", | |||||
| "Scrap": "廢料", | |||||
| "Unit": "單位", | |||||
| "Back to List": "返回列表", | |||||
| "Production Output Data Entry": "生產輸出數據輸入", | |||||
| "Step": "步驟", | |||||
| "Quality Check": "品質檢查", | |||||
| "Action": "操作", | |||||
| "Changeover Time (mins)": "生產後轉換時間(分鐘)", | |||||
| "Completed": "完成", | |||||
| "completed": "完成", | |||||
| "Date": "日期", | |||||
| "Failed to submit scan data. Please try again.": "掃碼數據提交失敗. 請重試.", | |||||
| "In Progress": "進行中", | |||||
| "Is Dark": " 顔色深淺度", | |||||
| "Is Dense": "濃淡", | |||||
| "Is Float": "浮沉", | |||||
| "Job Order Code": "工單編號", | |||||
| "Operator": "操作員", | |||||
| "Output Qty": "輸出數量", | |||||
| "Pending": "待處理", | |||||
| "pending": "待處理", | |||||
| "Please scan equipment code (optional if not required)": "請掃描設備編號(可選)", | |||||
| "Please scan operator code": "請掃描操作員編號", | |||||
| "Please scan operator code first": "請先掃描操作員編號", | |||||
| "Processing Time (mins)": "步驟時間(分鐘)", | |||||
| "Production Process Information": "生產流程信息", | |||||
| "Production Process Steps": "生產流程步驟", | |||||
| "Scan Operator & Equipment": "掃描操作員和設備", | |||||
| "Seq": "序號", | |||||
| "Setup Time (mins)": "生產前預備時間(分鐘)", | |||||
| "Start": "開始", | |||||
| "Start QR Scan": "開始掃碼", | |||||
| "Status": "狀態", | |||||
| "in_progress": "進行中", | |||||
| "In_Progress": "進行中", | |||||
| "inProgress": "進行中", | |||||
| "Step Name": "名稱", | |||||
| "Stop QR Scan": "停止掃碼", | |||||
| "Submit & Start": "提交並開始", | |||||
| "Total Steps": "總步驟數", | |||||
| "Unknown": "", | |||||
| "Validation failed. Please check operator and equipment.": "驗證失敗. 請檢查操作員和設備.", | |||||
| "View": "查看", | |||||
| "Back": "返回", | |||||
| "BoM Material": "半成品/成品清單", | |||||
| "Is Dark | Dense | Float": "顔色深淺度 | 濃淡 | 浮沉", | |||||
| "Item Code": "物料編號", | |||||
| "Item Name": "物料名稱", | |||||
| "Enter the number of cartons: ": "請輸入箱數:", | |||||
| "Number of cartons": "箱數", | |||||
| "You need to enter a number": "您需要輸入一個數字", | |||||
| "Number must be at least 1": "數字必須至少為1", | |||||
| "Confirm": "確認", | |||||
| "Cancel": "取消", | |||||
| "Print Pick Record": "打印板頭紙", | |||||
| "Printed Successfully.": "成功列印", | |||||
| "Job Order Info": "工單信息", | |||||
| "Matching Stock": "匹配庫存", | |||||
| "No data found": "沒有找到資料", | |||||
| "Print Quantity": "打印數量", | |||||
| "Select Printer": "選擇打印機", | |||||
| "Printer": "打印機", | |||||
| "Enter print quantity": "請輸入打印數量", | |||||
| "Production Priority": "生產優先級", | |||||
| "Please select a printer first": "請先選擇打印機", | |||||
| "Production Process": "工藝流程", | |||||
| "Production Process Line Remark": "工藝明細", | |||||
| "Remark": "明細", | |||||
| "Req. Qty": "需求數量", | |||||
| "Seq No": "序號", | |||||
| "Seq No Remark": "序號明細", | |||||
| "Stock Available": "庫存可用", | |||||
| "Stock Status": "庫存狀態", | |||||
| "Target Production Date": "目標生產日期", | |||||
| "Description": "描述", | |||||
| "id": "ID", | |||||
| "Finished lines": "完成行", | |||||
| "Invalid Stock In Line Id": "無效庫存行ID", | |||||
| "Production date": "生產日期", | |||||
| "Required Qty": "需求數量", | |||||
| "Total processes": "總流程數", | |||||
| "View Details": "查看詳情", | |||||
| "view stockin": "查看入庫", | |||||
| "Completed Step": "完成步驟", | |||||
| "Continue": "繼續", | |||||
| "Executing": "執行中", | |||||
| "Order Complete": "訂單完成", | |||||
| "Pause": "暫停", | |||||
| "Production Output Data": "生產輸出數據", | |||||
| "Step Information": "步驟信息", | |||||
| "Stop": "停止", | |||||
| "Putaway Detail": "上架詳情", | |||||
| "Lines with sufficient stock: ": "足夠庫存:", | |||||
| "Lines with insufficient stock: ": "庫存不足:", | |||||
| "Total lines: ": "總數量:", | |||||
| "Demand Forecast Setting": "需求預測設定", | |||||
| "Equipment Type/Code": "使用設備-編號", | |||||
| "Equipment": "設備", | |||||
| "Time Information(mins)": "時間信息(分鐘)", | |||||
| "Processing Time": "生產時間", | |||||
| "Setup Time": "生產前預備時間", | |||||
| "Changeover Time": "生產後轉換時間", | |||||
| "Warehouse": "倉庫", | |||||
| "Supplier": "供應商", | |||||
| "Purchase Order":"採購單", | |||||
| "Demand Forecast":"需求預測", | |||||
| "Pick Order": "提料單", | |||||
| "Deliver Order":"送貨訂單", | |||||
| "Project":"專案", | |||||
| "Product":"產品", | |||||
| "Material":"材料", | |||||
| "mat":"原料", | |||||
| "consumables": "消耗品", | |||||
| "non-consumables": "非消耗品", | |||||
| "fg": "成品", | |||||
| "sfg": "半成品", | |||||
| "item": "貨品", | |||||
| "FG":"成品", | |||||
| "FG & Material Demand Forecast Detail":"成品及材料需求預測詳情", | |||||
| "View item In-out And inventory Ledger":"查看物料出入庫及庫存日誌", | |||||
| "Delivery Order":"送貨訂單", | |||||
| "Detail Scheduling":"詳細排程", | |||||
| "Customer":"客戶", | |||||
| "qcItem":"品檢項目", | |||||
| "QC Check Item":"QC品檢項目", | |||||
| "QC Category":"QC品檢模板", | |||||
| "qcCategory":"品檢模板", | |||||
| "QC Check Template":"QC檢查模板", | |||||
| "Mail":"郵件", | |||||
| "Import Testing":"匯入測試", | |||||
| "Overview": "總覽", | |||||
| "Projects": "專案", | |||||
| "Create Project": "新增專案", | |||||
| "Task Template": "任務範本", | |||||
| "Create Task Template": "新增任務範本", | |||||
| "Qc Item": "QC 項目", | |||||
| "FG Production Schedule": "FG 生產排程", | |||||
| "Inventory": "庫存", | |||||
| "scheduling":"排程", | |||||
| "settings": "設定", | |||||
| "items": "物料", | |||||
| "edit":"編輯", | |||||
| "Edit Equipment Type":"設備類型詳情", | |||||
| "Edit Equipment":"設備詳情", | |||||
| "equipmentType":"設備類型", | |||||
| "Description":"描述", | |||||
| "Details": "詳情", | |||||
| "Equipment Type Details":"設備類型詳情", | |||||
| "Save":"儲存", | |||||
| "Cancel":"取消", | |||||
| "Equipment Details":"設備詳情", | |||||
| "Exclude Date":"排除日期", | |||||
| "Finished Goods Name":"成品名稱", | |||||
| "create": "新增", | |||||
| "hr": "小時", | |||||
| "hrs": "小時", | |||||
| "min": "分鐘", | |||||
| "mins": "分鐘", | |||||
| "Job Order": "工單", | |||||
| "Edit Job Order": "工單詳情", | |||||
| "Production": "生產流程", | |||||
| "Put Away": "上架", | |||||
| "Put Away Scan": "上架掃碼", | |||||
| "Finished Good Order": "成品出倉", | |||||
| "finishedGood": "成品", | |||||
| "Router": "執貨路線", | |||||
| "Job Order Pickexcution": "工單提料", | |||||
| "No data available": "沒有資料", | |||||
| "Start Scan": "開始掃碼", | |||||
| "Stop Scan": "停止掃碼", | |||||
| "Scan Result": "掃碼結果", | |||||
| "Expiry Date": "有效期", | |||||
| "Pick Order Code": "提料單編號", | |||||
| "Target Date": "需求日期", | |||||
| "Lot Required Pick Qty": "批號需求數量", | |||||
| "Job Order Match": "工單匹配", | |||||
| "All Pick Order Lots": "所有提料單批號", | |||||
| "Rows per page": "每頁行數", | |||||
| "No data available": "沒有資料", | |||||
| "jodetail": "工單細節", | |||||
| "Sign out": "登出" | |||||
| } | } | ||||
| @@ -2,6 +2,8 @@ | |||||
| "Purchase Order": "採購訂單", | "Purchase Order": "採購訂單", | ||||
| "Purchase Receipt": "處理採購來貨", | "Purchase Receipt": "處理採購來貨", | ||||
| "Code": "編號", | "Code": "編號", | ||||
| "row per page": "每頁行數", | |||||
| "Rows per page": "每頁行數", | |||||
| "OrderDate": "下單日期", | "OrderDate": "下單日期", | ||||
| "Order Date": "下單日期", | "Order Date": "下單日期", | ||||
| "Order Date To": "下單日期至", | "Order Date To": "下單日期至", | ||||
| @@ -63,7 +65,7 @@ | |||||
| "qty cannot be greater than remaining qty": "數量不能大於剩餘數量", | "qty cannot be greater than remaining qty": "數量不能大於剩餘數量", | ||||
| "acceptQty must not greater than": "揀收數量不能大於", | "acceptQty must not greater than": "揀收數量不能大於", | ||||
| "Record pol": "記錄採購訂單", | "Record pol": "記錄採購訂單", | ||||
| "Add some entries!": "添加條目!", | |||||
| "Add some entries!": "添加一些物料!", | |||||
| "draft": "草稿", | "draft": "草稿", | ||||
| "pending": "待處理", | "pending": "待處理", | ||||
| "determine1": "上報1", | "determine1": "上報1", | ||||