From aba67740797f54e77ac9ef34e3e1ffd430694869 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Thu, 23 Oct 2025 11:39:04 +0800 Subject: [PATCH] update --- src/app/api/pickOrder/actions.ts | 29 ++- .../FinishedGoodFloorLanePanel.tsx | 2 +- .../GoodPickExecutionRecord.tsx | 238 +++++++++++------- .../GoodPickExecutiondetail.tsx | 95 +------ 4 files changed, 178 insertions(+), 186 deletions(-) diff --git a/src/app/api/pickOrder/actions.ts b/src/app/api/pickOrder/actions.ts index eb1c639..d05db53 100644 --- a/src/app/api/pickOrder/actions.ts +++ b/src/app/api/pickOrder/actions.ts @@ -320,12 +320,17 @@ export interface UpdateDoPickOrderHideStatusRequest { } export interface CompletedDoPickOrderResponse { id: number; + doPickOrderRecordId: number; // ✅ 新增 pickOrderId: number; + pickOrderIds: number[]; // ✅ 新增:所有 pick order IDs pickOrderCode: string; + pickOrderCodes: string; // ✅ 新增:所有 pick order codes (逗号分隔) pickOrderConsoCode: string; pickOrderStatus: string; deliveryOrderId: number; + deliveryOrderIds: number[]; // ✅ 新增:所有 delivery order IDs deliveryNo: string; + deliveryNos: string; // ✅ 新增:所有 delivery order codes (逗号分隔) deliveryDate: string; shopId: number; shopCode: string; @@ -335,6 +340,7 @@ export interface CompletedDoPickOrderResponse { shopPoNo: string; numberOfCartons: number; truckLanceCode: string; + DepartureTime: string; // ✅ 新增 storeId: string; completedDate: string; fgPickOrders: FGPickOrderResponse[]; @@ -911,23 +917,32 @@ export const fetchAllPickOrderLotsHierarchical = cache(async (userId: number): P }; } }); -export const fetchLotDetailsByPickOrderId = async (pickOrderId: number): Promise => { +export const fetchLotDetailsByDoPickOrderRecordId = async (doPickOrderRecordId: number): Promise<{ + fgInfo: any; + pickOrders: any[]; +}> => { try { - console.log("🔍 Fetching lot details for pickOrderId:", pickOrderId); + console.log("🔍 Fetching lot details for doPickOrderRecordId:", doPickOrderRecordId); - const data = await serverFetchJson( - `${BASE_API_URL}/pickOrder/lot-details-by-pick-order/${pickOrderId}`, + const data = await serverFetchJson<{ + fgInfo: any; + pickOrders: any[]; + }>( + `${BASE_API_URL}/pickOrder/lot-details-by-do-pick-order-record/${doPickOrderRecordId}`, { method: 'GET', next: { tags: ["pickorder"] }, } ); - console.log("✅ Fetched lot details for pickOrderId:", data); + console.log("✅ Fetched hierarchical lot details:", data); return data; } catch (error) { - console.error("❌ Error fetching lot details for pickOrderId:", error); - return []; + console.error("❌ Error fetching lot details:", error); + return { + fgInfo: null, + pickOrders: [] + }; } }; // Update the existing function to use the non-auto-assign endpoint diff --git a/src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx b/src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx index df32906..56a0afa 100644 --- a/src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx +++ b/src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx @@ -23,7 +23,7 @@ const FinishedGoodFloorLanePanel: React.FC = ({ onPickOrderAssigned }) => const [isLoadingSummary, setIsLoadingSummary] = useState(false); const [isAssigning, setIsAssigning] = useState(false); //const [selectedDate, setSelectedDate] = useState("today"); - const [selectedDate, setSelectedDate] = useState("2025-09-27"); + const [selectedDate, setSelectedDate] = useState("today"); const loadData = async (dateValue: string) => { setIsLoadingSummary(true); diff --git a/src/components/FinishedGoodSearch/GoodPickExecutionRecord.tsx b/src/components/FinishedGoodSearch/GoodPickExecutionRecord.tsx index 8ea96b2..6829595 100644 --- a/src/components/FinishedGoodSearch/GoodPickExecutionRecord.tsx +++ b/src/components/FinishedGoodSearch/GoodPickExecutionRecord.tsx @@ -44,7 +44,7 @@ import { fetchCompletedDoPickOrders, CompletedDoPickOrderResponse, CompletedDoPickOrderSearchParams, - fetchLotDetailsByPickOrderId + fetchLotDetailsByDoPickOrderRecordId } from "@/app/api/pickOrder/actions"; import { fetchNameList, NameList } from "@/app/api/user/actions"; import { @@ -407,30 +407,54 @@ const GoodPickExecutionRecord: React.FC = ({ filterArgs }) => { setSelectedDoPickOrder(doPickOrder); setShowDetailView(true); - // ✅ 修复:使用新的 API 根据 pickOrderId 获取 lot 详情 try { - const lotDetails = await fetchLotDetailsByPickOrderId(doPickOrder.pickOrderId); - setDetailLotData(lotDetails); - console.log("✅ Loaded detail lot data for pick order:", doPickOrder.pickOrderCode, lotDetails); + // ✅ 使用 doPickOrderRecordId 而不是 pickOrderId + const hierarchicalData = await fetchLotDetailsByDoPickOrderRecordId(doPickOrder.doPickOrderRecordId); + console.log("✅ Loaded hierarchical lot data:", hierarchicalData); - // ✅ 触发打印按钮状态更新 - 基于详情数据 - const allCompleted = lotDetails.length > 0 && lotDetails.every(lot => + // ✅ 转换为平铺格式 + const flatLotData: any[] = []; + + if (hierarchicalData.pickOrders && hierarchicalData.pickOrders.length > 0) { + hierarchicalData.pickOrders.forEach((po: any) => { + po.pickOrderLines?.forEach((line: any) => { + if (line.lots && line.lots.length > 0) { + line.lots.forEach((lot: any) => { + flatLotData.push({ + pickOrderCode: po.pickOrderCode, + itemCode: line.item.code, + itemName: line.item.name, + lotNo: lot.lotNo, + location: lot.location, + requiredQty: lot.requiredQty, + actualPickQty: lot.actualPickQty, + processingStatus: lot.processingStatus, + stockOutLineStatus: lot.stockOutLineStatus + }); + }); + } + }); + }); + } + + setDetailLotData(flatLotData); + + // ✅ 计算完成状态 + const allCompleted = flatLotData.length > 0 && flatLotData.every(lot => lot.processingStatus === 'completed' ); - // ✅ 发送事件,包含标签页信息 window.dispatchEvent(new CustomEvent('pickOrderCompletionStatus', { detail: { allLotsCompleted: allCompleted, - tabIndex: 2 // ✅ 明确指定这是来自标签页 2 的事件 + tabIndex: 2 } })); - } catch (error) { + } catch (error) { // ✅ 添加 catch 块 console.error("❌ Error loading detail lot data:", error); setDetailLotData([]); - // ✅ 如果加载失败,禁用打印按钮 window.dispatchEvent(new CustomEvent('pickOrderCompletionStatus', { detail: { allLotsCompleted: false, @@ -458,86 +482,132 @@ const GoodPickExecutionRecord: React.FC = ({ filterArgs }) => { // ✅ 如果显示详情视图,渲染类似 GoodPickExecution 的表格 - if (showDetailView && selectedDoPickOrder) { - return ( - - - {/* 返回按钮和标题 */} - - - - {t("Pick Order Details")}: {selectedDoPickOrder.pickOrderCode} - - + // ✅ 如果显示详情视图,渲染层级结构 +if (showDetailView && selectedDoPickOrder) { + return ( + + + {/* 返回按钮和标题 */} + + + + {t("Pick Order Details")}: {selectedDoPickOrder.ticketNo} + + - {/* 订单基本信息 */} - - - {t("Order Information")} - - + {/* FG 订单基本信息 */} + + + {t("Shop Name")}: {selectedDoPickOrder.shopName} - - {t("Delivery No")}: {selectedDoPickOrder.deliveryNo} + + {t("Store ID")}: {selectedDoPickOrder.storeId} - + + {t("Ticket No.")}: {selectedDoPickOrder.ticketNo} + + + {t("Truck Lance Code")}: {selectedDoPickOrder.truckLanceCode} + + {t("Completed Date")}: {dayjs(selectedDoPickOrder.completedDate).format(OUTPUT_DATE_FORMAT)} - - - {/* ✅ 添加数据检查 */} - {detailLotData.length === 0 ? ( - - - {t("No lot details found for this order")} - + + + + {/* ✅ 添加:多个 Pick Orders 信息(如果有) */} + {selectedDoPickOrder.pickOrderIds && selectedDoPickOrder.pickOrderIds.length > 1 && ( + + + {t("This ticket contains")} {selectedDoPickOrder.pickOrderIds.length} {t("pick orders")}: + + + {selectedDoPickOrder.pickOrderCodes?.split(', ').map((code, idx) => ( + + ))} - ) : ( - /* 显示完成数据的表格 */ - - - - - {t("Pick Order Code")} - {t("Item Code")} - {t("Item Name")} - {t("Lot No")} - {t("Location")} - {t("Required Qty")} - {t("Actual Pick Qty")} - {t("Submitted Status")} - - - - {detailLotData.map((lot, index) => ( - - {lot.pickOrderCode || 'N/A'} - {lot.itemCode || 'N/A'} - {lot.itemName || 'N/A'} - {lot.lotNo || 'N/A'} - {lot.location || 'N/A'} - {lot.requiredQty || 0} - {lot.actualPickQty || 0} - - - - - ))} - -
-
- )} -
-
- ); - } + + )} + + {/* ✅ 数据检查 */} + {detailLotData.length === 0 ? ( + + + {t("No lot details found for this order")} + + + ) : ( + /* ✅ 按 Pick Order 分组显示 */ + + {/* ✅ 按 pickOrderCode 分组 */} + {Object.entries( + detailLotData.reduce((acc: any, lot: any) => { + const key = lot.pickOrderCode || 'Unknown'; + if (!acc[key]) acc[key] = []; + acc[key].push(lot); + return acc; + }, {}) + ).map(([pickOrderCode, lots]: [string, any]) => ( + + }> + + {t("Pick Order")}: {pickOrderCode} ({(lots as any[]).length} {t("items")}) + + + + + + + + {t("Index")} + {t("Item Code")} + {t("Item Name")} + {t("Lot No")} + {t("Location")} + {t("Required Qty")} + {t("Actual Pick Qty")} + {t("Status")} + + + + {(lots as any[]).map((lot: any, index: number) => ( + + {index + 1} + {lot.itemCode || 'N/A'} + {lot.itemName || 'N/A'} + {lot.lotNo || 'N/A'} + {lot.location || 'N/A'} + {lot.requiredQty || 0} + {lot.actualPickQty || 0} + + + + + ))} + +
+
+
+
+ ))} +
+ )} +
+
+ ); +} // ✅ 默认列表视图 return ( diff --git a/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx b/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx index ba53432..637a2fe 100644 --- a/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx +++ b/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx @@ -663,100 +663,7 @@ const [isConfirmingLot, setIsConfirmingLot] = useState(false); }); } }); - targetPickOrder.pickOrderLines.forEach((line: any) => { - if (line.lots && line.lots.length > 0) { - // ✅ 有 lots 的情况 - line.lots.forEach((lot: any) => { - flatLotData.push({ - pickOrderId: targetPickOrder.pickOrderId, - pickOrderCode: targetPickOrder.pickOrderCode, - pickOrderConsoCode: targetPickOrder.consoCode, - pickOrderTargetDate: targetPickOrder.targetDate, - pickOrderStatus: targetPickOrder.status, - - pickOrderLineId: line.id, - pickOrderLineRequiredQty: line.requiredQty, - pickOrderLineStatus: line.status, - - itemId: line.item.id, - itemCode: line.item.code, - itemName: line.item.name, - //uomCode: line.item.uomCode, - uomDesc: line.item.uomDesc, - uomShortDesc: line.item.uomShortDesc, - lotId: lot.id, - lotNo: lot.lotNo, - expiryDate: lot.expiryDate, - location: lot.location, - stockUnit: lot.stockUnit, - availableQty: lot.availableQty, - requiredQty: lot.requiredQty, - actualPickQty: lot.actualPickQty, - inQty: lot.inQty, - outQty: lot.outQty, - holdQty: lot.holdQty, - lotStatus: lot.lotStatus, - lotAvailability: lot.lotAvailability, - processingStatus: lot.processingStatus, - suggestedPickLotId: lot.suggestedPickLotId, - stockOutLineId: lot.stockOutLineId, - stockOutLineStatus: lot.stockOutLineStatus, - stockOutLineQty: lot.stockOutLineQty, - - routerId: lot.router?.id, - routerIndex: lot.router?.index, - routerRoute: lot.router?.route, - routerArea: lot.router?.area, - }); - }); - } else { - // ✅ 没有 lots 的情况(null stock)- 也要显示 - flatLotData.push({ - pickOrderId: targetPickOrder.pickOrderId, - pickOrderCode: targetPickOrder.pickOrderCode, - pickOrderConsoCode: targetPickOrder.consoCode, - pickOrderTargetDate: targetPickOrder.targetDate, - pickOrderStatus: targetPickOrder.status, - - pickOrderLineId: line.id, - pickOrderLineRequiredQty: line.requiredQty, - pickOrderLineStatus: line.status, - - itemId: line.item.id, - itemCode: line.item.code, - itemName: line.item.name, - //uomCode: line.item.uomCode, - uomDesc: line.item.uomDesc, - - // ✅ Null stock 字段 - lotId: null, - lotNo: null, - expiryDate: null, - location: null, - stockUnit: line.item.uomDesc, - availableQty: 0, - requiredQty: line.requiredQty, - actualPickQty: 0, - inQty: 0, - outQty: 0, - holdQty: 0, - lotStatus: 'unavailable', - lotAvailability: 'insufficient_stock', - processingStatus: 'pending', - suggestedPickLotId: null, - stockOutLineId: null, - stockOutLineStatus: null, - stockOutLineQty: 0, - - routerId: null, - routerIndex: 999999, // ✅ 放到最后 - routerRoute: null, - routerArea: null, - uomShortDesc: line.item.uomShortDesc - }); - } - }); - + console.log("✅ Transformed flat lot data:", flatLotData); console.log("🔍 Total items (including null stock):", flatLotData.length);