Browse Source

fix(qms): 解决质检模块Excel导入和数据验证问题

- 添加检验类型编码验证,避免未知类型导致ItemNo为空
- 修复Excel导入时空行和空单元格处理逻辑
- 改进getCellStringValue方法,正确读取Excel单元格文本值
- 添加多个数据验证检查,包括项目描述、值类型等必填项验证
- 修复inspectTypeNo映射缺失的GX和***类型处理逻辑
- 优化数值类型字段的最大最小值解析逻辑
- 统一错误消息格式,提供更清晰的错误提示信息
master
qiankanghui 1 month ago
parent
commit
9b9ef49811
  1. 2
      src/main/java/com/xujie/modules/inspection/service/impl/InspectionRequestServiceImpl.java
  2. 99
      src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java

2
src/main/java/com/xujie/modules/inspection/service/impl/InspectionRequestServiceImpl.java

@ -1131,7 +1131,7 @@ public class InspectionRequestServiceImpl extends ServiceImpl<InspectionRequestH
Map<String, Object> poInfo = poDetailMapper.getPoDetailByOrderRef(site, dto.getPoNo(), dto.getPoItemNo());
if (poInfo == null) {
throw new RuntimeException(String.format(
"第%d行:PO号 %s 行号 %s 不存在,请检查外部订单号(order_ref1)和外部行号(order_ref2)",
"第%d行:PO号 %s 行号 %s 不存在,请检查外部订单号",
rowNum, dto.getPoNo(), dto.getPoItemNo()));
}

99
src/main/java/com/xujie/modules/qms/service/impl/QcServiceImpl.java

@ -228,6 +228,10 @@ public class QcServiceImpl implements QcService {
}else if ("***".equals(data.getInspectionTypeNo())) {
data.setItemNo("PF-" + itemNo);
}
// 检验类型不在编码规则内时直接报错,避免 ItemNo 为空导致 INSERT 失败
if (StringUtils.isBlank(data.getItemNo())) {
throw new RuntimeException("未知的检验类型编码:" + data.getInspectionTypeNo() + ",无法生成项目编码!");
}
List<QcItemData> checkItemOnlyOne = qcMapper.checkItemOnlyOne(data);
if (!checkItemOnlyOne.isEmpty()) {
throw new RuntimeException("该检验项目已存在!");
@ -315,13 +319,25 @@ public class QcServiceImpl implements QcService {
QcItemData task = null;
// 遍历每一行(从第二行开始)
for (int j = 1; j < rows; j++) {
// 实例化对象
task = new QcItemData();
//获得该行
XSSFRow row = sheet.getRow(j);
if (row == null) {
continue;
}
// 读取关键列(不能用 getRawValue,文本单元格它返回的是共享字符串表索引而非真实文本)
String itemDesc = getCellStringValue(row.getCell(0));
String inspectionTypeNo = getCellStringValue(row.getCell(3));
// 关键列均为空视为空行,跳过(避免模板残留空行导致插入失败)
if (StringUtils.isBlank(itemDesc) && StringUtils.isBlank(inspectionTypeNo)) {
continue;
}
// 实例化对象
task = new QcItemData();
// 为对象赋值
QcSiteBuHelper.resolveSiteParam(data.getSite(), task::setSite, task::setBuNo);
task.setInspectionTypeNo(row.getCell(3).getRawValue());
// itemType 必须在 getItemNo 之前设置,否则按类型查不到已有编码,每行都会生成相同编码
task.setItemType("D");
task.setInspectionTypeNo(inspectionTypeNo);
// 获取编码
String itemNo = qcMapper.getItemNo(task);
if ("101".equals(task.getInspectionTypeNo()) || "102".equals(task.getInspectionTypeNo()) || "103".equals(task.getInspectionTypeNo()) || "104".equals(task.getInspectionTypeNo())) {
@ -334,36 +350,40 @@ public class QcServiceImpl implements QcService {
task.setItemNo("FQC-" + itemNo);
} else if ("108".equals(task.getInspectionTypeNo())) {
task.setItemNo("PQC-" + itemNo);
} else if ("GX".equals(task.getInspectionTypeNo())) {
task.setItemNo("GX-" + itemNo);
} else if ("***".equals(task.getInspectionTypeNo())) {
task.setItemNo("PF-" + itemNo);
}
// 检验类型编码无效时明确报错,避免 ItemNo 为空导致 INSERT 失败
if (StringUtils.isBlank(task.getItemNo())) {
throw new RuntimeException("第" + (j + 1) + "行检验类型编码无效:" + task.getInspectionTypeNo());
}
if (StringUtils.isBlank(itemDesc)) {
throw new RuntimeException("第" + (j + 1) + "行检验项目描述不能为空!");
}
task.setItemDesc(row.getCell(0).getStringCellValue());
task.setValueType(row.getCell(1).getStringCellValue());
if (row.getCell(1).getStringCellValue().equals("文本")){
task.setItemDesc(itemDesc.trim());
String valueType = getCellStringValue(row.getCell(1));
if (StringUtils.isBlank(valueType)) {
throw new RuntimeException("第" + (j + 1) + "行值类型不能为空!");
}
task.setValueType(valueType);
if (valueType.equals("文本")){
task.setValueTypeDb("T");
task.setMaxValue(null);
task.setMinValue(null);
} else if (row.getCell(1).getStringCellValue().equals("数字")) {
} else if (valueType.equals("数字")) {
task.setValueTypeDb("N");
if (row.getCell(3) == null) {
task.setMaxValue(null);
} else {
task.setMaxValue(BigDecimal.valueOf(row.getCell(3).getNumericCellValue()));
}
if (row.getCell(4) == null) {
task.setMinValue(null);
} else {
task.setMinValue(BigDecimal.valueOf(row.getCell(4).getNumericCellValue()));
}
} else {
task.setValueTypeDb(null);
}
if (row.getCell(2) == null) {
task.setDefaultValue(null);
String maxValue = getCellStringValue(row.getCell(4));
task.setMaxValue(StringUtils.isBlank(maxValue) ? null : new BigDecimal(maxValue.trim()));
String minValue = getCellStringValue(row.getCell(5));
task.setMinValue(StringUtils.isBlank(minValue) ? null : new BigDecimal(minValue.trim()));
} else {
task.setDefaultValue(row.getCell(2).getRawValue());
throw new RuntimeException("第" + (j + 1) + "行值类型无效:" + valueType + "(只能填写 文本 或 数字)");
}
task.setItemType("D");
task.setDefaultValue(getCellStringValue(row.getCell(2)));
task.setCreatedBy(data.getCreateBy());
task.setMethodNo(row.getCell(5).getRawValue());
task.setMethodNo(getCellStringValue(row.getCell(6)));
// 新增
qcMapper.qcItemSave(task);
// 新增项目里的方法
@ -374,6 +394,35 @@ public class QcServiceImpl implements QcService {
}
}
/**
* 读取单元格的实际文本值。
* 不能直接使用 getRawValue():对文本单元格它返回的是共享字符串表的索引而不是真实文本;
* 这里按单元格类型分别取值,保证拿到用户在 Excel 中看到的内容。
**/
private String getCellStringValue(XSSFCell cell) {
if (cell == null) {
return null;
}
CellType cellType = cell.getCellType();
if (cellType == CellType.FORMULA) {
cellType = cell.getCachedFormulaResultType();
}
switch (cellType) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
}
// 按单元格显示格式取值,避免出现 105.0、科学计数法等格式偏差
return new DataFormatter().formatCellValue(cell).trim();
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
default:
return null;
}
}
// ======================= 质检员信息维护 =======================
/**

Loading…
Cancel
Save