|
|
|
@@ -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<Props> = ({ 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<Props> = ({ filterArgs }) => { |
|
|
|
|
|
|
|
|
|
|
|
// ✅ 如果显示详情视图,渲染类似 GoodPickExecution 的表格 |
|
|
|
if (showDetailView && selectedDoPickOrder) { |
|
|
|
return ( |
|
|
|
<FormProvider {...formProps}> |
|
|
|
<Box> |
|
|
|
{/* 返回按钮和标题 */} |
|
|
|
<Box sx={{ mb: 2, display: 'flex', alignItems: 'center', gap: 2 }}> |
|
|
|
<Button variant="outlined" onClick={handleBackToList}> |
|
|
|
{t("Back to List")} |
|
|
|
</Button> |
|
|
|
<Typography variant="h6"> |
|
|
|
{t("Pick Order Details")}: {selectedDoPickOrder.pickOrderCode} |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
// ✅ 如果显示详情视图,渲染层级结构 |
|
|
|
if (showDetailView && selectedDoPickOrder) { |
|
|
|
return ( |
|
|
|
<FormProvider {...formProps}> |
|
|
|
<Box> |
|
|
|
{/* 返回按钮和标题 */} |
|
|
|
<Box sx={{ mb: 2, display: 'flex', alignItems: 'center', gap: 2 }}> |
|
|
|
<Button variant="outlined" onClick={handleBackToList}> |
|
|
|
{t("Back to List")} |
|
|
|
</Button> |
|
|
|
<Typography variant="h6"> |
|
|
|
{t("Pick Order Details")}: {selectedDoPickOrder.ticketNo} |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
|
|
|
|
{/* 订单基本信息 */} |
|
|
|
<Box sx={{ mb: 2, p: 2, backgroundColor: '#f5f5f5', borderRadius: 1 }}> |
|
|
|
<Typography variant="h6" gutterBottom> |
|
|
|
{t("Order Information")} |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2"> |
|
|
|
{/* FG 订单基本信息 */} |
|
|
|
<Paper sx={{ mb: 2, p: 2 }}> |
|
|
|
<Stack spacing={1}> |
|
|
|
<Typography variant="subtitle1"> |
|
|
|
<strong>{t("Shop Name")}:</strong> {selectedDoPickOrder.shopName} |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2"> |
|
|
|
<strong>{t("Delivery No")}:</strong> {selectedDoPickOrder.deliveryNo} |
|
|
|
<Typography variant="subtitle1"> |
|
|
|
<strong>{t("Store ID")}:</strong> {selectedDoPickOrder.storeId} |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2"> |
|
|
|
<Typography variant="subtitle1"> |
|
|
|
<strong>{t("Ticket No.")}:</strong> {selectedDoPickOrder.ticketNo} |
|
|
|
</Typography> |
|
|
|
<Typography variant="subtitle1"> |
|
|
|
<strong>{t("Truck Lance Code")}:</strong> {selectedDoPickOrder.truckLanceCode} |
|
|
|
</Typography> |
|
|
|
<Typography variant="subtitle1"> |
|
|
|
<strong>{t("Completed Date")}:</strong> {dayjs(selectedDoPickOrder.completedDate).format(OUTPUT_DATE_FORMAT)} |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
|
|
|
|
{/* ✅ 添加数据检查 */} |
|
|
|
{detailLotData.length === 0 ? ( |
|
|
|
<Box sx={{ p: 3, textAlign: 'center' }}> |
|
|
|
<Typography variant="body2" color="text.secondary"> |
|
|
|
{t("No lot details found for this order")} |
|
|
|
</Typography> |
|
|
|
</Stack> |
|
|
|
</Paper> |
|
|
|
|
|
|
|
{/* ✅ 添加:多个 Pick Orders 信息(如果有) */} |
|
|
|
{selectedDoPickOrder.pickOrderIds && selectedDoPickOrder.pickOrderIds.length > 1 && ( |
|
|
|
<Paper sx={{ mb: 2, p: 2, backgroundColor: '#f5f5f5' }}> |
|
|
|
<Typography variant="subtitle2" sx={{ mb: 1, fontWeight: 'bold' }}> |
|
|
|
{t("This ticket contains")} {selectedDoPickOrder.pickOrderIds.length} {t("pick orders")}: |
|
|
|
</Typography> |
|
|
|
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}> |
|
|
|
{selectedDoPickOrder.pickOrderCodes?.split(', ').map((code, idx) => ( |
|
|
|
<Chip |
|
|
|
key={idx} |
|
|
|
label={code} |
|
|
|
size="small" |
|
|
|
variant="outlined" |
|
|
|
/> |
|
|
|
))} |
|
|
|
</Box> |
|
|
|
) : ( |
|
|
|
/* 显示完成数据的表格 */ |
|
|
|
<TableContainer component={Paper}> |
|
|
|
<Table> |
|
|
|
<TableHead> |
|
|
|
<TableRow> |
|
|
|
<TableCell>{t("Pick Order Code")}</TableCell> |
|
|
|
<TableCell>{t("Item Code")}</TableCell> |
|
|
|
<TableCell>{t("Item Name")}</TableCell> |
|
|
|
<TableCell>{t("Lot No")}</TableCell> |
|
|
|
<TableCell>{t("Location")}</TableCell> |
|
|
|
<TableCell>{t("Required Qty")}</TableCell> |
|
|
|
<TableCell>{t("Actual Pick Qty")}</TableCell> |
|
|
|
<TableCell>{t("Submitted Status")}</TableCell> |
|
|
|
</TableRow> |
|
|
|
</TableHead> |
|
|
|
<TableBody> |
|
|
|
{detailLotData.map((lot, index) => ( |
|
|
|
<TableRow key={index}> |
|
|
|
<TableCell>{lot.pickOrderCode || 'N/A'}</TableCell> |
|
|
|
<TableCell>{lot.itemCode || 'N/A'}</TableCell> |
|
|
|
<TableCell>{lot.itemName || 'N/A'}</TableCell> |
|
|
|
<TableCell>{lot.lotNo || 'N/A'}</TableCell> |
|
|
|
<TableCell>{lot.location || 'N/A'}</TableCell> |
|
|
|
<TableCell>{lot.requiredQty || 0}</TableCell> |
|
|
|
<TableCell>{lot.actualPickQty || 0}</TableCell> |
|
|
|
<TableCell> |
|
|
|
<Chip |
|
|
|
label={t(lot.processingStatus || 'unknown')} |
|
|
|
color={lot.processingStatus === 'completed' ? 'success' : 'default'} |
|
|
|
size="small" |
|
|
|
/> |
|
|
|
</TableCell> |
|
|
|
</TableRow> |
|
|
|
))} |
|
|
|
</TableBody> |
|
|
|
</Table> |
|
|
|
</TableContainer> |
|
|
|
)} |
|
|
|
</Box> |
|
|
|
</FormProvider> |
|
|
|
); |
|
|
|
} |
|
|
|
</Paper> |
|
|
|
)} |
|
|
|
|
|
|
|
{/* ✅ 数据检查 */} |
|
|
|
{detailLotData.length === 0 ? ( |
|
|
|
<Box sx={{ p: 3, textAlign: 'center' }}> |
|
|
|
<Typography variant="body2" color="text.secondary"> |
|
|
|
{t("No lot details found for this order")} |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
) : ( |
|
|
|
/* ✅ 按 Pick Order 分组显示 */ |
|
|
|
<Stack spacing={2}> |
|
|
|
{/* ✅ 按 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]) => ( |
|
|
|
<Accordion key={pickOrderCode} defaultExpanded={true}> |
|
|
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}> |
|
|
|
<Typography variant="subtitle1" fontWeight="bold"> |
|
|
|
{t("Pick Order")}: {pickOrderCode} ({(lots as any[]).length} {t("items")}) |
|
|
|
</Typography> |
|
|
|
</AccordionSummary> |
|
|
|
<AccordionDetails> |
|
|
|
<TableContainer component={Paper}> |
|
|
|
<Table size="small"> |
|
|
|
<TableHead> |
|
|
|
<TableRow> |
|
|
|
<TableCell>{t("Index")}</TableCell> |
|
|
|
<TableCell>{t("Item Code")}</TableCell> |
|
|
|
<TableCell>{t("Item Name")}</TableCell> |
|
|
|
<TableCell>{t("Lot No")}</TableCell> |
|
|
|
<TableCell>{t("Location")}</TableCell> |
|
|
|
<TableCell align="right">{t("Required Qty")}</TableCell> |
|
|
|
<TableCell align="right">{t("Actual Pick Qty")}</TableCell> |
|
|
|
<TableCell align="center">{t("Status")}</TableCell> |
|
|
|
</TableRow> |
|
|
|
</TableHead> |
|
|
|
<TableBody> |
|
|
|
{(lots as any[]).map((lot: any, index: number) => ( |
|
|
|
<TableRow key={index}> |
|
|
|
<TableCell>{index + 1}</TableCell> |
|
|
|
<TableCell>{lot.itemCode || 'N/A'}</TableCell> |
|
|
|
<TableCell>{lot.itemName || 'N/A'}</TableCell> |
|
|
|
<TableCell>{lot.lotNo || 'N/A'}</TableCell> |
|
|
|
<TableCell>{lot.location || 'N/A'}</TableCell> |
|
|
|
<TableCell align="right">{lot.requiredQty || 0}</TableCell> |
|
|
|
<TableCell align="right">{lot.actualPickQty || 0}</TableCell> |
|
|
|
<TableCell align="center"> |
|
|
|
<Chip |
|
|
|
label={t(lot.processingStatus || 'unknown')} |
|
|
|
color={lot.processingStatus === 'completed' ? 'success' : 'default'} |
|
|
|
size="small" |
|
|
|
/> |
|
|
|
</TableCell> |
|
|
|
</TableRow> |
|
|
|
))} |
|
|
|
</TableBody> |
|
|
|
</Table> |
|
|
|
</TableContainer> |
|
|
|
</AccordionDetails> |
|
|
|
</Accordion> |
|
|
|
))} |
|
|
|
</Stack> |
|
|
|
)} |
|
|
|
</Box> |
|
|
|
</FormProvider> |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// ✅ 默认列表视图 |
|
|
|
return ( |
|
|
|
|