| @@ -1,7 +1,7 @@ | |||||
| "use server"; | "use server"; | ||||
| import { cache } from 'react'; | 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 { JoStatus, Machine, Operator } from "."; | ||||
| import { BASE_API_URL } from "@/config/api"; | import { BASE_API_URL } from "@/config/api"; | ||||
| import { revalidateTag } from "next/cache"; | import { revalidateTag } from "next/cache"; | ||||
| @@ -103,6 +103,17 @@ export interface AssignJobOrderResponse { | |||||
| errorPosition: string | null; | errorPosition: string | null; | ||||
| } | } | ||||
| export interface PrintPickRecordRequest{ | |||||
| pickOrderId: number; | |||||
| printerId: number; | |||||
| printQty: number; | |||||
| } | |||||
| export interface PrintPickRecordResponse{ | |||||
| success: boolean; | |||||
| message?: string | |||||
| } | |||||
| export const recordSecondScanIssue = cache(async ( | export const recordSecondScanIssue = cache(async ( | ||||
| pickOrderId: number, | pickOrderId: number, | ||||
| itemId: number, | itemId: number, | ||||
| @@ -113,6 +124,7 @@ export const recordSecondScanIssue = cache(async ( | |||||
| reason: string; | reason: string; | ||||
| createdBy: number; | createdBy: number; | ||||
| } | } | ||||
| ) => { | ) => { | ||||
| return serverFetchJson<any>( | return serverFetchJson<any>( | ||||
| `${BASE_API_URL}/jo/second-scan-issue/${pickOrderId}/${itemId}`, | `${BASE_API_URL}/jo/second-scan-issue/${pickOrderId}/${itemId}`, | ||||
| @@ -317,3 +329,20 @@ export const fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick = cache(a | |||||
| headers: { "Content-Type": "application/json" } | 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 () =>{ | const handleDraft = useCallback(async () =>{ | ||||
| try{ | try{ | ||||
| if (fgPickOrdersData.length === 0) { | 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]; | const currentFgOrder = fgPickOrdersData[0]; | ||||
| @@ -32,7 +32,8 @@ import { useTranslation } from "react-i18next"; | |||||
| import { useRouter } from "next/navigation"; | import { useRouter } from "next/navigation"; | ||||
| import { | import { | ||||
| fetchCompletedJobOrderPickOrdersrecords, | fetchCompletedJobOrderPickOrdersrecords, | ||||
| fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick | |||||
| fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick, | |||||
| PrintPickRecord | |||||
| } from "@/app/api/jo/actions"; | } from "@/app/api/jo/actions"; | ||||
| import { fetchNameList, NameList } from "@/app/api/user/actions"; | import { fetchNameList, NameList } from "@/app/api/user/actions"; | ||||
| import { | import { | ||||
| @@ -42,6 +43,7 @@ import { | |||||
| import SearchBox, { Criterion } from "../SearchBox"; | 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"; | |||||
| interface Props { | interface Props { | ||||
| filterArgs: Record<string, any>; | 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 信息 | // ✅ 修改:如果显示详情视图,渲染 Job Order 详情和 Lot 信息 | ||||
| if (showDetailView && selectedJobOrderPickOrder) { | if (showDetailView && selectedJobOrderPickOrder) { | ||||
| return ( | return ( | ||||
| @@ -332,8 +372,17 @@ const CompleteJobOrderRecord: React.FC<Props> = ({ filterArgs }) => { | |||||
| <Typography variant="subtitle1"> | <Typography variant="subtitle1"> | ||||
| <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 }}> | |||||
| <Button | |||||
| variant="contained" | |||||
| color="primary" | |||||
| onClick={handlePickRecord} | |||||
| sx={{ mt: 1 }} | |||||
| > | |||||
| {t("Print Pick Record")} | |||||
| </Button> | |||||
| </Stack> | |||||
| </CardContent> | </CardContent> | ||||
| </Card> | </Card> | ||||
| @@ -252,5 +252,7 @@ | |||||
| "acceptedWeight": "接受重量", | "acceptedWeight": "接受重量", | ||||
| "receivedQty": "接收數量", | "receivedQty": "接收數量", | ||||
| "stock in information": "庫存信息", | "stock in information": "庫存信息", | ||||
| "No Uom": "沒有單位" | |||||
| "No Uom": "沒有單位", | |||||
| "Print Pick Record" : "打印板頭紙", | |||||
| "Printed Successfully." : "成功列印" | |||||
| } | } | ||||
| @@ -305,7 +305,7 @@ | |||||
| "Hide Completed: OFF": "完成: OFF", | "Hide Completed: OFF": "完成: OFF", | ||||
| "Hide Completed: ON": "完成: ON", | "Hide Completed: ON": "完成: ON", | ||||
| "Number must be at least 1": "數量至少為1", | "Number must be at least 1": "數量至少為1", | ||||
| "Printed Successfully.": "打印成功。", | |||||
| "Printed Successfully.": "成功列印", | |||||
| "Product": "產品", | "Product": "產品", | ||||
| "You need to enter a number": "您需要輸入一個數字", | "You need to enter a number": "您需要輸入一個數字", | ||||
| "Available in warehouse": "在倉庫中可用", | "Available in warehouse": "在倉庫中可用", | ||||