|
|
|
@@ -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<number, any>(); |
|
|
|
|
|
|
|
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<number>(); |
|
|
|
|
|
|
|
// ✅ lots:按 lotId 去重并合并 requiredQty |
|
|
|
if (line.lots && line.lots.length > 0) { |
|
|
|
const lotMap = new Map<number, any>(); |
|
|
|
|
|
|
|
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([]); |
|
|
|
|