Browse Source

2026-09-21

IQC基础数据导入
master
fengyuan_yang 2 months ago
parent
commit
460699439d
  1. 18
      src/main/java/com/heai/modules/pms/controller/QcController.java
  2. 4
      src/main/java/com/heai/modules/pms/mapper/QcMapper.java
  3. 499
      src/main/java/com/heai/modules/pms/service/Impl/QcServiceImpl.java
  4. 6
      src/main/java/com/heai/modules/pms/service/QcService.java
  5. 94
      src/main/java/com/heai/modules/pms/util/QcExcelImportHelper.java
  6. 32
      src/main/resources/mapper/pms/QcMapper.xml

18
src/main/java/com/heai/modules/pms/controller/QcController.java

@ -873,6 +873,24 @@ public class QcController {
return R.ok();
}
@PostMapping("/uploadPartAttrExcel")
public R uploadPartAttrExcel(@RequestParam(value = "file") MultipartFile file, @ModelAttribute GetParamInData data){
qcService.uploadPartAttrExcel(file, data);
return R.ok();
}
@PostMapping("/uploadPartTemplateExcel")
public R uploadPartTemplateExcel(@RequestParam(value = "file") MultipartFile file, @ModelAttribute GetParamInData data){
qcService.uploadPartTemplateExcel(file, data);
return R.ok();
}
@PostMapping("/uploadPartStandardExcel")
public R uploadPartStandardExcel(@RequestParam(value = "file") MultipartFile file, @ModelAttribute GetParamInData data){
qcService.uploadPartStandardExcel(file, data);
return R.ok();
}
// ======================= IPQC 巡检特殊配置(按工序) =======================
@PostMapping("/getPatrolConfigList")

4
src/main/java/com/heai/modules/pms/mapper/QcMapper.java

@ -121,6 +121,8 @@ public interface QcMapper {
QcItemData selectQcItemByNo(@Param("site") String site, @Param("itemNo") String itemNo);
QcFAIRecordData selectPartByExactNo(@Param("site") String site, @Param("partNo") String partNo);
QcTemplateData selectDetail(QcTemplateData data);
void saveItemDetailed(QcTemplateData data);
@ -189,6 +191,8 @@ public interface QcMapper {
void savePartAttributeDetails(QcTemplateData data);
void updatePartAttributeInspectionMethod(QcTemplateData data);
List<QcTemplateData> getTemplateList(QcTemplateData data);
List<QcTemplateData> getPartTemplateList(QcTemplateData data);

499
src/main/java/com/heai/modules/pms/service/Impl/QcServiceImpl.java

@ -1052,7 +1052,7 @@ public class QcServiceImpl implements QcService {
}
String pairKey = templateId + "||" + itemNo;
if (!excelKeys.add(pairKey)) {
throw new RuntimeException("同一模板下检验项目重复:" + itemNo);
throw new RuntimeException("Excel中检验模板【" + templateId + "】的检验项目【" + itemNo + "】重复");
}
QcTemplateData template = templateCache.get(templateId);
if (template == null) {
@ -1079,6 +1079,14 @@ public class QcServiceImpl implements QcService {
&& !template.getInspectionTypeNo().equals(item.getInspectionTypeNo())) {
throw new RuntimeException("检验项目【" + itemNo + "】与模板检验类型不匹配");
}
QcTemplateData existQuery = new QcTemplateData();
existQuery.setSite(StringUtils.defaultIfBlank(template.getSite(), site));
existQuery.setBuNo(StringUtils.defaultIfBlank(template.getBuNo(), buNo));
existQuery.setTemplateId(template.getTemplateId());
existQuery.setItemNo(item.getItemNo());
if (qcMapper.selectItemDetails(existQuery) != null) {
throw new RuntimeException("检验模板【" + template.getTemplateId() + "】下检验项目【" + item.getItemNo() + "】已存在");
}
String excelDefault = QcExcelImportHelper.getString(row, headers, "标准值");
BigDecimal excelMax = QcExcelImportHelper.getDecimal(row, headers, "最大值");
BigDecimal excelMin = QcExcelImportHelper.getDecimal(row, headers, "最小值");
@ -1102,7 +1110,10 @@ public class QcServiceImpl implements QcService {
}
Integer nextOrder = orderByTemplate.get(templateId);
if (nextOrder == null) {
nextOrder = 1;
nextOrder = qcMapper.getQCDetailOrderId(detail);
if (nextOrder == null) {
nextOrder = 1;
}
}
detail.setOrderId(nextOrder);
orderByTemplate.put(templateId, nextOrder + 1);
@ -1122,11 +1133,9 @@ public class QcServiceImpl implements QcService {
if (!errors.isEmpty()) {
throw new RuntimeException("导入失败:<br/>" + String.join("<br/>", errors));
}
Set<String> clearedTemplates = new HashSet<>();
for (QcTemplateData detail : toSave) {
String clearKey = detail.getSite() + "||" + detail.getBuNo() + "||" + detail.getTemplateId();
if (clearedTemplates.add(clearKey)) {
qcMapper.delTemplateItem(detail);
if (qcMapper.selectItemDetails(detail) != null) {
throw new RuntimeException("检验模板【" + detail.getTemplateId() + "】下检验项目【" + detail.getItemNo() + "】已存在");
}
qcMapper.addItemDetails(detail);
}
@ -1876,6 +1885,484 @@ public class QcServiceImpl implements QcService {
}
/**
* 物料属性导入(对应新增)
**/
@Override
@Transactional
public void uploadPartAttrExcel(MultipartFile file, GetParamInData paramData) {
String site = QcExcelImportHelper.resolveSite(paramData.getSite());
String buNo = QcExcelImportHelper.resolveBuNo();
List<String> errors = new ArrayList<>();
List<QcPartAttributeData> toSave = new ArrayList<>();
Set<String> partNos = new HashSet<>();
try (Workbook workbook = QcExcelImportHelper.openWorkbook(file)) {
Sheet sheet = QcExcelImportHelper.getDataSheet(workbook, QcExcelImportHelper.FLAG_PART_ATTR);
Map<String, Integer> headers = QcExcelImportHelper.readHeaderIndex(sheet.getRow(0));
int lastRow = sheet.getLastRowNum();
for (int r = 1; r <= lastRow; r++) {
Row row = sheet.getRow(r);
if (QcExcelImportHelper.isBlankRow(row, headers)) {
continue;
}
int excelRow = r + 1;
try {
String partNo = QcExcelImportHelper.getString(row, headers, "物料编码");
if (StringUtils.isBlank(partNo)) {
throw new RuntimeException("物料编码不能为空");
}
if (!partNos.add(partNo)) {
throw new RuntimeException("物料编码重复:" + partNo);
}
QcFAIRecordData part = qcMapper.selectPartByExactNo(site, partNo);
if (part == null) {
throw new RuntimeException("物料不存在:" + partNo);
}
QcPartAttributeData task = new QcPartAttributeData();
task.setSite(site);
task.setBuNo(buNo);
task.setPartNo(part.getPartNo());
task.setPartDesc(part.getPartDesc());
task.setAttributeType("A");
task.setCreateBy(paramData.getCreateBy());
task.setUpdateBy(paramData.getCreateBy());
task.setDefaultValue(blankToNull(QcExcelImportHelper.getString(row, headers, "默认值")));
task.setStandardValue(blankToNull(QcExcelImportHelper.getString(row, headers, "标准值")));
task.setMaxValue(blankToNull(QcExcelImportHelper.getString(row, headers, "上限值")));
task.setMinValue(blankToNull(QcExcelImportHelper.getString(row, headers, "下限值")));
task.setFirstIPQCPatrolTime(QcExcelImportHelper.getDecimal(row, headers, "首次巡检时长(h)", "首次巡检时长"));
task.setLastIPQCPatrolTime(QcExcelImportHelper.getDecimal(row, headers, "下次巡检时长(h)", "下次巡检时长"));
task.setCycleIPQCPatrolTime(QcExcelImportHelper.getDecimal(row, headers, "累计巡检时长(h)", "累计巡检时长"));
task.setIqcExempt(ynOrDefaultN(QcExcelImportHelper.getString(row, headers, "IQC检验")));
task.setIpqcExempt(ynOrDefaultN(QcExcelImportHelper.getString(row, headers, "IPQC检验")));
task.setOqcExempt(ynOrDefaultN(QcExcelImportHelper.getString(row, headers, "OQC检验")));
task.setFqcExempt(ynOrDefaultN(QcExcelImportHelper.getString(row, headers, "FQC检验")));
task.setSqcExempt(ynOrDefaultN(QcExcelImportHelper.getString(row, headers, "SQC检验")));
task.setFaiExempt("N");
task.setPqcExempt("N");
task.setExemptInspection("N");
task.setAttributeRemark(blankToNull(QcExcelImportHelper.getString(row, headers, "备注")));
if (qcMapper.selectPartAttributeByNo(task) != null) {
throw new RuntimeException("该物料属性已存在:" + partNo);
}
toSave.add(task);
} catch (RuntimeException e) {
errors.add("第" + excelRow + "行:" + e.getMessage());
}
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("导入失败:" + e.getMessage());
}
assertImportRows(toSave, errors);
for (QcPartAttributeData task : toSave) {
qcPartAttributeSave(task);
}
}
/**
* 物料检验模板导入(对应检验模板清单)
**/
@Override
@Transactional
public void uploadPartTemplateExcel(MultipartFile file, GetParamInData paramData) {
String site = QcExcelImportHelper.resolveSite(paramData.getSite());
String buNo = QcExcelImportHelper.resolveBuNo();
Map<String, String> typeNameMap = new HashMap<>();
for (QcInspectionTypeData type : loadInspectionTypes(site)) {
if (type != null && StringUtils.isNotBlank(type.getInspectionTypeNo())) {
typeNameMap.put(type.getInspectionTypeNo(), type.getInspectionTypeName());
}
}
Set<String> operations = loadOperationDescs();
Set<String> resources = loadResourceIds(site);
Map<String, String> suppliers = loadSupplierKeys(site);
Map<String, String> customers = loadCustomerKeys(site);
List<QcSamplingInspectionProgrammeData> programmes = loadSamplingProgrammes(site);
List<QcSamplingInspectionLevelData> levels = loadSamplingLevels(site);
List<String> errors = new ArrayList<>();
List<QcTemplateData> toSave = new ArrayList<>();
Set<String> excelKeys = new HashSet<>();
try (Workbook workbook = QcExcelImportHelper.openWorkbook(file)) {
Sheet sheet = QcExcelImportHelper.getDataSheet(workbook, QcExcelImportHelper.FLAG_PART_TEMPLATE);
Map<String, Integer> headers = QcExcelImportHelper.readHeaderIndex(sheet.getRow(0));
int lastRow = sheet.getLastRowNum();
for (int r = 1; r <= lastRow; r++) {
Row row = sheet.getRow(r);
if (QcExcelImportHelper.isBlankRow(row, headers)) {
continue;
}
int excelRow = r + 1;
try {
String partNo = QcExcelImportHelper.getString(row, headers, "物料编码");
if (StringUtils.isBlank(partNo)) {
throw new RuntimeException("物料编码不能为空");
}
String templateId = QcExcelImportHelper.getString(row, headers, "检验模板编码");
if (StringUtils.isBlank(templateId)) {
throw new RuntimeException("检验模板编码不能为空");
}
QcPartAttributeData partQuery = new QcPartAttributeData();
partQuery.setSite(site);
partQuery.setBuNo(buNo);
partQuery.setPartNo(partNo);
partQuery.setAttributeType("A");
if (qcMapper.selectPartAttributeByNo(partQuery) == null) {
throw new RuntimeException("物料属性不存在,请先导入物料属性:" + partNo);
}
QcTemplateData templateQuery = new QcTemplateData();
templateQuery.setSite(site);
templateQuery.setBuNo(buNo);
templateQuery.setTemplateId(templateId);
QcTemplateData template = qcMapper.selectTemplateData(templateQuery);
if (template == null) {
throw new RuntimeException("检验模板不存在:" + templateId);
}
String typeNo = template.getInspectionTypeNo();
String operation = blankToNull(QcExcelImportHelper.getString(row, headers, "工序"));
String resourceId = blankToNull(QcExcelImportHelper.getString(row, headers, "机台"));
String supplierInput = QcExcelImportHelper.getString(row, headers, "供应商");
String customerInput = QcExcelImportHelper.getString(row, headers, "客户");
String method = resolvePartInspectionMethod(typeNo, typeNameMap.get(typeNo),
QcExcelImportHelper.getString(row, headers, "检验方式"));
QcTemplateData detail = new QcTemplateData();
detail.setSite(site);
detail.setBuNo(buNo);
detail.setAttributeNo(partNo);
detail.setAttributeType("A");
detail.setTemplateId(template.getTemplateId());
detail.setInspectionTypeNo(typeNo);
detail.setUpdateBy(paramData.getCreateBy());
detail.setIpqcInspectionMethod(method);
String levelInput = QcExcelImportHelper.getString(row, headers, "检验水平编码");
String programmeInput = QcExcelImportHelper.getString(row, headers, "抽样方案编码");
detail.setSamplingLevelNo(StringUtils.isNotBlank(levelInput)
? resolveSamplingLevelNo(levelInput, levels) : template.getSamplingLevelNo());
detail.setSamplingProgrammeNo(StringUtils.isNotBlank(programmeInput)
? resolveSamplingProgrammeNo(programmeInput, programmes) : template.getSamplingProgrammeNo());
BigDecimal cycle = QcExcelImportHelper.getDecimal(row, headers, "检验周期(h)", "检验周期");
BigDecimal aql = QcExcelImportHelper.getDecimal(row, headers, "AQL");
BigDecimal ac = QcExcelImportHelper.getDecimal(row, headers, "AC");
BigDecimal re = QcExcelImportHelper.getDecimal(row, headers, "RE");
detail.setInspectionCycle(cycle != null ? cycle : template.getInspectionCycle());
detail.setAql(aql != null ? aql : template.getAql());
detail.setAc(ac != null ? ac : template.getAc());
detail.setRe(re != null ? re : template.getRe());
if (needsOperationAndResource(typeNo)) {
if (StringUtils.isNotBlank(supplierInput) || StringUtils.isNotBlank(customerInput)) {
throw new RuntimeException("当前检验类型只需填写工序和机台");
}
if (StringUtils.isNotBlank(resourceId) && StringUtils.isBlank(operation)) {
throw new RuntimeException("填写机台时必须填写工序");
}
if (StringUtils.isNotBlank(operation) && !operations.contains(operation)) {
throw new RuntimeException("工序不存在:" + operation);
}
if (StringUtils.isNotBlank(resourceId) && !resources.contains(resourceId)) {
throw new RuntimeException("机台不存在:" + resourceId);
}
detail.setOperation(operation);
detail.setResourceID(resourceId);
if (!qcMapper.getPA(detail).isEmpty()) {
if (StringUtils.isBlank(operation) && StringUtils.isBlank(resourceId)) {
throw new RuntimeException("未填写工序和机台的模板已存在");
}
if (StringUtils.isBlank(resourceId)) {
throw new RuntimeException("工序已存在:" + operation);
}
throw new RuntimeException("工序【" + operation + "】和机台【" + resourceId + "】的组合已存在");
}
} else if ("105".equals(typeNo)) {
if (StringUtils.isNotBlank(operation) || StringUtils.isNotBlank(resourceId) || StringUtils.isNotBlank(customerInput)) {
throw new RuntimeException("IQC只需填写供应商");
}
String supplierId = resolveMasterId(supplierInput, suppliers, "供应商");
detail.setManufacturerID(supplierId);
if (!qcMapper.getPA2(detail).isEmpty()) {
throw new RuntimeException(StringUtils.isBlank(supplierId) ? "未填写供应商的模板已存在" : "供应商已存在:" + supplierInput);
}
} else if ("110".equals(typeNo)) {
if (StringUtils.isNotBlank(operation) || StringUtils.isNotBlank(resourceId) || StringUtils.isNotBlank(supplierInput)) {
throw new RuntimeException("OQC只需填写客户");
}
String customerId = resolveMasterId(customerInput, customers, "客户");
if (StringUtils.isBlank(customerId)) {
throw new RuntimeException("客户不能为空");
}
detail.setCustomerID(customerId);
if (!qcMapper.getPA3(detail).isEmpty()) {
throw new RuntimeException("客户已存在:" + customerInput);
}
} else if (StringUtils.isNotBlank(operation) || StringUtils.isNotBlank(resourceId)
|| StringUtils.isNotBlank(supplierInput) || StringUtils.isNotBlank(customerInput)) {
throw new RuntimeException("当前检验类型不需要填写工序、机台、供应商或客户");
}
String excelKey = partNo + "|" + templateId + "|" + StringUtils.defaultString(detail.getOperation())
+ "|" + StringUtils.defaultString(detail.getResourceID())
+ "|" + StringUtils.defaultString(detail.getManufacturerID())
+ "|" + StringUtils.defaultString(detail.getCustomerID());
if (!excelKeys.add(excelKey)) {
throw new RuntimeException("Excel中存在重复的模板组合");
}
toSave.add(detail);
} catch (RuntimeException e) {
errors.add("第" + excelRow + "行:" + e.getMessage());
}
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("导入失败:" + e.getMessage());
}
assertImportRows(toSave, errors);
Set<String> syncedTemplateKeys = new HashSet<>();
for (QcTemplateData detail : toSave) {
savePartAttributeDetailAndSync(detail, syncedTemplateKeys);
if (StringUtils.isNotBlank(detail.getIpqcInspectionMethod())) {
qcMapper.updatePartAttributeInspectionMethod(detail);
}
}
}
/**
* 物料检验标准导入(qc_part_attr_detailed)
**/
@Override
@Transactional
public void uploadPartStandardExcel(MultipartFile file, GetParamInData paramData) {
String site = QcExcelImportHelper.resolveSite(paramData.getSite());
String buNo = QcExcelImportHelper.resolveBuNo();
List<String> errors = new ArrayList<>();
List<QcTemplateData> toSave = new ArrayList<>();
Map<String, Integer> orderByPart = new HashMap<>();
Set<String> excelKeys = new HashSet<>();
try (Workbook workbook = QcExcelImportHelper.openWorkbook(file)) {
Sheet sheet = QcExcelImportHelper.getDataSheet(workbook, QcExcelImportHelper.FLAG_PART_STANDARD);
Map<String, Integer> headers = QcExcelImportHelper.readHeaderIndex(sheet.getRow(0));
int lastRow = sheet.getLastRowNum();
for (int r = 1; r <= lastRow; r++) {
Row row = sheet.getRow(r);
if (QcExcelImportHelper.isBlankRow(row, headers)) {
continue;
}
int excelRow = r + 1;
try {
String partNo = QcExcelImportHelper.getString(row, headers, "物料编码");
if (StringUtils.isBlank(partNo)) {
throw new RuntimeException("物料编码不能为空");
}
String itemNo = QcExcelImportHelper.getString(row, headers, "检验项目编码");
if (StringUtils.isBlank(itemNo)) {
throw new RuntimeException("检验项目编码不能为空");
}
if (!excelKeys.add(partNo + "|" + itemNo)) {
throw new RuntimeException("Excel中物料【" + partNo + "】的检验项目【" + itemNo + "】重复");
}
QcPartAttributeData partQuery = new QcPartAttributeData();
partQuery.setSite(site);
partQuery.setBuNo(buNo);
partQuery.setPartNo(partNo);
partQuery.setAttributeType("A");
if (qcMapper.selectPartAttributeByNo(partQuery) == null) {
throw new RuntimeException("物料属性不存在,请先导入物料属性:" + partNo);
}
QcItemData item = qcMapper.selectQcItemByNo(site, itemNo);
if (item == null) {
throw new RuntimeException("检验项目不存在:" + itemNo);
}
QcTemplateData existQuery = new QcTemplateData();
existQuery.setSite(site);
existQuery.setBuNo(buNo);
existQuery.setAttributeNo(partNo);
existQuery.setItemNo(item.getItemNo());
if (qcMapper.selectPartAttrItemDetails(existQuery) != null) {
throw new RuntimeException("物料【" + partNo + "】下检验项目【" + item.getItemNo() + "】已存在");
}
String excelDefault = QcExcelImportHelper.getString(row, headers, "标准值");
BigDecimal excelMax = QcExcelImportHelper.getDecimal(row, headers, "最大值");
BigDecimal excelMin = QcExcelImportHelper.getDecimal(row, headers, "最小值");
QcTemplateData detail = new QcTemplateData();
detail.setSite(site);
detail.setBuNo(buNo);
detail.setAttributeNo(partNo);
detail.setAttributeType("A");
detail.setItemNo(item.getItemNo());
detail.setInspectionTypeNo(item.getInspectionTypeNo());
detail.setUpdateBy(paramData.getCreateBy());
detail.setDefaultValue(StringUtils.isNotBlank(excelDefault) ? excelDefault : item.getDefaultValue());
if ("T".equals(item.getValueTypeDb())) {
detail.setMaxValue(null);
detail.setMinValue(null);
} else {
detail.setMaxValue(excelMax != null ? excelMax : item.getMaxValue());
detail.setMinValue(excelMin != null ? excelMin : item.getMinValue());
if (detail.getMaxValue() != null && detail.getMinValue() != null
&& detail.getMaxValue().compareTo(detail.getMinValue()) < 0) {
throw new RuntimeException("最大值不能小于最小值");
}
}
Integer nextOrder = orderByPart.get(partNo);
if (nextOrder == null) {
nextOrder = qcMapper.getPartAttrDetailedMaxOrderId(detail);
if (nextOrder == null) {
nextOrder = 1;
}
}
detail.setOrderId(nextOrder);
orderByPart.put(partNo, nextOrder + 1);
toSave.add(detail);
} catch (RuntimeException e) {
errors.add("第" + excelRow + "行:" + e.getMessage());
}
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("导入失败:" + e.getMessage());
}
assertImportRows(toSave, errors);
Set<String> updatedParts = new HashSet<>();
for (QcTemplateData detail : toSave) {
if (qcMapper.selectPartAttrItemDetails(detail) != null) {
throw new RuntimeException("物料【" + detail.getAttributeNo() + "】下检验项目【" + detail.getItemNo() + "】已存在");
}
qcMapper.insertPartAttrDetailed(detail);
if (updatedParts.add(detail.getAttributeNo())) {
qcMapper.updatePartAttributeTime(detail);
}
}
}
private void assertImportRows(List<?> toSave, List<String> errors) {
if (toSave.isEmpty() && errors.isEmpty()) {
throw new RuntimeException("没有可导入的数据,请检查Excel内容");
}
if (!errors.isEmpty()) {
throw new RuntimeException("导入失败:<br/>" + String.join("<br/>", errors));
}
}
private String ynOrDefaultN(String value) {
if (StringUtils.isBlank(value)) {
return "N";
}
return QcExcelImportHelper.resolveYn(value);
}
private boolean needsOperationAndResource(String typeNo) {
return "101".equals(typeNo) || "102".equals(typeNo) || "103".equals(typeNo)
|| "104".equals(typeNo) || "106".equals(typeNo) || "107".equals(typeNo);
}
private String resolvePartInspectionMethod(String typeNo, String typeName, String value) {
boolean ipqc = "101".equals(typeNo) || (typeName != null && typeName.toUpperCase().contains("IPQC"));
boolean iqc = "105".equals(typeNo) || (typeName != null && typeName.toUpperCase().contains("IQC"));
if (!ipqc && !iqc) {
if (StringUtils.isNotBlank(value)) {
throw new RuntimeException("当前检验类型不需要填写检验方式");
}
return null;
}
if (StringUtils.isBlank(value)) {
throw new RuntimeException("检验方式不能为空");
}
String input = value.trim();
List<String> options = iqc ? QcExcelImportHelper.iqcInspectionMethods() : QcExcelImportHelper.ipqcInspectionMethods();
if (!options.contains(input)) {
throw new RuntimeException("检验方式不合法:" + value);
}
return input;
}
private Set<String> loadOperationDescs() {
Set<String> set = new HashSet<>();
List<QcPartAttributeData> list = qcMapper.getOperationDescList(new QcPartAttributeData());
if (list != null) {
for (QcPartAttributeData row : list) {
if (row != null && StringUtils.isNotBlank(row.getOperationDesc())) {
set.add(row.getOperationDesc().trim());
}
}
}
return set;
}
private Set<String> loadResourceIds(String site) {
Set<String> set = new HashSet<>();
QcFAIRecordData query = new QcFAIRecordData();
query.setSite(site);
List<QcFAIRecordData> list = qcMapper.getAllResourceList(query);
if (list != null) {
for (QcFAIRecordData row : list) {
if (row != null && StringUtils.isNotBlank(row.getResourceId())) {
set.add(row.getResourceId().trim());
}
}
}
return set;
}
private Map<String, String> loadSupplierKeys(String site) {
QcPartAttributeData query = new QcPartAttributeData();
query.setSite(site);
return toMasterKeyMap(qcMapper.getManufacturerList(query), true);
}
private Map<String, String> loadCustomerKeys(String site) {
QcPartAttributeData query = new QcPartAttributeData();
query.setSite(site);
return toMasterKeyMap(qcMapper.getCustomerList(query), false);
}
private Map<String, String> toMasterKeyMap(List<QcPartAttributeData> list, boolean supplier) {
Map<String, String> map = new HashMap<>();
if (list == null) {
return map;
}
for (QcPartAttributeData row : list) {
if (row == null) {
continue;
}
String id = supplier ? row.getManufacturerID() : row.getCustomerID();
String name = supplier ? row.getManufacturerName() : row.getCustomerName();
if (StringUtils.isBlank(id)) {
continue;
}
map.put("ID:" + id.trim(), id.trim());
if (StringUtils.isNotBlank(name)) {
String nameKey = "NAME:" + name.trim();
String exists = map.get(nameKey);
if (exists == null) {
map.put(nameKey, id.trim());
} else if (!exists.equals(id.trim())) {
map.put(nameKey, "");
}
}
}
return map;
}
private String resolveMasterId(String input, Map<String, String> keys, String label) {
if (StringUtils.isBlank(input)) {
return null;
}
String value = input.trim();
String byId = keys.get("ID:" + value);
if (StringUtils.isNotBlank(byId)) {
return byId;
}
String byName = keys.get("NAME:" + value);
if ("".equals(byName)) {
throw new RuntimeException(label + "名称不唯一,请填写编码:" + value);
}
if (StringUtils.isNotBlank(byName)) {
return byName;
}
throw new RuntimeException(label + "不存在:" + value);
}
// ======================= 类别属性设置维护 =======================
/**

6
src/main/java/com/heai/modules/pms/service/QcService.java

@ -181,6 +181,12 @@ public interface QcService {
void uploadPartAttributeExcel(MultipartFile file, GetParamInData data);
void uploadPartAttrExcel(MultipartFile file, GetParamInData data);
void uploadPartTemplateExcel(MultipartFile file, GetParamInData data);
void uploadPartStandardExcel(MultipartFile file, GetParamInData data);
void uploadFamilyAttributeExcel(MultipartFile file, GetParamInData data);
PageUtils qcFAIInspectionSearch(QcFAIRecordData data);

94
src/main/java/com/heai/modules/pms/util/QcExcelImportHelper.java

@ -44,6 +44,9 @@ public final class QcExcelImportHelper {
public static final String FLAG_ITEM = "item";
public static final String FLAG_TEMPLATE = "template";
public static final String FLAG_TEMPLATE_ITEM = "templateItem";
public static final String FLAG_PART_ATTR = "partAttr";
public static final String FLAG_PART_TEMPLATE = "partTemplate";
public static final String FLAG_PART_STANDARD = "partStandard";
public static final String DEFAULT_BU_NO = "*";
private static final int DATA_ROW_END = 1000;
@ -65,6 +68,7 @@ public final class QcExcelImportHelper {
public static class TemplateOptions {
private List<String> inspectionTypeNames = new ArrayList<>();
private List<String> inspectionMethods = new ArrayList<>();
public List<String> getInspectionTypeNames() {
return inspectionTypeNames;
@ -73,6 +77,22 @@ public final class QcExcelImportHelper {
public void setInspectionTypeNames(List<String> inspectionTypeNames) {
this.inspectionTypeNames = inspectionTypeNames == null ? new ArrayList<String>() : inspectionTypeNames;
}
public List<String> getInspectionMethods() {
return inspectionMethods;
}
public void setInspectionMethods(List<String> inspectionMethods) {
this.inspectionMethods = inspectionMethods == null ? new ArrayList<String>() : inspectionMethods;
}
}
public static List<String> ipqcInspectionMethods() {
return Arrays.asList("首件检", "自检", "巡检", "末件检");
}
public static List<String> iqcInspectionMethods() {
return Arrays.asList("材料进货检验", "刀模进货检验-外观", "刀模进货检验-上机", "刀模维修检验-外观", "刀模维修检验-上机");
}
private QcExcelImportHelper() {
@ -102,6 +122,25 @@ public final class QcExcelImportHelper {
return new String[]{"*检验模板编码", "*检验项目编码", "标准值", "最大值", "最小值"};
}
public static String[] partAttrHeaders() {
return new String[]{
"*物料编码", "默认值", "标准值", "上限值", "下限值",
"首次巡检时长(h)", "下次巡检时长(h)", "累计巡检时长(h)",
"IQC检验", "IPQC检验", "OQC检验", "FQC检验", "SQC检验", "备注"
};
}
public static String[] partTemplateHeaders() {
return new String[]{
"*物料编码", "*检验模板编码", "检验方式", "工序", "机台", "供应商", "客户",
"检验水平编码", "检验周期(h)", "抽样方案编码", "AQL", "AC", "RE"
};
}
public static String[] partStandardHeaders() {
return new String[]{"*物料编码", "*检验项目编码", "标准值", "最大值", "最小值"};
}
public static String dataSheetName(String flag) {
if (FLAG_METHOD.equals(flag)) {
return "检验方法";
@ -115,6 +154,15 @@ public final class QcExcelImportHelper {
if (FLAG_TEMPLATE_ITEM.equals(flag)) {
return "模板检验项目";
}
if (FLAG_PART_ATTR.equals(flag)) {
return "物料属性";
}
if (FLAG_PART_TEMPLATE.equals(flag)) {
return "物料检验模板";
}
if (FLAG_PART_STANDARD.equals(flag)) {
return "物料检验标准";
}
throw new RuntimeException("不支持的导入模板类型");
}
@ -158,7 +206,21 @@ public final class QcExcelImportHelper {
note = "带*列为必填。检验类型、检验值类型、需上传图片请用下拉选择。方法编码、抽样方案编码、检验水平编码请按系统中已有编码手填。填写抽样方案时须同时填写检验水平。项目编码由系统自动生成。";
} else if (FLAG_TEMPLATE_ITEM.equals(flag)) {
headers = templateItemHeaders();
note = "带*列为必填。同一模板在本次Excel中的行将覆盖该模板原有检验项目清单,序号按Excel顺序从1开始。标准值、最大值、最小值不填则取检验项目上的值;填写则以Excel为准。不导入判定标准。";
note = "带*列为必填。只新增,不覆盖原有检验项目。同一模板下检验项目不能与已有清单或本次Excel重复,重复则整批不导入。序号接在原有清单之后,按Excel顺序排列。标准值、最大值、最小值不填则取检验项目上的值;填写则以Excel为准。不导入判定标准。";
needFixedDropdown = false;
} else if (FLAG_PART_ATTR.equals(flag)) {
headers = partAttrHeaders();
note = "带*列为必填。物料名称按物料编码自动带出。IQC检验、IPQC检验、OQC检验、FQC检验、SQC检验请选择 是 或 否,不填按否。工厂取当前用户默认工厂。";
} else if (FLAG_PART_TEMPLATE.equals(flag)) {
headers = partTemplateHeaders();
note = "带*列为必填。工序、机台、供应商可以不填;填写机台时必须同时填写工序。OQC需填写客户。检验水平编码、检验周期、抽样方案编码、AQL、AC、RE不填则取检验模板上的值,填写则以Excel为准。检验水平、抽样方案须为系统中已有编码或名称。检验方式在IPQC、IQC时必填。";
List<String> methods = new ArrayList<>();
methods.addAll(ipqcInspectionMethods());
methods.addAll(iqcInspectionMethods());
options.setInspectionMethods(methods);
} else if (FLAG_PART_STANDARD.equals(flag)) {
headers = partStandardHeaders();
note = "带*列为必填。只新增,不覆盖原有检验标准。同一物料下检验项目不能与已有标准或本次Excel重复,重复则整批不导入。序号接在原有标准之后,按Excel顺序排列。标准值、最大值、最小值不填则取检验项目上的值;填写则以Excel为准。";
needFixedDropdown = false;
} else {
headers = templateHeaders();
@ -180,13 +242,19 @@ public final class QcExcelImportHelper {
textStyle.setDataFormat(workbook.createDataFormat().getFormat("@"));
applyTextColumns(sheet, headers, textStyle,
"检验类型", "检验值类型", "方法编码", "抽样方案编码", "检验水平编码", "需上传图片",
"检验模板编码", "检验项目编码", "标准值");
"检验模板编码", "检验项目编码", "标准值", "物料编码", "检验方式", "工序", "机台", "供应商", "客户");
if (needFixedDropdown) {
writeOptionsSheet(workbook, options);
addDropdown(sheet, headers, "检验类型", "optInspectionType");
addDropdown(sheet, headers, "检验值类型", "optValueType");
addDropdown(sheet, headers, "需上传图片", "optYn");
addDropdown(sheet, headers, "IQC检验", "optYn");
addDropdown(sheet, headers, "IPQC检验", "optYn");
addDropdown(sheet, headers, "OQC检验", "optYn");
addDropdown(sheet, headers, "FQC检验", "optYn");
addDropdown(sheet, headers, "SQC检验", "optYn");
addDropdown(sheet, headers, "检验方式", "optInspectMethod");
}
Sheet noteSheet = workbook.createSheet("填写说明");
@ -216,6 +284,15 @@ public final class QcExcelImportHelper {
if (FLAG_TEMPLATE_ITEM.equals(flag)) {
return "模板检验项目导入模板.xlsx";
}
if (FLAG_PART_ATTR.equals(flag)) {
return "物料属性导入模板.xlsx";
}
if (FLAG_PART_TEMPLATE.equals(flag)) {
return "物料检验模板导入模板.xlsx";
}
if (FLAG_PART_STANDARD.equals(flag)) {
return "物料检验标准导入模板.xlsx";
}
return "QC导入模板.xlsx";
}
@ -421,19 +498,28 @@ public final class QcExcelImportHelper {
private static void writeOptionsSheet(Workbook workbook, TemplateOptions options) {
Sheet sheet = workbook.createSheet(OPTIONS_SHEET);
String[] titles = {"检验类型", "检验值类型", "需上传图片"};
boolean hasMethods = sizeOf(options.getInspectionMethods()) > 0;
String[] titles = hasMethods
? new String[]{"检验类型", "检验值类型", "需上传图片", "检验方式"}
: new String[]{"检验类型", "检验值类型", "需上传图片"};
Row titleRow = sheet.createRow(0);
for (int i = 0; i < titles.length; i++) {
titleRow.createCell(i).setCellValue(titles[i]);
sheet.setColumnWidth(i, 18 * 256);
sheet.setColumnWidth(i, 22 * 256);
}
writeOptionColumn(sheet, 0, options.getInspectionTypeNames());
writeOptionColumn(sheet, 1, Arrays.asList("文本", "数字"));
writeOptionColumn(sheet, 2, Arrays.asList("是", "否"));
if (hasMethods) {
writeOptionColumn(sheet, 3, options.getInspectionMethods());
}
createName(workbook, "optInspectionType", 0, sizeOf(options.getInspectionTypeNames()));
createName(workbook, "optValueType", 1, 2);
createName(workbook, "optYn", 2, 2);
if (hasMethods) {
createName(workbook, "optInspectMethod", 3, sizeOf(options.getInspectionMethods()));
}
}
private static void writeOptionColumn(Sheet sheet, int col, List<String> values) {

32
src/main/resources/mapper/pms/QcMapper.xml

@ -160,6 +160,14 @@
WHERE site = #{site} AND ItemNo = #{itemNo} AND ItemType = 'D'
</select>
<select id="selectPartByExactNo" resultType="com.heai.modules.pms.data.QcFAIRecordData">
SELECT TOP 1
PartNo,
PartDescription AS partDesc
FROM part
WHERE site = #{site} AND PartNo = #{partNo}
</select>
<!-- 检测是否存在该项目 -->
<select id="checkQcItem" parameterType="com.heai.modules.pms.data.QcItemData" resultType="com.heai.modules.pms.data.QcItemData">
SELECT ItemNo,
@ -1441,6 +1449,20 @@
#{attributeType}, #{operation}, #{manufacturerID}, #{resourceID}, #{site}, #{buNo}, #{customerID}, #{inspectionTypeNo})
</insert>
<update id="updatePartAttributeInspectionMethod" parameterType="com.heai.modules.pms.data.QcTemplateData">
UPDATE qc_attribute_template
SET ipqc_inspection_method = #{ipqcInspectionMethod}
WHERE site = #{site}
AND bu_no = #{buNo}
AND attribute_no = #{attributeNo}
AND attribute_type = #{attributeType}
AND template_id = #{templateId}
AND ISNULL(operation, '') = ISNULL(#{operation, jdbcType=VARCHAR}, '')
AND ISNULL(resource_id, '') = ISNULL(#{resourceID, jdbcType=VARCHAR}, '')
AND ISNULL(manufacturer_id, '') = ISNULL(#{manufacturerID, jdbcType=VARCHAR}, '')
AND ISNULL(customer_id, '') = ISNULL(#{customerID, jdbcType=VARCHAR}, '')
</update>
<!-- 可选模板 -->
<select id="getTemplateList" resultType="com.heai.modules.pms.data.QcTemplateData" parameterType="com.heai.modules.pms.data.QcTemplateData">
SELECT
@ -3925,7 +3947,15 @@
attribute_type,
manufacturer_id
FROM qc_attribute_template
WHERE site = #{site} and bu_no = #{buNo} and attribute_no = #{attributeNo} and attribute_type = #{attributeType} and template_id = #{templateId} and manufacturer_id = #{manufacturerID}
WHERE site = #{site} and bu_no = #{buNo} and attribute_no = #{attributeNo} and attribute_type = #{attributeType} and template_id = #{templateId}
<choose>
<when test="manufacturerID != null and manufacturerID != ''">
AND manufacturer_id = #{manufacturerID}
</when>
<otherwise>
AND (manufacturer_id IS NULL OR manufacturer_id = '')
</otherwise>
</choose>
</select>
<!-- 校验物料属性模板:客户 -->

Loading…
Cancel
Save