Browse Source

一个sheet里存在多个CmcInvoice和一个sheet里存在多个Cargo Ready Date的情况,前端提示错误信息

java8
han\hanst 3 weeks ago
parent
commit
caf2491c63
  1. 10
      src/main/java/com/xujie/sys/modules/ecss/data/EcssCoDelNotifyData.java
  2. 148
      src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelExcelServiceImpl.java
  3. 9
      src/main/resources/mapper/ecss/CoDelMapper.xml
  4. BIN
      src/main/resources/templates/declaration-all-template-WOERMA-pdf.xlsx
  5. BIN
      src/main/resources/templates/declaration-all-template-WOERMA.xlsx
  6. BIN
      src/main/resources/templates/declaration-packingList-template-WOERMA.xlsx

10
src/main/java/com/xujie/sys/modules/ecss/data/EcssCoDelNotifyData.java

@ -27,4 +27,14 @@ public class EcssCoDelNotifyData extends EcssCoDelNotify {
private Boolean modifyFlag;
private Boolean modifyQtyFlag;
/**
* Excel文件中的实际行号用于错误提示不保存到数据库
*/
private transient Integer excelRowNumber;
/**
* Excel文件中的Sheet名称用于错误提示不保存到数据库
*/
private transient String excelSheetName;
}

148
src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelExcelServiceImpl.java

@ -89,7 +89,7 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
Map<String, Object> summary = new HashMap<>();
summary.put("cmcInvoice", invoice);
// 格式化日期为字符串
// 格式化日期为字符串取第一条数据的日期
Date readyDate = dataList.get(0).getReadyDate();
String formattedDate = readyDate != null ? DateUtils.format(readyDate, "yyyy-MM-dd") : "";
summary.put("readyDate", formattedDate);
@ -196,22 +196,23 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
List<String> failList = new ArrayList<>();
// 添加Sheet错误信息到失败列表
// 注意只添加那些数据未被过滤的错误skipped=false已被过滤的错误skipped=true不需要再显示
for (SheetErrorInfo error : sheetErrors) {
if (error.getSkipped()) {
// 跳过类型的错误作为警告信息
failList.add("Sheet [" + error.getSheetName() + "] 已跳过:" + error.getErrorMessage());
} else {
// 验证失败类型的错误
failList.add("Sheet [" + error.getSheetName() + "] 错误:" + error.getErrorMessage());
if (error.getErrorDetails() != null && !error.getErrorDetails().isEmpty()) {
// 限制显示前5个错误详情
int limit = Math.min(5, error.getErrorDetails().size());
for (int i = 0; i < limit; i++) {
failList.add(" - " + error.getErrorDetails().get(i));
}
if (error.getErrorDetails().size() > 5) {
failList.add(" - ... 还有 " + (error.getErrorDetails().size() - 5) + " 个错误");
}
// 跳过类型的错误如多个Invoice日期不一致数据已在预览时被过滤不需要在保存结果中显示
continue;
}
// 其他类型的错误如数据格式错误必填字段为空等数据仍然存在可能导致保存失败
failList.add("Sheet [" + error.getSheetName() + "] 错误:" + error.getErrorMessage());
if (error.getErrorDetails() != null && !error.getErrorDetails().isEmpty()) {
// 限制显示前5个错误详情
int limit = Math.min(5, error.getErrorDetails().size());
for (int i = 0; i < limit; i++) {
failList.add(" - " + error.getErrorDetails().get(i));
}
if (error.getErrorDetails().size() > 5) {
failList.add(" - ... 还有 " + (error.getErrorDetails().size() - 5) + " 个错误");
}
}
}
@ -532,6 +533,7 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
}
boolean hasRowError = false; // 标记当前Sheet是否有行错误
List<EcssCoDelNotifyData> currentSheetData = new ArrayList<>(); // 记录当前Sheet的数据
// 遍历每一行从第四行开始即索引3
for (int j = 3; j < rows; j++) {
@ -611,6 +613,10 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
task.setSite(site); // site
task.setBuNo(inData.getBuNo()); // bu
// 记录Excel行号和Sheet名称用于错误提示
task.setExcelRowNumber(j + 1); // j是索引j+1是Excel中的实际行号
task.setExcelSheetName(sheetName);
// 解析日期
Date readDate;
try {
@ -719,9 +725,106 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
task.setUsername(inData.getUsername());
// 物料存在性检查已移至批量处理阶段此处不再单独检查
excelList.add(task);
// 先添加到当前Sheet的数据列表稍后根据校验结果决定是否添加到总列表
currentSheetData.add(task);
}
// 校验1检查当前Sheet中的CmcInvoice唯一性
Set<String> uniqueInvoices = currentSheetData.stream()
.map(EcssCoDelNotifyData::getCmcInvoice)
.collect(Collectors.toSet());
boolean hasMultipleInvoices = uniqueInvoices.size() > 1;
boolean hasDateInconsistency = false;
if (hasMultipleInvoices) {
// 发现多个不同的CmcInvoice
if (currentSheetError == null) {
currentSheetError = new SheetErrorInfo();
currentSheetError.setSheetName(sheetName);
currentSheetError.setSheetIndex(s);
currentSheetError.setErrorDetails(new ArrayList<>());
}
// 无论currentSheetError是否已存在都要标记为跳过
currentSheetError.setErrorType("DATA_ERROR");
currentSheetError.setErrorMessage("数据错误,该Sheet数据将不会导入");
currentSheetError.setSkipped(true);
// 统计每个发票号出现的行
Map<String, List<Integer>> invoiceRowsMap = new HashMap<>();
for (EcssCoDelNotifyData data : currentSheetData) {
String invoice = data.getCmcInvoice();
invoiceRowsMap.putIfAbsent(invoice, new ArrayList<>());
invoiceRowsMap.get(invoice).add(data.getExcelRowNumber());
}
List<String> invoiceDetails = new ArrayList<>();
for (Map.Entry<String, List<Integer>> entry : invoiceRowsMap.entrySet()) {
String invoice = entry.getKey();
List<Integer> dataRows = entry.getValue();
Collections.sort(dataRows);
String rowStr = dataRows.stream().map(String::valueOf).collect(Collectors.joining("、"));
invoiceDetails.add("[" + invoice + "] (第" + rowStr + "行)");
}
String errorMsg = "存在多个CMC Invoice:" + String.join(" | ", invoiceDetails);
currentSheetError.addErrorDetail(errorMsg);
hasRowError = true;
}
// 校验2检查当前Sheet中的Cargo Ready Date一致性按发票号分组
Map<String, Map<String, List<Integer>>> invoiceDateMap = new HashMap<>();
for (EcssCoDelNotifyData data : currentSheetData) {
String invoice = data.getCmcInvoice();
Date readyDate = data.getReadyDate();
String dateKey = readyDate != null ? DateUtils.format(readyDate, "yyyy-MM-dd") : "";
invoiceDateMap.putIfAbsent(invoice, new HashMap<>());
invoiceDateMap.get(invoice).putIfAbsent(dateKey, new ArrayList<>());
invoiceDateMap.get(invoice).get(dateKey).add(data.getExcelRowNumber());
}
// 检查是否有发票存在多个不同的日期
for (Map.Entry<String, Map<String, List<Integer>>> entry : invoiceDateMap.entrySet()) {
String invoice = entry.getKey();
Map<String, List<Integer>> dateGroups = entry.getValue();
if (dateGroups.size() > 1) {
// 发现日期不一致
hasDateInconsistency = true;
if (currentSheetError == null) {
currentSheetError = new SheetErrorInfo();
currentSheetError.setSheetName(sheetName);
currentSheetError.setSheetIndex(s);
currentSheetError.setErrorDetails(new ArrayList<>());
}
// 无论currentSheetError是否已存在都要标记为跳过
currentSheetError.setErrorType("DATA_ERROR");
currentSheetError.setErrorMessage("数据错误,该Sheet数据将不会导入");
currentSheetError.setSkipped(true);
List<String> dateDetails = new ArrayList<>();
for (Map.Entry<String, List<Integer>> dateEntry : dateGroups.entrySet()) {
String date = dateEntry.getKey().isEmpty() ? "未填写" : dateEntry.getKey();
List<Integer> dataRows = dateEntry.getValue();
Collections.sort(dataRows);
String rowStr = dataRows.stream().map(String::valueOf).collect(Collectors.joining("、"));
dateDetails.add(date + " (第" + rowStr + "行)");
}
String errorMsg = "存在不同的Ready Date:" + String.join(" | ", dateDetails);
currentSheetError.addErrorDetail(errorMsg);
hasRowError = true;
}
}
// 只有在没有严重错误多个Invoice或日期不一致才将数据添加到总列表
if (!hasMultipleInvoices && !hasDateInconsistency) {
excelList.addAll(currentSheetData);
} else {
log.warn("Sheet [{}] 因数据错误被跳过,共 {} 条数据未导入", sheetName, currentSheetData.size());
}
// 在Sheet处理结束时如果有行错误添加到错误列表
if (hasRowError && currentSheetError != null) {
sheetErrors.add(currentSheetError);
@ -762,7 +865,7 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
// 处理公式类型 - 获取缓存结果
else if (cellType == CellType.FORMULA) {
CellType cachedType = cell.getCachedFormulaResultType();
if (cachedType == CellType.NUMERIC) {
// 公式结果是数值类型且是日期格式
if (DateUtil.isCellDateFormatted(cell)) {
@ -809,7 +912,7 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
// 处理公式类型 - 获取缓存结果
if (cellType == CellType.FORMULA) {
CellType cachedType = cell.getCachedFormulaResultType();
if (cachedType == CellType.NUMERIC) {
// 公式结果是数值类型 - 直接获取数值并转换为字符串
// 检查是否是日期格式
@ -868,7 +971,7 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
// 处理公式类型 - 获取缓存结果
if (cellType == CellType.FORMULA) {
CellType cachedType = cell.getCachedFormulaResultType();
if (cachedType == CellType.NUMERIC) {
return (int) Math.round(cell.getNumericCellValue());
} else if (cachedType == CellType.STRING) {
@ -911,7 +1014,7 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
("Qty (pcs)".equalsIgnoreCase(columnName) || "TP".equalsIgnoreCase(columnName));
CellType cellType = cell.getCellType();
if (cellType == CellType.NUMERIC) {
BigDecimal value = BigDecimal.valueOf(cell.getNumericCellValue());
return value.setScale(6, RoundingMode.HALF_UP); // 四舍五入保留四位小数
@ -931,7 +1034,7 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
} else if (cellType == CellType.FORMULA) {
// 获取缓存结果
CellType cachedType = cell.getCachedFormulaResultType();
if (cachedType == CellType.NUMERIC) {
BigDecimal formulaValue = BigDecimal.valueOf(cell.getNumericCellValue());
return formulaValue.setScale(6, RoundingMode.HALF_UP); // 四舍五入保留四位小数
@ -979,7 +1082,8 @@ public class CoDelExcelServiceImpl implements CoDelExcelService {
if (!sheetErrors.isEmpty()) {
StringBuilder errorMsg = new StringBuilder("以下Sheet存在问题:\n");
for (SheetErrorInfo error : sheetErrors) {
errorMsg.append("Sheet [").append(error.getSheetName()).append("]: ").append(error.getErrorMessage()).append("\n");
errorMsg.append("Sheet [").append(error.getSheetName()).append("]: ").
append(String.join("\n", error.getErrorDetails())).append("\n\n");
}
throw new RuntimeException(errorMsg.toString());
}

9
src/main/resources/mapper/ecss/CoDelMapper.xml

@ -75,6 +75,15 @@
<if test="query.modifyData == 'true'">
and a.modifyFlag=1
</if>
<if test="query.fscFlag == 'true'">
AND a.fscFlag = 'Y'
</if>
<if test="query.boxSizeFlag == 'true'">
AND a.boxSizeFlag = 'Y'
</if>
<if test="query.walMartOrderFlag == 'true'">
AND a.walMartOrderFlag = 'Y'
</if>
<if test="query.exportFlag != null and query.exportFlag != ''">
and ISNULL(a.export_flag,'N') = #{query.exportFlag}
</if>

BIN
src/main/resources/templates/declaration-all-template-WOERMA-pdf.xlsx

BIN
src/main/resources/templates/declaration-all-template-WOERMA.xlsx

BIN
src/main/resources/templates/declaration-packingList-template-WOERMA.xlsx

Loading…
Cancel
Save