| @@ -26,7 +26,7 @@ const jo: React.FC = async () => { | |||
| {t("Job Order")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["jo", "common", "purchaseOrder", "dashboard"]}> {/* TODO: Improve */} | |||
| <I18nProvider namespaces={["jo", "common", "purchaseOrder", "dashboard","common"]}> {/* TODO: Improve */} | |||
| <Suspense fallback={<JoSearch.Loading />}> | |||
| <JoSearch /> | |||
| </Suspense> | |||
| @@ -17,7 +17,7 @@ const PurchaseOrder: React.FC = async () => { | |||
| // preloadClaims(); | |||
| return ( | |||
| <> | |||
| <I18nProvider namespaces={["purchaseOrder", "common", "items"]}> | |||
| <I18nProvider namespaces={["purchaseOrder", "common", "items","dashboard"]}> | |||
| <Stack | |||
| direction="row" | |||
| justifyContent="space-between" | |||
| @@ -16,7 +16,7 @@ import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerP | |||
| import { fetchStockInLineInfo } from "@/app/api/po/actions"; | |||
| import JoRelease from "./JoRelease"; | |||
| import { submitDialog } from "../Swal/CustomAlerts"; | |||
| import ProductionProcessJobOrderDetail from "../ProductionProcess/ProductionProcessJobOrderDetail"; | |||
| type Props = { | |||
| id?: number; | |||
| defaultValues: Partial<JoDetail> | undefined; | |||
| @@ -192,10 +192,16 @@ const JoSave: React.FC<Props> = ({ | |||
| {serverError} | |||
| </Typography> | |||
| )} | |||
| {/* | |||
| <ActionButtons handleRelease={handleRelease} handleStart={handleStart}/> | |||
| <InfoCard /> | |||
| <JoRelease pickLines={pickLines} handleRelease={handleRelease}/> | |||
| <PickTable /> | |||
| */} | |||
| {id ? ( | |||
| <ProductionProcessJobOrderDetail jobOrderId={id} onBack={handleBack} fromJosave={true}/> | |||
| ) : null} | |||
| {/* | |||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | |||
| <Button | |||
| variant="outlined" | |||
| @@ -205,6 +211,7 @@ const JoSave: React.FC<Props> = ({ | |||
| {t("Back")} | |||
| </Button> | |||
| </Stack> | |||
| */} | |||
| </Stack> | |||
| </FormProvider> | |||
| </> | |||
| @@ -33,6 +33,8 @@ import { | |||
| fetchCompletedJobOrderPickOrders, | |||
| fetchCompletedJobOrderPickOrderRecords | |||
| } from "@/app/api/jo/actions"; | |||
| import { fetchPrinterCombo } from "@/app/api/settings/printer"; | |||
| import { PrinterCombo } from "@/app/api/settings/printer"; | |||
| interface Props { | |||
| pickOrders: PickOrderResult[]; | |||
| } | |||
| @@ -63,6 +65,7 @@ const [hasAssignedJobOrders, setHasAssignedJobOrders] = useState(false); | |||
| const [hasDataTab0, setHasDataTab0] = useState(false); | |||
| const [hasDataTab1, setHasDataTab1] = useState(false); | |||
| const hasAnyAssignedData = hasDataTab0 || hasDataTab1; | |||
| const [printers, setPrinters] = useState<PrinterCombo[]>([]); | |||
| const [hideCompletedUntilNext, setHideCompletedUntilNext] = useState<boolean>( | |||
| typeof window !== 'undefined' && localStorage.getItem('hideCompletedUntilNext') === 'true' | |||
| ); | |||
| @@ -92,6 +95,19 @@ const hasAnyAssignedData = hasDataTab0 || hasDataTab1; | |||
| 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(() => { | |||
| const onAssigned = () => { | |||
| localStorage.removeItem('hideCompletedUntilNext'); | |||
| @@ -466,7 +482,7 @@ const hasAnyAssignedData = hasDataTab0 || hasDataTab1; | |||
| p: 2 | |||
| }}> | |||
| {tabIndex === 0 && <JobPickExecution filterArgs={filterArgs} />} | |||
| {tabIndex === 1 && <CompleteJobOrderRecord filterArgs={filterArgs} />} | |||
| {tabIndex === 1 && <CompleteJobOrderRecord filterArgs={filterArgs} printerCombo={printers} />} | |||
| {tabIndex === 2 && <JobPickExecutionsecondscan filterArgs={filterArgs} />} | |||
| {/* {tabIndex === 3 && <FInishedJobOrderRecord filterArgs={filterArgs} />} */} | |||
| </Box> | |||
| @@ -25,6 +25,7 @@ import { | |||
| AccordionSummary, | |||
| AccordionDetails, | |||
| Checkbox, | |||
| Autocomplete, | |||
| } from "@mui/material"; | |||
| import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; | |||
| import { useCallback, useEffect, useState, useRef, useMemo } from "react"; | |||
| @@ -44,9 +45,10 @@ import SearchBox, { Criterion } from "../SearchBox"; | |||
| import { useSession } from "next-auth/react"; | |||
| import { SessionWithTokens } from "@/config/authConfig"; | |||
| import Swal from "sweetalert2"; | |||
| import { PrinterCombo } from "@/app/api/settings/printer"; | |||
| interface Props { | |||
| filterArgs: Record<string, any>; | |||
| printerCombo: PrinterCombo[]; | |||
| } | |||
| // 修改:已完成的 Job Order Pick Order 接口 | |||
| @@ -99,7 +101,7 @@ interface LotDetail { | |||
| uomDesc: string; | |||
| } | |||
| const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs ,printerCombo=[]}) => { | |||
| const { t } = useTranslation("jo"); | |||
| const router = useRouter(); | |||
| 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 [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({ | |||
| 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"); | |||
| 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", | |||
| icon: "success", | |||
| text: t("Printed Successfully."), | |||
| showConfirmButton: false, | |||
| 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 信息 | |||
| if (showDetailView && selectedJobOrderPickOrder) { | |||
| return ( | |||
| @@ -373,16 +432,18 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| <strong>{t("Required Qty")}:</strong> {selectedJobOrderPickOrder.reqQty} {selectedJobOrderPickOrder.uom} | |||
| </Typography> | |||
| </Stack> | |||
| {/* | |||
| <Stack direction="row" spacing={4} useFlexGap flexWrap="wrap" sx={{ mt: 2 }}> | |||
| <Button | |||
| variant="contained" | |||
| color="primary" | |||
| onClick={handlePickRecord} | |||
| onClick={() => handlePickRecord(selectedJobOrderPickOrder)} | |||
| sx={{ mt: 1 }} | |||
| > | |||
| {t("Print Pick Record")} | |||
| </Button> | |||
| </Stack> | |||
| */} | |||
| </CardContent> | |||
| </Card> | |||
| @@ -538,26 +599,56 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}> | |||
| {t("Total")}: {filteredJobOrderPickOrders.length} {t("completed Job Order pick orders with matching")} | |||
| </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 ? ( | |||
| <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}> | |||
| <CardContent> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center"> | |||
| <Box> | |||
| <Typography variant="h6"> | |||
| {jobOrderPickOrder.pickOrderCode} | |||
| {jobOrderPickOrder.jobOrderCode} | |||
| </Typography> | |||
| <Typography variant="body2" color="text.secondary"> | |||
| {jobOrderPickOrder.jobOrderName} - {jobOrderPickOrder.jobOrderCode} | |||
| {jobOrderPickOrder.jobOrderName} - {jobOrderPickOrder.pickOrderCode} | |||
| </Typography> | |||
| <Typography variant="body2" color="text.secondary"> | |||
| {t("Completed")}: {new Date(jobOrderPickOrder.completedDate).toLocaleString()} | |||
| @@ -566,6 +657,7 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| {t("Target Date")}: {jobOrderPickOrder.pickOrderTargetDate} | |||
| </Typography> | |||
| </Box> | |||
| <Box> | |||
| <Chip | |||
| label={t(jobOrderPickOrder.pickOrderStatus) } | |||
| @@ -592,6 +684,16 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| > | |||
| {t("View Details")} | |||
| </Button> | |||
| <Button | |||
| variant="contained" | |||
| color="primary" | |||
| onClick={() => handlePickRecord(jobOrderPickOrder)} | |||
| sx={{ mt: 1 }} | |||
| > | |||
| {t("Print Pick Record")} | |||
| </Button> | |||
| </CardActions> | |||
| </Card> | |||
| ))} | |||
| @@ -101,7 +101,7 @@ const PoSearchList: React.FC<{ | |||
| selectedPoId: number; | |||
| onSelect: (po: PoResult) => void; | |||
| }> = ({ poList, selectedPoId, onSelect }) => { | |||
| const { t } = useTranslation("purchaseOrder"); | |||
| const { t } = useTranslation(["purchaseOrder", "dashboard"]); | |||
| const [searchTerm, setSearchTerm] = useState(''); | |||
| const filteredPoList = useMemo(() => { | |||
| @@ -963,7 +963,7 @@ const closeNewModal = useCallback(() => { | |||
| ); | |||
| } | |||
| const NoRowsOverlay: React.FC = () => { | |||
| const { t } = useTranslation("home"); | |||
| const { t } = useTranslation("purchaseOrder"); | |||
| return ( | |||
| <Box | |||
| display="flex" | |||
| @@ -112,7 +112,7 @@ function InputDataGrid<T, V, E>({ | |||
| const { | |||
| t, | |||
| // i18n: { language }, | |||
| } = useTranslation("purchaseOrder"); | |||
| } = useTranslation(["purchaseOrder","dashboard"]); | |||
| const formKey = _formKey.toString(); | |||
| const { setValue, getValues } = useFormContext(); | |||
| const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | |||
| @@ -380,7 +380,7 @@ const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => { | |||
| return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>; | |||
| }; | |||
| const NoRowsOverlay: React.FC = () => { | |||
| const { t } = useTranslation("home"); | |||
| const { t } = useTranslation("purchaseOrder"); | |||
| return ( | |||
| <Box | |||
| display="flex" | |||
| @@ -39,7 +39,7 @@ const PoSearch: React.FC<Props> = ({ | |||
| const [selectAll, setSelectAll] = useState(false); | |||
| const [filteredPo, setFilteredPo] = useState<PoResult[]>(po); | |||
| const [filterArgs, setFilterArgs] = useState<Record<string, any>>({estimatedArrivalDate : dayjsToDateString(dayjs(), "input")}); | |||
| const { t } = useTranslation("purchaseOrder"); | |||
| const { t } = useTranslation(["purchaseOrder", "dashboard"]); | |||
| const router = useRouter(); | |||
| const [pagingController, setPagingController] = useState( | |||
| defaultPagingController, | |||
| @@ -489,10 +489,25 @@ const ProductionProcessDetail: React.FC<ProductProcessDetailProps> = ({ | |||
| <TableCell>{t("Description")}</TableCell> | |||
| <TableCell>{t("Equipment Type/Code")}</TableCell> | |||
| <TableCell>{t("Operator")}</TableCell> | |||
| {/*} | |||
| <TableCell>{t("Processing Time (mins)")}</TableCell> | |||
| <TableCell>{t("Setup 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("Action")}</TableCell> | |||
| </TableRow> | |||
| @@ -516,10 +531,12 @@ const ProductionProcessDetail: React.FC<ProductProcessDetailProps> = ({ | |||
| <TableCell><Typography fontWeight={500}>{line.description || "-"}</Typography></TableCell> | |||
| <TableCell><Typography fontWeight={500}>{equipmentName}</Typography></TableCell> | |||
| <TableCell><Typography fontWeight={500}>{line.operatorName}</Typography></TableCell> | |||
| {/* | |||
| <TableCell><Typography fontWeight={500}>{line.durationInMinutes} </Typography></TableCell> | |||
| <TableCell><Typography fontWeight={500}>{line.prepTimeInMinutes} </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"> | |||
| {isCompleted ? ( | |||
| <Chip label={t("Completed")} color="success" size="small" | |||
| @@ -46,11 +46,13 @@ interface JobOrderLine { | |||
| interface ProductProcessJobOrderDetailProps { | |||
| jobOrderId: number; | |||
| onBack: () => void; | |||
| fromJosave?: boolean; | |||
| } | |||
| const ProductionProcessJobOrderDetail: React.FC<ProductProcessJobOrderDetailProps> = ({ | |||
| jobOrderId, | |||
| onBack, | |||
| fromJosave, | |||
| }) => { | |||
| const { t } = useTranslation(); | |||
| const [loading, setLoading] = useState(false); | |||
| @@ -363,7 +365,7 @@ const handleRelease = useCallback(() => { | |||
| <Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}> | |||
| {t("Lines with insufficient stock: ")}<strong style={{ color: "red" }}>{stockCounts.insufficient}</strong> | |||
| </Typography> | |||
| {!fromJosave && ( | |||
| <Button | |||
| variant="contained" | |||
| color="primary" | |||
| @@ -372,6 +374,7 @@ const handleRelease = useCallback(() => { | |||
| > | |||
| {t("Release")} | |||
| </Button> | |||
| )} | |||
| </Stack> | |||
| </CardContent> | |||
| </Card> | |||
| @@ -414,9 +417,15 @@ const handleRelease = useCallback(() => { | |||
| <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | |||
| <Tab label={t("Job Order Info")} /> | |||
| <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> | |||
| </Box> | |||
| @@ -424,6 +433,7 @@ const handleRelease = useCallback(() => { | |||
| <Box sx={{ p: 2 }}> | |||
| {tabIndex === 0 && <InfoCardContent />} | |||
| {tabIndex === 1 && <PickTableContent />} | |||
| {tabIndex === 2 && ( | |||
| <ProductionProcessDetail | |||
| jobOrderId={jobOrderId} | |||
| @@ -435,6 +445,7 @@ const handleRelease = useCallback(() => { | |||
| )} | |||
| {tabIndex === 3 && <ProductionProcessesLineRemarkTableContent />} | |||
| {tabIndex === 4 && <JobPickExecutionsecondscan filterArgs={{ jobOrderId: jobOrderId }} />} | |||
| </Box> | |||
| </Box> | |||
| ); | |||
| @@ -347,6 +347,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro | |||
| </Typography> | |||
| <Stack direction="row" spacing={2} justifyContent="center" sx={{ mt: 2 }}> | |||
| {/* | |||
| <Button | |||
| variant="contained" | |||
| color="error" | |||
| @@ -374,6 +375,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro | |||
| {t("Continue")} | |||
| </Button> | |||
| )} | |||
| */} | |||
| <Button | |||
| sx={{ mt: 2, alignSelf: "flex-end" }} | |||
| variant="outlined" | |||
| @@ -25,9 +25,14 @@ | |||
| "user": "用戶", | |||
| "User Group": "用戶群組", | |||
| "Items": "物料", | |||
| "Release": "放單", | |||
| "Demand Forecast Setting": "需求預測設定", | |||
| "Equipment Type/Code": "使用設備-編號", | |||
| "Equipment": "設備", | |||
| "Time Information(mins)": "時間信息(分鐘)", | |||
| "Processing Time": "生產時間", | |||
| "Setup Time": "生產前預備時間", | |||
| "Changeover Time": "生產後轉換時間", | |||
| "Warehouse": "倉庫", | |||
| "Supplier": "供應商", | |||
| "Purchase Order":"採購單", | |||
| @@ -127,9 +132,9 @@ | |||
| "Date": "日期", | |||
| "Failed to submit scan data. Please try again.": "掃碼數據提交失敗. 請重試.", | |||
| "In Progress": "進行中", | |||
| "Is Dark": "是否黑暗", | |||
| "Is Dense": "是否密集", | |||
| "Is Float": "是否浮動", | |||
| "Is Dark": " 顔色深淺度", | |||
| "Is Dense": "濃淡", | |||
| "Is Float": "浮沉", | |||
| "Job Order Code": "工單編號", | |||
| "Operator": "操作員", | |||
| "Output Qty": "輸出數量", | |||
| @@ -152,7 +157,7 @@ | |||
| "In_Progress": "進行中", | |||
| "inProgress": "進行中", | |||
| "Step Name": "步驟名稱", | |||
| "Step Name": "名稱", | |||
| "Stop QR Scan": "停止掃碼", | |||
| "Submit & Start": "提交並開始", | |||
| "Total Steps": "總步驟數", | |||
| @@ -161,7 +166,7 @@ | |||
| "View": "查看", | |||
| "Back": "返回", | |||
| "BoM Material": "物料清單", | |||
| "Is Dark | Dense | Float": "是否黑暗 | 密集 | 浮動", | |||
| "Is Dark | Dense | Float": "顔色深淺度 | 濃淡 | 浮沉", | |||
| "Item Code": "物料編號", | |||
| "Item Name": "物料名稱", | |||
| "Job Order Info": "工單信息", | |||
| @@ -193,6 +198,8 @@ | |||
| "Production Output Data": "生產輸出數據", | |||
| "Step Information": "步驟信息", | |||
| "Stop": "停止", | |||
| "Putaway Detail": "上架詳情" | |||
| "Putaway Detail": "上架詳情", | |||
| "Lines with sufficient stock: ": "足夠庫存:", | |||
| "Lines with insufficient stock: ": "庫存不足:", | |||
| "Total lines: ": "總數量:" | |||
| } | |||
| @@ -7,6 +7,7 @@ | |||
| "Warehouse temperature record": "倉庫溫度記錄", | |||
| "Warehouse type": "倉庫類型", | |||
| "Last 6 hours": "過去6小時", | |||
| "Add some entries!": "添加一些物料!", | |||
| "Last 24 hours": "過去24小時", | |||
| "Cold storage": "冷藏倉", | |||
| "Normal temperature storage": "常溫倉", | |||
| @@ -1,4 +1,5 @@ | |||
| { | |||
| "Demand Qty": "需求數量" | |||
| "Demand Qty": "需求數量", | |||
| "Add some entries!": "添加一些物料!" | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| { | |||
| "Job Order": "工單", | |||
| "Create Job Order": "創建工單", | |||
| "Create Job Order": "建立工單", | |||
| "Edit Job Order Detail": "工單詳情", | |||
| "Details": "細節", | |||
| "Actions": "操作", | |||
| @@ -11,7 +11,7 @@ | |||
| "UoM": "銷售單位", | |||
| "Status": "工單狀態", | |||
| "Lot No.": "批號", | |||
| "Bom": "物料清單", | |||
| "Bom": "半成品/成品編號", | |||
| "Release": "放單", | |||
| "Pending": "待掃碼", | |||
| "Pending for pick": "待提料", | |||
| @@ -82,7 +82,11 @@ | |||
| "Lot Availability": "批號可用性", | |||
| "Pick Order Id": "提料單編號", | |||
| "Pick Order Code": "提料單編號", | |||
| "Select a printer": "選擇打印機", | |||
| "Please select a printer": "請選擇打印機", | |||
| "Next": "下一步", | |||
| "Pick Order Conso Code": "提料單組合編號", | |||
| "Enter the number of cartons": "請輸入箱數", | |||
| "Pick Order Target Date": "提料單需求日期", | |||
| "Pick Order Status": "提料單狀態", | |||
| "Second Scan Status": "對料狀態", | |||
| @@ -244,7 +248,7 @@ | |||
| "productionDate": "生產日期", | |||
| "warehouse": "倉庫", | |||
| "Add Record": "添加記錄", | |||
| "Add some entries!": "添加一些條目!", | |||
| "Add some entries!": "添加一些物料!", | |||
| "Clean Record": "清空記錄", | |||
| "Escalation History": "升級歷史", | |||
| "Escalation Info": "升級信息", | |||
| @@ -274,5 +278,194 @@ | |||
| "Estimated Production Date": "預計生產日期及時間", | |||
| "Plan Start": "預計生產日期及時間", | |||
| "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 Receipt": "處理採購來貨", | |||
| "Code": "編號", | |||
| "row per page": "每頁行數", | |||
| "Rows per page": "每頁行數", | |||
| "OrderDate": "下單日期", | |||
| "Order Date": "下單日期", | |||
| "Order Date To": "下單日期至", | |||
| @@ -63,7 +65,7 @@ | |||
| "qty cannot be greater than remaining qty": "數量不能大於剩餘數量", | |||
| "acceptQty must not greater than": "揀收數量不能大於", | |||
| "Record pol": "記錄採購訂單", | |||
| "Add some entries!": "添加條目!", | |||
| "Add some entries!": "添加一些物料!", | |||
| "draft": "草稿", | |||
| "pending": "待處理", | |||
| "determine1": "上報1", | |||