|
|
|
@ -86,6 +86,11 @@ public class CoDelExcelServiceImpl implements CoDelExcelService { |
|
|
|
*/ |
|
|
|
private static final int NOTIFY_DETAIL_BATCH_SIZE = |
|
|
|
Math.max(1, SQL_SERVER_PARAM_SAFE_LIMIT / NOTIFY_DETAIL_PARAM_COUNT_PER_ROW); |
|
|
|
/** |
|
|
|
* 统一维护 Cargo Ready Date 相关错误文案,避免前后端匹配漂移 |
|
|
|
*/ |
|
|
|
private static final String CARGO_READY_DATE_EMPTY_ERROR_DETAIL = "[Cargo Ready Date] 列不能为空"; |
|
|
|
private static final String CARGO_READY_DATE_PARSE_ERROR_DETAIL = "[Cargo Ready Date] 列格式有误"; |
|
|
|
private static final XSSFColor PART_ARCHIVE_LIGHT_TURQUOISE = |
|
|
|
new XSSFColor(new byte[]{(byte) 0x92, (byte) 0xCD, (byte) 0xDC}, new DefaultIndexedColorMap()); |
|
|
|
private static final XSSFColor PART_ARCHIVE_ORANGE = |
|
|
|
@ -196,6 +201,13 @@ public class CoDelExcelServiceImpl implements CoDelExcelService { |
|
|
|
throw new RuntimeException("导入失败:" + e.getMessage()); |
|
|
|
} |
|
|
|
|
|
|
|
// 业务规则:只要存在 Cargo Ready Date 为空的Sheet,就必须阻断提交,避免“预览告警但可提交”的数据不一致 |
|
|
|
List<String> readyDateEmptySheets = collectReadyDateEmptySheets(sheetErrors); |
|
|
|
if (!readyDateEmptySheets.isEmpty()) { |
|
|
|
throw new RuntimeException("提交失败:Sheet [" + String.join("、", readyDateEmptySheets) |
|
|
|
+ "] 存在 Cargo Ready Date 为空,请补充后重新上传"); |
|
|
|
} |
|
|
|
|
|
|
|
// 处理删除的发票号 |
|
|
|
if (deletedInvoices != null && !deletedInvoices.trim().isEmpty()) { |
|
|
|
try { |
|
|
|
@ -678,12 +690,21 @@ public class CoDelExcelServiceImpl implements CoDelExcelService { |
|
|
|
|
|
|
|
// 解析日期 |
|
|
|
Date readDate; |
|
|
|
String cargoReadyDateValue = getStringCellValue(row, cargoReadyDateIdx); |
|
|
|
if (StringUtils.isBlank(cargoReadyDateValue)) { |
|
|
|
currentSheetError.addErrorDetail("第" + (j + 1) + "行的 " + CARGO_READY_DATE_EMPTY_ERROR_DETAIL); |
|
|
|
hasRowError = true; |
|
|
|
continue; |
|
|
|
} |
|
|
|
try { |
|
|
|
LocalDate localDate = parseDateCell(row.getCell(cargoReadyDateIdx)); |
|
|
|
if (localDate == null) { |
|
|
|
throw new RuntimeException(CARGO_READY_DATE_PARSE_ERROR_DETAIL); |
|
|
|
} |
|
|
|
String formatted = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); |
|
|
|
readDate = DateUtils.getDateByParten(formatted, "yyyy-MM-dd"); |
|
|
|
} catch (Exception e) { |
|
|
|
currentSheetError.addErrorDetail("第" + (j+1) + "行的 [Cargo Ready Date] 列格式有误"); |
|
|
|
currentSheetError.addErrorDetail("第" + (j + 1) + "行的 " + CARGO_READY_DATE_PARSE_ERROR_DETAIL); |
|
|
|
hasRowError = true; |
|
|
|
continue; |
|
|
|
} |
|
|
|
@ -905,6 +926,32 @@ public class CoDelExcelServiceImpl implements CoDelExcelService { |
|
|
|
log.info("=== Excel导入完成 === 成功处理 {} 条数据,发现 {} 个Sheet存在问题", excelList.size(), sheetErrors.size()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 识别包含 Cargo Ready Date 为空错误的Sheet,用于提交阶段阻断。 |
|
|
|
*/ |
|
|
|
private List<String> collectReadyDateEmptySheets(List<SheetErrorInfo> sheetErrors) { |
|
|
|
if (sheetErrors == null || sheetErrors.isEmpty()) { |
|
|
|
return Collections.emptyList(); |
|
|
|
} |
|
|
|
return sheetErrors.stream() |
|
|
|
.filter(Objects::nonNull) |
|
|
|
.filter(this::hasCargoReadyDateEmptyError) |
|
|
|
.map(SheetErrorInfo::getSheetName) |
|
|
|
.filter(StringUtils::isNotBlank) |
|
|
|
.distinct() |
|
|
|
.collect(Collectors.toList()); |
|
|
|
} |
|
|
|
|
|
|
|
private boolean hasCargoReadyDateEmptyError(SheetErrorInfo sheetError) { |
|
|
|
List<String> errorDetails = sheetError.getErrorDetails(); |
|
|
|
if (errorDetails == null || errorDetails.isEmpty()) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
return errorDetails.stream() |
|
|
|
.filter(StringUtils::isNotBlank) |
|
|
|
.anyMatch(detail -> detail.contains(CARGO_READY_DATE_EMPTY_ERROR_DETAIL)); |
|
|
|
} |
|
|
|
|
|
|
|
public static LocalDate parseDateCell(Cell cell) { |
|
|
|
if (cell == null) return null; |
|
|
|
|
|
|
|
|