diff --git a/src/components/DashboardPage/truckSchedule/TruckScheduleDashboard.tsx b/src/components/DashboardPage/truckSchedule/TruckScheduleDashboard.tsx
index 2c963dd..67384f3 100644
--- a/src/components/DashboardPage/truckSchedule/TruckScheduleDashboard.tsx
+++ b/src/components/DashboardPage/truckSchedule/TruckScheduleDashboard.tsx
@@ -566,11 +566,6 @@ const TruckScheduleDashboard: React.FC = () => {
{row.numberOfShopsToServe} [{row.numberOfPickTickets}]
-
-
- {row.totalItemsToPick}
-
-
{
color={row.numberOfTicketsCompleted > 0 ? 'success' : 'default'}
/>
+
+
+ {row.totalItemsToPick}
+
+
{formatDateTime(row.firstTicketStartTime)}
diff --git a/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx b/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx
index 3c773a1..2b04d3b 100644
--- a/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx
+++ b/src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx
@@ -768,180 +768,196 @@ const fetchAllCombinedLotData = useCallback(async (userId?: number, pickOrderIdO
// 设置 FG info 到 fgPickOrders(用于显示 FG 信息卡片)
// 修改第 478-509 行的 fgOrder 构建逻辑:
-const fgOrder: FGPickOrderResponse = {
- doPickOrderId: hierarchicalData.fgInfo.doPickOrderId,
- ticketNo: hierarchicalData.fgInfo.ticketNo,
- storeId: hierarchicalData.fgInfo.storeId,
- shopCode: hierarchicalData.fgInfo.shopCode,
- shopName: hierarchicalData.fgInfo.shopName,
- truckLanceCode: hierarchicalData.fgInfo.truckLanceCode,
- DepartureTime: hierarchicalData.fgInfo.departureTime,
- shopAddress: "",
- pickOrderCode: mergedPickOrder.pickOrderCodes?.[0] || "",
- // 兼容字段
- pickOrderId: mergedPickOrder.pickOrderIds?.[0] || 0,
- pickOrderConsoCode: mergedPickOrder.consoCode || "",
- pickOrderTargetDate: mergedPickOrder.targetDate || "",
- pickOrderStatus: mergedPickOrder.status || "",
- deliveryOrderId: mergedPickOrder.doOrderIds?.[0] || 0,
- deliveryNo: mergedPickOrder.deliveryOrderCodes?.[0] || "",
- deliveryDate: "",
- shopId: 0,
- shopPoNo: "",
- numberOfCartons: mergedPickOrder.pickOrderLines?.length || 0,
- qrCodeData: hierarchicalData.fgInfo.doPickOrderId,
-
- // 新增:多个 pick orders 信息 - 保持数组格式,不要 join
- numberOfPickOrders: mergedPickOrder.pickOrderIds?.length || 0,
- pickOrderIds: mergedPickOrder.pickOrderIds || [],
- pickOrderCodes: Array.isArray(mergedPickOrder.pickOrderCodes)
- ? mergedPickOrder.pickOrderCodes
- : [], // 改:保持数组
- deliveryOrderIds: mergedPickOrder.doOrderIds || [],
- deliveryNos: Array.isArray(mergedPickOrder.deliveryOrderCodes)
- ? mergedPickOrder.deliveryOrderCodes
- : [], // 改:保持数组
- lineCountsPerPickOrder: Array.isArray(mergedPickOrder.lineCountsPerPickOrder)
- ? mergedPickOrder.lineCountsPerPickOrder
- : []
-};
-
- setFgPickOrders([fgOrder]);
- console.log(" DEBUG fgOrder.lineCountsPerPickOrder:", fgOrder.lineCountsPerPickOrder);
-console.log(" DEBUG fgOrder.pickOrderCodes:", fgOrder.pickOrderCodes);
-console.log(" DEBUG fgOrder.deliveryNos:", fgOrder.deliveryNos);
- // 移除:不需要 doPickOrderDetail 和 switcher 逻辑
- // if (hierarchicalData.pickOrders.length > 1) { ... }
-
- // 直接使用合并后的 pickOrderLines
- console.log("🎯 Displaying merged pick order lines");
-
- // 将层级数据转换为平铺格式(用于表格显示)
- const flatLotData: any[] = [];
-
- mergedPickOrder.pickOrderLines.forEach((line: any) => {
- // ✅ FIXED: 处理 lots(如果有)
- if (line.lots && line.lots.length > 0) {
- // 修复:先对 lots 按 lotId 去重并合并 requiredQty
- const lotMap = new Map();
-
- line.lots.forEach((lot: any) => {
- const lotId = lot.id;
- if (lotMap.has(lotId)) {
- // 如果已存在,合并 requiredQty
- const existingLot = lotMap.get(lotId);
- existingLot.requiredQty = (existingLot.requiredQty || 0) + (lot.requiredQty || 0);
- // 保留其他字段(使用第一个遇到的 lot 的字段)
- } else {
- // 首次遇到,添加到 map
- lotMap.set(lotId, { ...lot });
- }
- });
-
- // 遍历去重后的 lots
- lotMap.forEach((lot: any) => {
- flatLotData.push({
- // 使用合并后的数据
- pickOrderConsoCode: mergedPickOrder.consoCode,
- pickOrderTargetDate: mergedPickOrder.targetDate,
- pickOrderStatus: mergedPickOrder.status,
- pickOrderId: line.pickOrderId || mergedPickOrder.pickOrderIds?.[0] || 0, // 使用第一个 pickOrderId
- pickOrderCode: mergedPickOrder.pickOrderCodes?.[0] || "",
- pickOrderLineId: line.id,
- pickOrderLineRequiredQty: line.requiredQty,
- pickOrderLineStatus: line.status,
-
- itemId: line.item.id,
- itemCode: line.item.code,
- itemName: line.item.name,
- 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, // 使用合并后的 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,
- stockInLineId: lot.stockInLineId,
- routerId: lot.router?.id,
- routerIndex: lot.router?.index,
- routerRoute: lot.router?.route,
- routerArea: lot.router?.area,
- noLot: false,
- });
+ const fgOrder: FGPickOrderResponse = {
+ doPickOrderId: hierarchicalData.fgInfo.doPickOrderId,
+ ticketNo: hierarchicalData.fgInfo.ticketNo,
+ storeId: hierarchicalData.fgInfo.storeId,
+ shopCode: hierarchicalData.fgInfo.shopCode,
+ shopName: hierarchicalData.fgInfo.shopName,
+ truckLanceCode: hierarchicalData.fgInfo.truckLanceCode,
+ DepartureTime: hierarchicalData.fgInfo.departureTime,
+ shopAddress: "",
+ pickOrderCode: mergedPickOrder.pickOrderCodes?.[0] || "",
+
+ // 兼容字段(注意 consoCodes 是数组)
+ pickOrderId: mergedPickOrder.pickOrderIds?.[0] || 0,
+ pickOrderConsoCode: Array.isArray(mergedPickOrder.consoCodes)
+ ? mergedPickOrder.consoCodes[0] || ""
+ : "",
+ pickOrderTargetDate: mergedPickOrder.targetDate || "",
+ pickOrderStatus: mergedPickOrder.status || "",
+ deliveryOrderId: mergedPickOrder.doOrderIds?.[0] || 0,
+ deliveryNo: mergedPickOrder.deliveryOrderCodes?.[0] || "",
+ deliveryDate: "",
+ shopId: 0,
+ shopPoNo: "",
+ numberOfCartons: mergedPickOrder.pickOrderLines?.length || 0,
+ qrCodeData: hierarchicalData.fgInfo.doPickOrderId,
+
+ // 多个 pick orders 信息:全部保留为数组
+ numberOfPickOrders: mergedPickOrder.pickOrderIds?.length || 0,
+ pickOrderIds: mergedPickOrder.pickOrderIds || [],
+ pickOrderCodes: Array.isArray(mergedPickOrder.pickOrderCodes)
+ ? mergedPickOrder.pickOrderCodes
+ : [],
+ deliveryOrderIds: mergedPickOrder.doOrderIds || [],
+ deliveryNos: Array.isArray(mergedPickOrder.deliveryOrderCodes)
+ ? mergedPickOrder.deliveryOrderCodes
+ : [],
+ lineCountsPerPickOrder: Array.isArray(mergedPickOrder.lineCountsPerPickOrder)
+ ? mergedPickOrder.lineCountsPerPickOrder
+ : [],
+ };
+
+ setFgPickOrders([fgOrder]);
+ console.log(" DEBUG fgOrder.lineCountsPerPickOrder:", fgOrder.lineCountsPerPickOrder);
+ console.log(" DEBUG fgOrder.pickOrderCodes:", fgOrder.pickOrderCodes);
+ console.log(" DEBUG fgOrder.deliveryNos:", fgOrder.deliveryNos);
+
+ // 直接使用合并后的 pickOrderLines
+ console.log("🎯 Displaying merged pick order lines");
+
+ // 将层级数据转换为平铺格式(用于表格显示)
+ const flatLotData: any[] = [];
+
+ mergedPickOrder.pickOrderLines.forEach((line: any) => {
+ // 用来记录这一行已经通过 lots 出现过的 lotId
+ const lotIdSet = new Set();
+
+ // ✅ lots:按 lotId 去重并合并 requiredQty
+ if (line.lots && line.lots.length > 0) {
+ const lotMap = new Map();
+
+ line.lots.forEach((lot: any) => {
+ const lotId = lot.id;
+ if (lotMap.has(lotId)) {
+ const existingLot = lotMap.get(lotId);
+ existingLot.requiredQty =
+ (existingLot.requiredQty || 0) + (lot.requiredQty || 0);
+ } else {
+ lotMap.set(lotId, { ...lot });
+ }
+ });
+
+ lotMap.forEach((lot: any) => {
+ if (lot.id != null) {
+ lotIdSet.add(lot.id);
+ }
+
+ flatLotData.push({
+ pickOrderConsoCode: Array.isArray(mergedPickOrder.consoCodes)
+ ? mergedPickOrder.consoCodes[0] || ""
+ : "",
+ pickOrderTargetDate: mergedPickOrder.targetDate,
+ pickOrderStatus: mergedPickOrder.status,
+ pickOrderId: line.pickOrderId || mergedPickOrder.pickOrderIds?.[0] || 0,
+ pickOrderCode: mergedPickOrder.pickOrderCodes?.[0] || "",
+ pickOrderLineId: line.id,
+ pickOrderLineRequiredQty: line.requiredQty,
+ pickOrderLineStatus: line.status,
+
+ itemId: line.item.id,
+ itemCode: line.item.code,
+ itemName: line.item.name,
+ 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,
+ stockInLineId: lot.stockInLineId,
+ routerId: lot.router?.id,
+ routerIndex: lot.router?.index,
+ routerRoute: lot.router?.route,
+ routerArea: lot.router?.area,
+ noLot: false,
});
- }
-
- // ✅ FIXED: 同时处理 stockouts(无论是否有 lots)
- if (line.stockouts && line.stockouts.length > 0) {
- // ✅ FIXED: 处理所有 stockouts,而不仅仅是第一个
- line.stockouts.forEach((stockout: any) => {
- flatLotData.push({
- pickOrderConsoCode: mergedPickOrder.consoCodes?.[0] || "",
- pickOrderTargetDate: mergedPickOrder.targetDate,
- pickOrderStatus: mergedPickOrder.status,
- pickOrderId: line.pickOrderId || mergedPickOrder.pickOrderIds?.[0] || 0,
- pickOrderCode: mergedPickOrder.pickOrderCodes?.[0] || "",
- pickOrderLineId: line.id,
- pickOrderLineRequiredQty: line.requiredQty,
- pickOrderLineStatus: line.status,
-
- itemId: line.item.id,
- itemCode: line.item.code,
- itemName: line.item.name,
- uomDesc: line.item.uomDesc,
- uomShortDesc: line.item.uomShortDesc,
-
- // Null stock 字段 - 从 stockouts 数组中获取
- lotId: stockout.lotId || null,
- lotNo: stockout.lotNo || null,
- expiryDate: null,
- location: stockout.location || null,
- stockUnit: line.item.uomDesc,
- availableQty: stockout.availableQty || 0,
- requiredQty: line.requiredQty,
- actualPickQty: stockout.qty || 0,
- inQty: 0,
- outQty: 0,
- holdQty: 0,
- lotStatus: 'unavailable',
- lotAvailability: 'insufficient_stock',
- processingStatus: stockout.status || 'pending',
- suggestedPickLotId: null,
- stockOutLineId: stockout.id || null, // 使用 stockouts 数组中的 id
- stockOutLineStatus: stockout.status || null,
- stockOutLineQty: stockout.qty || 0,
-
- routerId: null,
- routerIndex: 999999,
- routerRoute: null,
- routerArea: null,
- noLot: true,
- });
+ });
+ }
+
+ // ✅ stockouts:只保留“真正无批次 / 未在 lots 出现过”的行
+ if (line.stockouts && line.stockouts.length > 0) {
+ line.stockouts.forEach((stockout: any) => {
+ const hasLot = stockout.lotId != null;
+ const lotAlreadyInLots =
+ hasLot && lotIdSet.has(stockout.lotId as number);
+
+ // 有批次 & 已经通过 lots 渲染过 → 跳过,避免一条变两行
+ if (!stockout.noLot && lotAlreadyInLots) {
+ return;
+ }
+
+ // 只渲染:
+ // - noLot === true 的 Null stock 行
+ // - 或者 lotId 在 lots 中不存在的特殊情况
+ flatLotData.push({
+ pickOrderConsoCode: Array.isArray(mergedPickOrder.consoCodes)
+ ? mergedPickOrder.consoCodes[0] || ""
+ : "",
+ pickOrderTargetDate: mergedPickOrder.targetDate,
+ pickOrderStatus: mergedPickOrder.status,
+ pickOrderId: line.pickOrderId || mergedPickOrder.pickOrderIds?.[0] || 0,
+ pickOrderCode: mergedPickOrder.pickOrderCodes?.[0] || "",
+ pickOrderLineId: line.id,
+ pickOrderLineRequiredQty: line.requiredQty,
+ pickOrderLineStatus: line.status,
+
+ itemId: line.item.id,
+ itemCode: line.item.code,
+ itemName: line.item.name,
+ uomDesc: line.item.uomDesc,
+ uomShortDesc: line.item.uomShortDesc,
+
+ lotId: stockout.lotId || null,
+ lotNo: stockout.lotNo || null,
+ expiryDate: null,
+ location: stockout.location || null,
+ stockUnit: line.item.uomDesc,
+ availableQty: stockout.availableQty || 0,
+ requiredQty: line.requiredQty,
+ actualPickQty: stockout.qty || 0,
+ inQty: 0,
+ outQty: 0,
+ holdQty: 0,
+ lotStatus: stockout.noLot ? "unavailable" : "available",
+ lotAvailability: stockout.noLot ? "insufficient_stock" : "available",
+ processingStatus: stockout.status || "pending",
+ suggestedPickLotId: null,
+ stockOutLineId: stockout.id || null,
+ stockOutLineStatus: stockout.status || null,
+ stockOutLineQty: stockout.qty || 0,
+
+ routerId: null,
+ routerIndex: stockout.noLot ? 999999 : null,
+ routerRoute: null,
+ routerArea: null,
+ noLot: !!stockout.noLot,
});
- }
- });
-
- console.log(" Transformed flat lot data:", flatLotData);
- console.log(" Total items (including null stock):", flatLotData.length);
-
- setCombinedLotData(flatLotData);
- setOriginalCombinedData(flatLotData);
- checkAllLotsCompleted(flatLotData);
-
+ });
+ }
+ });
+
+ console.log(" Transformed flat lot data:", flatLotData);
+ console.log(" Total items (including null stock):", flatLotData.length);
+
+ setCombinedLotData(flatLotData);
+ setOriginalCombinedData(flatLotData);
+ checkAllLotsCompleted(flatLotData);
} catch (error) {
console.error(" Error fetching combined lot data:", error);
setCombinedLotData([]);