diff --git a/src/app/api/jo/actions.ts b/src/app/api/jo/actions.ts index 7d92e77..5890d78 100644 --- a/src/app/api/jo/actions.ts +++ b/src/app/api/jo/actions.ts @@ -604,6 +604,9 @@ export interface StockOutLineDetailResponse { location: string | null; availableQty: number | null; noLot: boolean; + /** Workbench API: matched suggest_pick_lot qty for this SOL lot line */ + //suggestedPickQty?: number | null; + //suggestedPickLotId?: number | null; } export interface LotDetailResponse { @@ -712,6 +715,21 @@ export const fetchJobOrderLotsHierarchicalByPickOrderId = cache(async (pickOrder }, ); }); + +/** JO Workbench: in−out available (matches scan-pick); stockouts include suggestedPickQty / suggestedPickLotId when SPL matches SOL lot line */ +/* +export const fetchJobOrderLotsHierarchicalByPickOrderIdWorkbench = cache( + async (pickOrderId: number) => { + return serverFetchJson( + `${BASE_API_URL}/jo/all-lots-hierarchical-by-pick-order-workbench/${pickOrderId}`, + { + method: "GET", + next: { tags: ["jo-hierarchical-workbench"] }, + }, + ); + }, +); +*/ // NOTE: Do NOT wrap in `cache()` because the list needs to reflect just-completed lines // immediately when navigating back from JobPickExecution. export const fetchAllJoPickOrders = async (type?: string | null, floor?: string | null) => { @@ -1076,6 +1094,32 @@ export const fetchCompletedJobOrderPickOrdersrecords = async (completedDate?: st cache: "no-store", }); }; +export const fetchJobOrderPickOrdersrecords = async ( + date?: string | null, + status?: string | null, +) => { + const params = new URLSearchParams(); + + if (date && String(date).trim() !== "") { + params.set("date", String(date).trim()); + } + if (status && String(status).trim() !== "" && String(status) !== "All") { + params.set("status", String(status).trim()); + } + + const q = params.toString() ? `?${params.toString()}` : ""; + return serverFetchJson(`${BASE_API_URL}/jo/job-order-pick-orders${q}`, { + method: "GET", + cache: "no-store", + }); +}; + +export const fetchJobOrderPickOrderLotDetailsForPick = cache(async (pickOrderId: number) => { + return serverFetchJson(`${BASE_API_URL}/jo/job-order-pick-order-lot-details/${pickOrderId}`, { + method: "GET", + headers: { "Content-Type": "application/json" } + }) +}) export const fetchJoForPrintQrCode = cache(async (date: string) => { return serverFetchJson( `${BASE_API_URL}/jo/joForPrintQrCode/${date}`, diff --git a/src/components/Jodetail/completeJobOrderRecord.tsx b/src/components/Jodetail/completeJobOrderRecord.tsx index 4b28be7..74aec53 100644 --- a/src/components/Jodetail/completeJobOrderRecord.tsx +++ b/src/components/Jodetail/completeJobOrderRecord.tsx @@ -32,8 +32,8 @@ import { useCallback, useEffect, useState, useRef, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { useRouter } from "next/navigation"; import { - fetchCompletedJobOrderPickOrdersrecords, - fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick, + fetchJobOrderPickOrdersrecords, + fetchJobOrderPickOrderLotDetailsForPick, PrintPickRecord } from "@/app/api/jo/actions"; import { fetchNameList, NameList } from "@/app/api/user/actions"; @@ -148,8 +148,8 @@ const CompleteJobOrderRecord: React.FC = ({ const errors = formProps.formState.errors; // 修改:使用新的 Job Order API 获取已完成的 Job Order Pick Orders(仅完成pick的) - const fetchCompletedJobOrderPickOrdersData = useCallback( - async (forDate?: string) => { + const fetchJobOrderPickOrdersData = useCallback( + async (forDate?: string, forStatus?: string) => { if (!currentUserId) return; setCompletedJobOrderPickOrdersLoading(true); @@ -160,21 +160,27 @@ const CompleteJobOrderRecord: React.FC = ({ : searchQuery.completedDate ? String(searchQuery.completedDate) : dayjs().format("YYYY-MM-DD"); - const completedJobOrderPickOrders = await fetchCompletedJobOrderPickOrdersrecords( - dateParam.trim() ? dateParam.trim() : null, + + const statusParam = + forStatus !== undefined + ? forStatus + : searchQuery.pickOrderStatus + ? String(searchQuery.pickOrderStatus) + : null; + + const data = await fetchJobOrderPickOrdersrecords( + dateParam?.trim() ? dateParam.trim() : null, + statusParam?.trim() ? statusParam.trim() : null, ); - const safeData = Array.isArray(completedJobOrderPickOrders) ? completedJobOrderPickOrders : []; + + const safeData = Array.isArray(data) ? data : []; setCompletedJobOrderPickOrders(safeData); setFilteredJobOrderPickOrders(safeData); - } catch (error) { - console.error("❌ Error fetching completed Job Order pick orders:", error); - setCompletedJobOrderPickOrders([]); - setFilteredJobOrderPickOrders([]); } finally { setCompletedJobOrderPickOrdersLoading(false); } }, - [currentUserId, searchQuery.completedDate], + [currentUserId, searchQuery.completedDate, searchQuery.pickOrderStatus], ); // 新增:获取 lot 详情数据(使用新的API) const fetchLotDetailsData = useCallback(async (pickOrderId: number) => { @@ -182,7 +188,7 @@ const CompleteJobOrderRecord: React.FC = ({ try { console.log("🔍 Fetching lot details for completed pick order:", pickOrderId); - const lotDetails = await fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId); + const lotDetails = await fetchJobOrderPickOrderLotDetailsForPick(pickOrderId); setDetailLotData(Array.isArray(lotDetails) ? lotDetails : []); console.log(" Fetched lot details:", lotDetails); @@ -198,9 +204,13 @@ const CompleteJobOrderRecord: React.FC = ({ useEffect(() => { if (!currentUserId) return; const d = searchQuery?.completedDate; + const s = searchQuery?.pickOrderStatus; + const dateStr = d != null && String(d).trim() !== "" ? String(d).trim() : ""; - void fetchCompletedJobOrderPickOrdersData(dateStr || undefined); - }, [currentUserId, searchQuery?.completedDate, fetchCompletedJobOrderPickOrdersData]); + const statusStr = s != null && String(s).trim() !== "" ? String(s).trim() : ""; + + void fetchJobOrderPickOrdersData(dateStr || undefined, statusStr || undefined); + }, [currentUserId, searchQuery?.completedDate, searchQuery?.pickOrderStatus, fetchJobOrderPickOrdersData]); // 修改:搜索功能(只更新 query;实际过滤交给 useEffect + date filter 统一处理) const handleSearch = useCallback((query: Record) => { @@ -316,6 +326,15 @@ const CompleteJobOrderRecord: React.FC = ({ paramName: "jobOrderCode", type: "text", }, + { + label: t("Pick Order Status"), + paramName: "pickOrderStatus", + type: "select-labelled", + options: [ + { label: t("Released"), value: "RELEASED" }, + { label: t("Completed"), value: "COMPLETED" }, + ], // 依你后端实际枚举 + }, { label: t("Job Order Item Name"), paramName: "jobOrderName", @@ -640,7 +659,9 @@ const CompleteJobOrderRecord: React.FC = ({ ) : ( - {paginatedData.map((jobOrderPickOrder) => ( + {paginatedData.map((jobOrderPickOrder) => { + const normalizedStatus = String(jobOrderPickOrder.pickOrderStatus ?? "").toLowerCase(); + return ( @@ -660,21 +681,18 @@ const CompleteJobOrderRecord: React.FC = ({ - + {jobOrderPickOrder.completedItems}/{jobOrderPickOrder.totalItems} {t("items completed")} - + + @@ -694,7 +712,9 @@ const CompleteJobOrderRecord: React.FC = ({ - ))} + ); + })} + )} diff --git a/src/i18n/zh/jo.json b/src/i18n/zh/jo.json index 9defda1..9885ad9 100644 --- a/src/i18n/zh/jo.json +++ b/src/i18n/zh/jo.json @@ -167,6 +167,9 @@ "View Details": "查看詳情", "Skip": "跳過", "Handler": "提料員", + "RELEASED": "已放單", + "Released": "已放單", + "COMPLETED": "已完成", "Now": "現時", "Last updated": "最後更新", "Auto-refresh every 5 minutes": "每5分鐘自動刷新",