| @@ -1,7 +1,7 @@ | |||
| "use server"; | |||
| import { cache } from 'react'; | |||
| import { Pageable, serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { Pageable, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; | |||
| import { JoStatus, Machine, Operator } from "."; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { revalidateTag } from "next/cache"; | |||
| @@ -103,6 +103,17 @@ export interface AssignJobOrderResponse { | |||
| errorPosition: string | null; | |||
| } | |||
| export interface PrintPickRecordRequest{ | |||
| pickOrderId: number; | |||
| printerId: number; | |||
| printQty: number; | |||
| } | |||
| export interface PrintPickRecordResponse{ | |||
| success: boolean; | |||
| message?: string | |||
| } | |||
| export const recordSecondScanIssue = cache(async ( | |||
| pickOrderId: number, | |||
| itemId: number, | |||
| @@ -113,6 +124,7 @@ export const recordSecondScanIssue = cache(async ( | |||
| reason: string; | |||
| createdBy: number; | |||
| } | |||
| ) => { | |||
| return serverFetchJson<any>( | |||
| `${BASE_API_URL}/jo/second-scan-issue/${pickOrderId}/${itemId}`, | |||
| @@ -317,3 +329,20 @@ export const fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick = cache(a | |||
| headers: { "Content-Type": "application/json" } | |||
| }) | |||
| }) | |||
| export async function PrintPickRecord(request: PrintPickRecordRequest){ | |||
| const params = new URLSearchParams(); | |||
| params.append('pickOrderId', request.pickOrderId.toString()) | |||
| params.append('printerId', request.printerId.toString()) | |||
| if (request.printQty !== null && request.printQty !== undefined) { | |||
| params.append('printQty', request.printQty.toString()); | |||
| } | |||
| const response = await serverFetchWithNoContent(`${BASE_API_URL}/jo/print-PickRecord?${params.toString()}`,{ | |||
| method: "GET" | |||
| }); | |||
| return { success: true, message: "Print job sent successfully (Pick Record)" } as PrintPickRecordResponse; | |||
| } | |||
| @@ -68,8 +68,8 @@ const PickOrderSearch: React.FC<Props> = ({ pickOrders }) => { | |||
| const handleDraft = useCallback(async () =>{ | |||
| try{ | |||
| if (fgPickOrdersData.length === 0) { | |||
| console.error("No FG Pick order data available"); | |||
| return; | |||
| console.error("No FG Pick order data available"); | |||
| return; | |||
| } | |||
| const currentFgOrder = fgPickOrdersData[0]; | |||
| @@ -32,7 +32,8 @@ import { useTranslation } from "react-i18next"; | |||
| import { useRouter } from "next/navigation"; | |||
| import { | |||
| fetchCompletedJobOrderPickOrdersrecords, | |||
| fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick | |||
| fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick, | |||
| PrintPickRecord | |||
| } from "@/app/api/jo/actions"; | |||
| import { fetchNameList, NameList } from "@/app/api/user/actions"; | |||
| import { | |||
| @@ -42,6 +43,7 @@ import { | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| import { useSession } from "next-auth/react"; | |||
| import { SessionWithTokens } from "@/config/authConfig"; | |||
| import Swal from "sweetalert2"; | |||
| interface Props { | |||
| filterArgs: Record<string, any>; | |||
| @@ -295,6 +297,44 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| })); | |||
| }, []); | |||
| const handlePickRecord = useCallback(async () =>{ | |||
| try{ | |||
| if (!selectedJobOrderPickOrder) { | |||
| 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 | |||
| }; | |||
| console.log("Printing Pick Record with request: ", printRequest); | |||
| const response = await PrintPickRecord(printRequest) | |||
| console.log("Print Pick Record response: ", response); | |||
| if(response.success){ | |||
| Swal.fire({ | |||
| position: "bottom-end", | |||
| icon: "info", | |||
| text: t("Printed Successfully."), | |||
| showConfirmButton: false, | |||
| timer: 1500 | |||
| }); | |||
| } else { | |||
| console.error("Print failed: ", response.message); | |||
| } | |||
| }catch(error){ | |||
| console.error("error: ", error) | |||
| } | |||
| },[t, selectedJobOrderPickOrder]); | |||
| // ✅ 修改:如果显示详情视图,渲染 Job Order 详情和 Lot 信息 | |||
| if (showDetailView && selectedJobOrderPickOrder) { | |||
| return ( | |||
| @@ -332,8 +372,17 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| <Typography variant="subtitle1"> | |||
| <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} | |||
| sx={{ mt: 1 }} | |||
| > | |||
| {t("Print Pick Record")} | |||
| </Button> | |||
| </Stack> | |||
| </CardContent> | |||
| </Card> | |||
| @@ -252,5 +252,7 @@ | |||
| "acceptedWeight": "接受重量", | |||
| "receivedQty": "接收數量", | |||
| "stock in information": "庫存信息", | |||
| "No Uom": "沒有單位" | |||
| "No Uom": "沒有單位", | |||
| "Print Pick Record" : "打印板頭紙", | |||
| "Printed Successfully." : "成功列印" | |||
| } | |||
| @@ -305,7 +305,7 @@ | |||
| "Hide Completed: OFF": "完成: OFF", | |||
| "Hide Completed: ON": "完成: ON", | |||
| "Number must be at least 1": "數量至少為1", | |||
| "Printed Successfully.": "打印成功。", | |||
| "Printed Successfully.": "成功列印", | |||
| "Product": "產品", | |||
| "You need to enter a number": "您需要輸入一個數字", | |||
| "Available in warehouse": "在倉庫中可用", | |||