package com.vci.ubcs.code.service.impl; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.common.utils.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.vci.ubcs.code.bo.AttributeValue; import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO; import com.vci.ubcs.code.bo.CodeTemplateAttrSqlBO; import com.vci.ubcs.code.dto.CodeOrderDTO; import com.vci.ubcs.code.entity.CodeAllCode; import com.vci.ubcs.code.entity.CodeClassify; import com.vci.ubcs.code.enumpack.CodeDefaultLC; import com.vci.ubcs.code.enumpack.CodeLevelTypeEnum; import com.vci.ubcs.code.lifecycle.CodeAllCodeLC; import com.vci.ubcs.code.mapper.CommonsMapper; import com.vci.ubcs.code.service.*; import com.vci.ubcs.code.util.ClientBusinessObject; import com.vci.ubcs.code.vo.CodeKeyAttrRepeatVO; import com.vci.ubcs.code.vo.pagemodel.*; import com.vci.ubcs.code.vo.webserviceModel.attrmap.DataObjectVO; import com.vci.ubcs.code.vo.webserviceModel.attrmap.RowDatas; import com.vci.ubcs.code.vo.webserviceModel.result.xml.XMLResultDataObjectDetailDO; import com.vci.ubcs.omd.feign.IBtmTypeClient; import com.vci.ubcs.omd.vo.BtmTypeVO; import com.vci.ubcs.starter.bo.WriteExcelData; import com.vci.ubcs.starter.exception.VciBaseException; import com.vci.ubcs.starter.poi.bo.ReadExcelOption; import com.vci.ubcs.starter.poi.bo.SheetDataSet; import com.vci.ubcs.starter.poi.bo.SheetRowData; import com.vci.ubcs.starter.poi.bo.WriteExcelOption; import com.vci.ubcs.starter.poi.util.ExcelUtil; import com.vci.ubcs.starter.revision.model.BaseModel; import com.vci.ubcs.starter.util.DefaultAttrAssimtUtil; import com.vci.ubcs.starter.util.LocalFileUtil; import com.vci.ubcs.starter.util.MdmBtmTypeConstant; import com.vci.ubcs.starter.web.constant.QueryOptionConstant; import com.vci.ubcs.starter.web.enumpck.BooleanEnum; import com.vci.ubcs.starter.web.enumpck.VciFieldTypeEnum; import com.vci.ubcs.starter.web.pagemodel.DataGrid; import com.vci.ubcs.starter.web.pagemodel.KeyValue; import com.vci.ubcs.starter.web.pagemodel.PageHelper; import com.vci.ubcs.starter.web.pagemodel.UIFormReferVO; import com.vci.ubcs.starter.web.toolmodel.DateConverter; import com.vci.ubcs.starter.web.util.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.map.HashedMap; import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Workbook; import org.springblade.core.redis.cache.BladeRedis; import org.springblade.core.tool.api.R; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.io.File; import java.io.IOException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.stream.Collectors; import static com.alibaba.druid.util.FnvHash.Constants.LIMIT; import static com.vci.ubcs.code.constant.MdmEngineConstant.*; import static com.vci.ubcs.starter.poi.util.ExcelUtil.*; @AllArgsConstructor @Service @Slf4j public class MdmIOServiceImpl implements MdmIOService { /** * 字段 */ public static final String ROW_INDEX = "LAY_TABLE_INDEX"; /** * 错误信息的字段 */ public static final String ERROR_MSG = "errorMsg"; @Value("${batchadd.exportattr.type:基本信息}") public String BATCHADD_EXCEPORT_ATTR_TYPE; @Value("${batchadd.redis.time:6000000}") public int BATCHADD_REDIS_TIME; /** * 主题库分类的服务 */ @Resource private ICodeClassifyService classifyService; /** * 通用查询 */ @Resource private CommonsMapper commonsMapper; /**** * 码值服务 */ @Resource ICodeAllCodeService codeAllCodeService; /** * 模板的服务 */ @Resource private CodeClstemplateServiceImpl templateService; /** * 主数据引擎的服务 */ @Resource private MdmEngineService engineService; /*** * resdis缓存服务 */ private final BladeRedis bladeRedis; /** * 生成编码的服务 */ @Resource private MdmProductCodeService productCodeService; /** * 关键属性的配置 */ @Autowired private ICodeKeyAttrRepeatService keyRuleService; /** * 公式的服务 */ @Autowired private FormulaServiceImpl formulaService; /** * 规则的服务 */ @Autowired private ICodeRuleService ruleService; /** * 业务类型的服务 */ @Autowired private IBtmTypeClient btmTypeClient; /** * 批量申请:选取选中分类下的所有模板关键属性,相似属性,必填属性,写入execl中 * * @param codeClassifyOid 分类的主键 * @return excel的文件地址 */ @Override public String downloadTopImportExcel(String codeClassifyOid){ List templateVOList=new ArrayList<>(); VciBaseUtil.alertNotNull("导出模板","导出的配置",codeClassifyOid,"主题库分类的主键"); CodeClassifyVO codeClassifyVO = classifyService.getObjectByOid(codeClassifyOid); templateVOList= templateService.childTemplates(codeClassifyOid); List codeClassifyVOS=classifyService.getIdPathToNamePathByParentId(codeClassifyOid,true); WriteExcelOption eo = new WriteExcelOption(); LinkedHashMap allFieldToOutNameMap=new LinkedHashMap<>(); templateVOList.stream().forEach(templateVO -> { //组合格式的不导入, // 枚举的提供序列的选择 //时间全部统一为yyyy-MM-dd HH:mm:ss //参照的自行输入名称 //分类注入的不用,都是导入后自动处理的 //编码,状态等字段不导入 List templateAttrVOS = templateVO.getAttributes().stream().filter(s -> !DEFAULT_ATTR_LIST.contains(s.getId()) && StringUtils.isBlank(s.getComponentRule()) && StringUtils.isBlank(s.getClassifyInvokeAttr()) && (VciBaseUtil.getBoolean(s.getFormDisplayFlag())) ).collect(Collectors.toList()); if(CollectionUtils.isEmpty(templateAttrVOS)){ throw new VciBaseException("模板没有配置任何【表单显示】为【是】的属性"); } templateAttrVOS.stream().forEach(codetemplateAttr ->{ String field=codetemplateAttr.getId(); String name=codetemplateAttr.getName(); CodeClassifyTemplateAttrVO codeBaseAttributeDTO=new CodeClassifyTemplateAttrVO(); boolean res=codetemplateAttr.getAttributeGroup().equals(BATCHADD_EXCEPORT_ATTR_TYPE)//基本属性字段显示 ||(StringUtils.isNotBlank(codetemplateAttr.getKeyAttrFlag())&&Boolean.parseBoolean(codetemplateAttr.getKeyAttrFlag()))//关键属性的存入 ||(StringUtils.isNotBlank(codetemplateAttr.getSameRepeatAttrFlag())&&Boolean.parseBoolean(codetemplateAttr.getSameRepeatAttrFlag())) //相似属性的存入 ||(StringUtils.isNotBlank(codetemplateAttr.getRequireFlag())&&Boolean.parseBoolean(codetemplateAttr.getRequireFlag())); if(allFieldToOutNameMap.containsKey(name)){//如果存在的话则需要根据具体的去赋值 codeBaseAttributeDTO= allFieldToOutNameMap.get(name); if(StringUtils.isNotBlank(codetemplateAttr.getKeyAttrFlag())&&Boolean.parseBoolean(codetemplateAttr.getKeyAttrFlag())){ codeBaseAttributeDTO.setKeyAttrFlag(codetemplateAttr.getKeyAttrFlag());//属性关键属性 } if(StringUtils.isNotBlank(codetemplateAttr.getRequireFlag())&&Boolean.parseBoolean(codetemplateAttr.getRequireFlag())){ codeBaseAttributeDTO.setRequireFlag(codetemplateAttr.getRequireFlag());//属性必填项 } if(StringUtils.isNotBlank(codetemplateAttr.getSameRepeatAttrFlag())&&Boolean.parseBoolean(codetemplateAttr.getSameRepeatAttrFlag())){ codeBaseAttributeDTO.setSameRepeatAttrFlag(codetemplateAttr.getSameRepeatAttrFlag());//属性相似属性 } }else if(res){ allFieldToOutNameMap.put(name,codetemplateAttr); } }); }); //整理好所有模板需要写入execl的属性信息 Workbook workbook = new HSSFWorkbook(); LinkedList excelDataList = new LinkedList<>(); if(!CollectionUtils.isEmpty(allFieldToOutNameMap)){ excelDataList.add(new WriteExcelData(0,0,"分类路径")); final int[] index = {0}; allFieldToOutNameMap.values().stream().forEach(attrVO -> { Object text = attrVO.getName(); text = exportKeyAndRequired(workbook,attrVO,text); int colIndex = 1 + index[0]++; WriteExcelData excelData = new WriteExcelData(0, colIndex, text); if(StringUtils.isNotBlank(attrVO.getCodeDateFormat()) || VciFieldTypeEnum.VTDateTime.name().equalsIgnoreCase(attrVO.getAttributeDataType()) || VciFieldTypeEnum.VTDate.name().equalsIgnoreCase(attrVO.getAttributeDataType()) ||VciFieldTypeEnum.VTTime.name().equalsIgnoreCase(attrVO.getAttributeDataType())){ excelData.setDateFormat(VciDateUtil.DateTimeFormat); } if(text instanceof RichTextString){ excelData.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex())); } excelDataList.add(excelData); if(StringUtils.isNotBlank(attrVO.getEnumString()) || StringUtils.isNotBlank(attrVO.getEnumId())){ //添加数据有效性 List enumValueList = new ArrayList<>(); enumValueList.add(""); List valueList = engineService.listComboboxItems(attrVO); if(!CollectionUtils.isEmpty(valueList)){ valueList.stream().forEach(kv->{ enumValueList.add(kv.getValue()); }); } //默认加1万条 WriteExcelData ed = new WriteExcelData(1,colIndex,""); ed.setRowTo(100); ed.setColTo(colIndex); ed.setValidation(true); ed.setValidationDataList(enumValueList); ed.setValidationErrorMsg("请在序列中选择正确的值"); excelDataList.add(ed); } if(VciFieldTypeEnum.VTBoolean.name().equalsIgnoreCase(attrVO.getAttributeDataType())){ List booleanList = new ArrayList<>(); booleanList.add("是"); booleanList.add("否"); //默认加1万条 WriteExcelData ed = new WriteExcelData(1,colIndex,""); ed.setRowTo(100); ed.setColTo(colIndex); ed.setValidation(true); ed.setValidationDataList(booleanList); ed.setValidationErrorMsg("请在序列中选择正确的值"); excelDataList.add(ed); } }); eo.addSheetDataList(codeClassifyVO.getName()+"导入模板",excelDataList); } LinkedList classPathList = new LinkedList<>(); classPathList.add(new WriteExcelData(0,0,"分类层级")); WriteExcelData idPathWriteExcelTitle=new WriteExcelData(0,1,"分类ID路径"); idPathWriteExcelTitle.setWidth(20); idPathWriteExcelTitle.setCenter(false); classPathList.add(idPathWriteExcelTitle); WriteExcelData namePathWriteExcelTitle=new WriteExcelData(0,2,"分类名称路径"); namePathWriteExcelTitle.setWidth(20); namePathWriteExcelTitle.setCenter(false); classPathList.add(namePathWriteExcelTitle); final int[] rowIndex = {1}; codeClassifyVOS.stream().forEach(codeClassifyVO1 -> { classPathList.add(new WriteExcelData(rowIndex[0],0,codeClassifyVO1.getDataLevel())); String idPath=codeClassifyVO1.getIdPath().startsWith("#")?codeClassifyVO1.getIdPath().substring(1):codeClassifyVO1.getIdPath(); WriteExcelData idPathWriteExcelData=new WriteExcelData(rowIndex[0],1,idPath); idPathWriteExcelData.setWidth(30); idPathWriteExcelData.setCenter(false); classPathList.add(idPathWriteExcelData); String namePath=codeClassifyVO1.getNamePath().startsWith("#")?codeClassifyVO1.getNamePath().substring(1):codeClassifyVO1.getNamePath(); WriteExcelData namePathWriteExcelData= new WriteExcelData(rowIndex[0],2,namePath); namePathWriteExcelData.setWidth(40); namePathWriteExcelData.setCenter(false); classPathList.add(namePathWriteExcelData); rowIndex[0]++; }); WriteExcelData excelData=new WriteExcelData(); excelData.setMerged(true); excelData.setRow(1); excelData.setRowTo(2); excelData.setCol(4); excelData.setColTo(9); excelData.setCenter(false); excelData.setReadOnly(true); excelData.setObj("导入数据时,分类路径必须填写叶子节点路径\n(选择叶子节点导入则不需要填写分类路径)"); excelData.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex())); classPathList.add(excelData); eo.addSheetDataList(codeClassifyVO.getName()+"分类对照表",classPathList); String excelName = LocalFileUtil.getDefaultTempFolder() + File.separator + codeClassifyVO.getName() + "_导入模板.xls"; // eo.addSheetDataList(templateVOList.size()+"模板信息【请勿删除或移动】",tempEDList); ExcelUtil.writeDataToFile(excelName,eo); return excelName; } /** * 生成导入的文件 * * @param codeClassifyOid 分类的主键 * @param isHistory 是否历史数据导入 * @return excel的文件地址 */ @Override public String createImportExcel(String codeClassifyOid, boolean isHistory) { List templateVOList=new ArrayList<>(); VciBaseUtil.alertNotNull("导出模板","导出的配置",codeClassifyOid,"主题库分类的主键"); CodeClassifyVO codeClassifyVO = classifyService.getObjectByOid(codeClassifyOid); if(isHistory){ templateVOList= templateService.childTemplates(codeClassifyOid); }else{ //找模板 CodeClassifyTemplateVO templateVO = engineService.getUsedTemplateByClassifyOid(codeClassifyOid); templateVOList.add(templateVO); } WriteExcelOption eo = new WriteExcelOption(); eo.setAppend(true); //增加模板的信息导入 LinkedList tempEDList = new LinkedList<>(); tempEDList.add(new WriteExcelData(0,0,"模板主键")); tempEDList.add(new WriteExcelData(0,1,"模板代号")); tempEDList.add(new WriteExcelData(0,2,"模板名称")); for(int j=0;j templateAttrVOS = codeClassifyTemplateVO.getAttributes().stream().filter(s -> !DEFAULT_ATTR_LIST.contains(s.getId()) && StringUtils.isBlank(s.getComponentRule()) && StringUtils.isBlank(s.getClassifyInvokeAttr()) && (isHistory || VciBaseUtil.getBoolean(s.getFormDisplayFlag())) ).collect(Collectors.toList()); if(CollectionUtils.isEmpty(templateAttrVOS)){ throw new VciBaseException("模板没有配置任何【表单显示】为【是】的属性"); } List idAttrVOList = codeClassifyTemplateVO.getAttributes().stream().filter(s -> s.getId().equalsIgnoreCase(CODE_FIELD)).collect(Collectors.toList()); LinkedList excelDataList = new LinkedList<>(); Workbook workbook = new HSSFWorkbook(); if(isHistory){ excelDataList.add(new WriteExcelData(0,0,"分类路径")); excelDataList.add(new WriteExcelData(0,1,"码段宽度")); excelDataList.add(new WriteExcelData(0,2,!CollectionUtils.isEmpty(idAttrVOList)?idAttrVOList.get(0).getName():"企业编码")); } for (int i = 0; i < templateAttrVOS.size(); i++) { CodeClassifyTemplateAttrVO attrVO = templateAttrVOS.get(i); Object text = attrVO.getName(); text = exportKeyAndRequired(workbook,attrVO,text); int colIndex = (isHistory?3:0) + i; WriteExcelData excelData = new WriteExcelData(0, colIndex, text); if(StringUtils.isNotBlank(attrVO.getCodeDateFormat()) || VciFieldTypeEnum.VTDateTime.name().equalsIgnoreCase(attrVO.getAttributeDataType()) || VciFieldTypeEnum.VTDate.name().equalsIgnoreCase(attrVO.getAttributeDataType()) ||VciFieldTypeEnum.VTTime.name().equalsIgnoreCase(attrVO.getAttributeDataType())){ excelData.setDateFormat(VciDateUtil.DateTimeFormat); } if(text instanceof RichTextString){ excelData.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex())); } excelDataList.add(excelData); if(StringUtils.isNotBlank(attrVO.getEnumString()) || StringUtils.isNotBlank(attrVO.getEnumId())){ //添加数据有效性 List enumValueList = new ArrayList<>(); enumValueList.add(""); List valueList = engineService.listComboboxItems(attrVO); if(!CollectionUtils.isEmpty(valueList)){ valueList.stream().forEach(kv->{ enumValueList.add(kv.getValue()); }); } //默认加1万条 WriteExcelData ed = new WriteExcelData(1,colIndex,""); ed.setRowTo(100); ed.setColTo(colIndex); ed.setValidation(true); ed.setValidationDataList(enumValueList); ed.setValidationErrorMsg("请在序列中选择正确的值"); excelDataList.add(ed); } if(VciFieldTypeEnum.VTBoolean.name().equalsIgnoreCase(attrVO.getAttributeDataType())){ List booleanList = new ArrayList<>(); booleanList.add("是"); booleanList.add("否"); //默认加1万条 WriteExcelData ed = new WriteExcelData(1,colIndex,""); ed.setRowTo(100); ed.setColTo(colIndex); ed.setValidation(true); ed.setValidationDataList(booleanList); ed.setValidationErrorMsg("请在序列中选择正确的值"); excelDataList.add(ed); } } eo.addSheetDataList(j+templateVO.getName(),excelDataList); tempEDList.add(new WriteExcelData(j+1,0,templateVO.getOid())); tempEDList.add(new WriteExcelData(j+1,1,templateVO.getId())); tempEDList.add(new WriteExcelData(j+1,2,templateVO.getName())); } String excelName = LocalFileUtil.getDefaultTempFolder() + File.separator + codeClassifyVO.getName() + (isHistory?"_历史数据导入模板.xls": "_导入模板.xls"); eo.addSheetDataList(templateVOList.size()+"模板信息【请勿删除或移动】",tempEDList); ExcelUtil.writeDataToFile(excelName,eo); return excelName; } /** * 导出的时候封装必输和关键属性 * @param attrVO 属性的显示对象 * @param text 单元格的值 */ private Object exportKeyAndRequired(Workbook workbook,CodeClassifyTemplateAttrVO attrVO,Object text){ //必输加*,关键属性为蓝色 if (VciBaseUtil.getBoolean(attrVO.getRequireFlag()) || VciBaseUtil.getBoolean(attrVO.getKeyAttrFlag())) { String value = text.toString(); if(VciBaseUtil.getBoolean(attrVO.getRequireFlag())) { value += REQUIRED_CHAR; } if(VciBaseUtil.getBoolean(attrVO.getKeyAttrFlag())){ value += KEY_ATTR_CHAR; } RichTextString ts = new HSSFRichTextString(value); if(VciBaseUtil.getBoolean(attrVO.getRequireFlag())){ Font font = workbook.createFont(); font.setColor(HSSFColor.HSSFColorPredefined.RED.getIndex()); ts.applyFont(font); } if(VciBaseUtil.getBoolean(attrVO.getKeyAttrFlag())){ Font font = workbook.createFont(); font.setColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex()); ts.applyFont(font); } return ts; } return text; } /** * 批量申请编码数据 * * @param orderDTO 编码申请信息,必须包含分类主键和码段的信息 * @param file excel文件的信息 * @return 有错误信息的excel的文件 */ @Override public CodeImProtRusultVO batchImportCode(CodeOrderDTO orderDTO, File file) { VciBaseUtil.alertNotNull(orderDTO,"编码申请相关的数据",orderDTO.getCodeClassifyOid(),"主题库分类主键"); ReadExcelOption reo = new ReadExcelOption(); reo.setReadAllSheet(true); List sheetDataSetList = ExcelUtil.readDataObjectFromExcel(file,null,reo); if(CollectionUtils.isEmpty(sheetDataSetList) || CollectionUtils.isEmpty(sheetDataSetList.get(0).getRowData()) ||sheetDataSetList.get(0).getRowData().size()<1){ throw new VciBaseException("没有读取到任何的数据"); } if(sheetDataSetList.size()>LIMIT+1){ throw new VciBaseException("为了保证系统的稳定性,请一次不要导入超过1万条的数据"); } //先找到每一行的标题,然后根据标题来获取对应的属性 SheetDataSet dataSet = sheetDataSetList.get(0); //找第一行,为了找标题 CodeClassifyTemplateVO templateVO = engineService.getUsedTemplateByClassifyOid(orderDTO.getCodeClassifyOid()); //校验模板是不是最新的 checkTemplateSync(sheetDataSetList,templateVO,0); //先不用管属性是否都存在,先转换一下数据 Map errorMap = new HashMap<>(); String redisUUid=batchImportCodes(orderDTO,templateVO,dataSet,errorMap,true); CodeImProtRusultVO codeImProtRusultVO = new CodeImProtRusultVO(); List needRowIndexList = new ArrayList<>(); String filePath = returnErrorToExcel(dataSet.getRowData(), errorMap, needRowIndexList, dataSet.getColName()); if(StringUtils.isNotBlank(filePath)) { codeImProtRusultVO.setFilePath(filePath); } if(StringUtils.isNotBlank(redisUUid)){ codeImProtRusultVO.setRedisUuid(redisUUid); } // return null; return codeImProtRusultVO; } /*** * 从顶层批量申请导入方法 * @param codeClassifyOid 分类的主键 * @param classifyAttr 分类路径使用的属性 * @param file excel文件的信息 * @return */ @Override public CodeImProtRusultVO batchTopImportCode(String codeClassifyOid, String classifyAttr, File file) { VciBaseUtil.alertNotNull(codeClassifyOid,"分类的主键"); ReadExcelOption reo = new ReadExcelOption(); reo.setReadAllSheet(true); List sheetDataSetList = ExcelUtil.readDataObjectFromExcel(file,null,reo); if(CollectionUtils.isEmpty(sheetDataSetList) || CollectionUtils.isEmpty(sheetDataSetList.get(0).getRowData()) ||sheetDataSetList.get(0).getRowData().size()<1){ throw new VciBaseException("没有读取到任何的数据"); } if(sheetDataSetList.size()>LIMIT+1){ throw new VciBaseException("为了保证系统的稳定性,请一次不要导入超过1万条的数据"); } //先找到每一行的标题,然后根据标题来获取对应的属性 SheetDataSet dataSet = sheetDataSetList.get(0); CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(codeClassifyOid); //获取当前模板 CodeClassifyTemplateVO selectCodeClassifyTemplateVO =engineService.getUsedTemplateByClassifyOid(codeClassifyOid); Map> templateColumnVOMap=new HashMap<>(); createTemplate(selectCodeClassifyTemplateVO,templateColumnVOMap); List childClassifyVOs = classifyService.listChildrenClassify(codeClassifyOid, true, classifyAttr, true); Map pathMap = Optional.ofNullable(childClassifyVOs).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getPath().startsWith("#") ? s.getPath().substring(1) : s.getPath(), t -> t)); pathMap.put("#current#", classifyFullInfo.getCurrentClassifyVO()); List titleRowData = dataSet.getColName(); Map errorMap = new ConcurrentHashMap<>(); //首先将数据以模板的形式分开 LinkedHashMap> codeclassifyDataMap=new LinkedHashMap<>(); List codeClassifyDatas=new ArrayList<>(); createExeclClassData(dataSet,pathMap,errorMap,codeClassifyDatas); //根据模板将数据整合在一起,去校验 Map/**数据对象**/> templateDatasMap =codeClassifyDatas.stream().collect(Collectors.toMap(CodeImprotDataVO::getTemplateOid,s->{ List l=new ArrayList<>(); l.add(s); return l; },(List s1,List s2)->{ s1.addAll(s2); return s1; })); String uuid=VciBaseUtil.getPk(); List codeImportTemplateVOS=new ArrayList<>(); Map codeRuleMap=new HashMap<>(); //相似数据 // MapwpResembleMap=new HashMap<>(); // List wpCodeImprotDataVOList=new ArrayList<>(); //按照模板去整理数据 templateDatasMap.keySet().stream().forEach(templateVOOid->{ List codeImprotDataVOS= templateDatasMap.get(templateVOOid); CodeClassifyTemplateVO templateVO= templateService.getObjectHasAttrByOid(templateVOOid); //除去默认的属性.还有只有表单显示的字段才导入 List attrVOS = templateVO.getAttributes().stream().filter(s -> !DEFAULT_ATTR_LIST.contains(s.getId()) && VciBaseUtil.getBoolean(s.getFormDisplayFlag()) ).collect(Collectors.toList()); Map fieldNameMap =attrVOS.stream().collect(Collectors.toMap(CodeClassifyTemplateAttrVO::getId,s->s.getName())); List allCboList=new ArrayList<>(); codeImprotDataVOS.stream().forEach(codeImprotDataVO -> { ListcolumnVOList =new ArrayList(); String templateOid=selectCodeClassifyTemplateVO.getOid(); if(templateColumnVOMap.containsKey(templateOid)){ columnVOList= columnVOList=templateColumnVOMap.get(templateOid); }else{ createTemplate(templateVO,templateColumnVOMap); columnVOList= columnVOList=templateColumnVOMap.get(templateOid); } String codeRuleOid=codeImprotDataVO.getCodeRuleOid(); if(!codeRuleMap.containsKey(codeRuleOid)){ CodeImportTemplateVO codeImportTemplateVO=new CodeImportTemplateVO(); codeImportTemplateVO.setRoot(false); codeImportTemplateVO.setCodeClassifyOid(codeImprotDataVO.getCodeClassifyOid()); codeImportTemplateVO.setCodeRuleOid(codeImprotDataVO.getCodeRuleOid()); codeImportTemplateVO.setCodeTemplateOid (codeImprotDataVO.getTemplateOid()); codeImportTemplateVO.setCodeClassifyVO( codeImprotDataVO.getCodeClassifyVO()); codeImportTemplateVO.setCodeClassifyTemplateVO( codeImprotDataVO.getCodeClassifyTemplateVO()); codeImportTemplateVO.setCodeRuleVO(codeImprotDataVO.getCodeRuleVO()); List colNames=codeImprotDataVO.getColNames(); codeImportTemplateVO.setCloNamesList(columnVOList); codeImportTemplateVOS.add(codeImportTemplateVO); codeRuleMap.put(codeRuleOid,codeImportTemplateVO); } List cboList=new ArrayList<>(); excelToCbo(classifyFullInfo,codeImprotDataVO,cboList,true); allCboList.addAll(cboList); //往选择的节点里面加数据 // CodeImprotDataVO wpcodeImprotDataVO=new CodeImprotDataVO(); // BeanUtilForVCI.copyPropertiesIgnoreCase(codeImprotDataVO,wpcodeImprotDataVO); /* wpcodeImprotDataVO.setCodeClassifyOid(codeClassifyOid); wpcodeImprotDataVO.setCodeClassifyVO(classifyFullInfo.getCurrentClassifyVO()); wpcodeImprotDataVO.setCodeClassifyTemplateVO(selectCodeClassifyTemplateVO); wpcodeImprotDataVO.setCodeRuleOid(classifyFullInfo.getCurrentClassifyVO().getCoderuleoid());*/ // wpCodeImprotDataVOList.add(wpcodeImprotDataVO);//往物品对象里添加 }); //都转换完了。需要批量检查 //如果出错了,我们依然执行有效的数据,无效的数据写回到excel中 //2.判断必输项。。需要全部的属性,如果是必输,但是表单里面不显示的,只能是分类注入或者组合规则 batchCheckRequiredAttrOnOrder(templateVO,allCboList,errorMap); //3.判断关键属性 CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, allCboList); Set selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList(); Set keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList(); if(!CollectionUtils.isEmpty(selfRepeatRowIndexList)){ selfRepeatRowIndexList.stream().forEach(rowIndex->{ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";在当前处理的数据文件中关键属性重复" ); }); } if(!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)){ keyAttrRepeatRowIndexList.stream().forEach(rowIndex->{ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" ); }); } //分类注入 // batchSwitchClassifyAttrOnOrder(attrVOS,allCboList,classifyFullInfo,false); //boolean reSwitchBooleanAttrOnOrder(attrVOS,allCboList); //4.校验规则 batchCheckVerifyOnOrder(attrVOS, allCboList,errorMap); //是否需要校验枚举/参照 //5.校验枚举是否正确 batchSwitchEnumAttrOnOrder(attrVOS, allCboList, errorMap); //7.处理参照的情况 batchSwitchReferAttrOnOrder(attrVOS,allCboList,errorMap); //6.时间格式的验证 //6.时间的,必须统一为yyyy-MM-dd HH:mm:ss batchSwitchDateAttrOnOrder(attrVOS,allCboList,errorMap); //设置默认值 batchSwitchAttrDefault(attrVOS, allCboList); //最后弄组合规则 batchSwitchComponentAttrOnOrder(attrVOS,allCboList); Map rowIndexCboMap = allCboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getAttributeValue((IMPORT_ROW_INDEX)), t -> t)); List needSaveCboList = allCboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return !errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); //相似校验 MapresembleMap=new HashMap<>(); List dataResembleVOS=new ArrayList<>(); String btmtypeid= classifyFullInfo.getTopClassifyVO().getBtmtypeid(); bathcResembleQuery(codeClassifyOid,templateVO,needSaveCboList,resembleMap,btmtypeid,dataResembleVOS); if(resembleMap.size()>0) { if(!CollectionUtils.isEmpty(dataResembleVOS)) { bladeRedis.set(uuid + "-resemble-data", dataResembleVOS); bladeRedis.expire(uuid + "-resemble-data",BATCHADD_REDIS_TIME);//redis过期时间 // createRedisDatas(uuid + "-resemble", codeImprotDataVOS, resembleMap, false); // wpResembleMap.putAll(resembleMap); } } //排除错误的,剩下正确的 Map newErrorMap=new HashMap<>(); newErrorMap.putAll(resembleMap); newErrorMap.putAll(errorMap); needSaveCboList = allCboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return !newErrorMap.containsKey(rowIndex); }).collect(Collectors.toList()); if(newErrorMap.size()>0) { createRedisDatas(uuid + "-resemble",codeImprotDataVOS, newErrorMap,false); } createRedisDatas(uuid + "-ok",codeImprotDataVOS, newErrorMap,true); }); //往物品节点上加模板 List needRowIndexList=new ArrayList<>(); CodeImProtRusultVO codeImProtRusultVO = new CodeImProtRusultVO(); if(errorMap.size()>0) { String filePath = returnErrorToExcel(dataSet.getRowData(), errorMap, needRowIndexList, dataSet.getColName()); if (StringUtils.isNotBlank(filePath)) { codeImProtRusultVO.setFilePath(filePath); } } if(StringUtils.isNotBlank(uuid)){ //将所有的分类存入缓存之中 codeImProtRusultVO.setRedisUuid(uuid); /** ListcolumnVOList=new ArrayList<>(); CodeImportTemplateVO wpCodeImportTemplateVO=new CodeImportTemplateVO(); wpCodeImportTemplateVO.setRoot(true); wpCodeImportTemplateVO.setCodeClassifyTemplateVO(selectCodeClassifyTemplateVO); wpCodeImportTemplateVO.setCodeClassifyVO(classifyFullInfo.getCurrentClassifyVO()); String templateOid=selectCodeClassifyTemplateVO.getOid(); if(templateColumnVOMap.containsKey(templateOid)){ columnVOList= columnVOList=templateColumnVOMap.get(templateOid); }else{ createTemplate(selectCodeClassifyTemplateVO,templateColumnVOMap); columnVOList= columnVOList=templateColumnVOMap.get(templateOid); } wpCodeImportTemplateVO.setCloNamesList(columnVOList); codeImportTemplateVOS.add(wpCodeImportTemplateVO); if(wpResembleMap.size()>0){ // redisService.setCacheList(uuid + "-resemble-data", wpDataResembleVOList); createRedisDatas(uuid + "-resemble",selectCodeClassifyTemplateVO, wpCodeImprotDataVOList, wpResembleMap, false,codeClassifyOid); } //排除错误的,剩下正确的 Map newErrorMap=new HashMap<>(); newErrorMap.putAll(wpResembleMap); newErrorMap.putAll(errorMap); List needSaveCboList = wpCodeImprotDataVOList.stream().filter(cbo -> { String rowIndex = cbo.getRowIndex(); return !newErrorMap.containsKey(rowIndex); }).collect(Collectors.toList()); createRedisDatas(uuid + "-ok",selectCodeClassifyTemplateVO,wpCodeImprotDataVOList, newErrorMap,true,codeClassifyOid);****/ if(codeImportTemplateVOS.size()>0){ bladeRedis.set(uuid + "-class",codeImportTemplateVOS); bladeRedis.expire(uuid + "-class",BATCHADD_REDIS_TIME); } } return codeImProtRusultVO; } /** * 导入历史数据 * * @param codeClassifyOid 分类的主键 * @param classifyAttr 分类路径使用的属性 * @param file excel文件的信息 * @return 有错误信息的excel */ @Override public CodeImProtRusultVO batchImportHistoryData(String codeClassifyOid, String classifyAttr,File file) { VciBaseUtil.alertNotNull(codeClassifyOid,"分类的主键"); ReadExcelOption reo = new ReadExcelOption(); reo.setReadAllSheet(true); List sheetDataSetList = ExcelUtil.readDataObjectFromExcel(file,null,reo); if (sheetDataSetList.size() > LIMIT + 1) { throw new VciBaseException("为了保证系统的稳定性,请一次不要导入超过1万条的数据"); } Map> shetNameMap=new HashMap<>(); //相似项目查重 String uuid=VciBaseUtil.getPk(); boolean isCreateUUid=false; boolean isExport=false; for(int i=0;i rowDataList = dataSet.getRowData(); //找第一行,为了找标题 CodeClassifyTemplateVO templateVO = new CodeClassifyTemplateVO(); /** if (!templateService.checkChildHasSameTemplate(classifyFullInfo.getCurrentClassifyVO().getOid())) { throw new VciBaseException("当前的分类以及下级分类的模板不相同"); }***/ //都转换完了。需要批量检查 //找所有的分类路径,需要校验路径是否正确,是否都在当前的分类的下级 List childClassifyVOs = classifyService.listChildrenClassify(codeClassifyOid, true, classifyAttr, true); Map pathMap = Optional.ofNullable(childClassifyVOs).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getPath().startsWith("#") ? s.getPath().substring(1) : s.getPath(), t -> t)); List titleRowData = dataSet.getColName(); Map errorMap = new ConcurrentHashMap<>(); pathMap.put("#current#",classifyFullInfo.getCurrentClassifyVO()); try { List templateVOList= checkSamesTemplate(titleRowData,sheetDataSetList,i,pathMap,errorMap); templateVO= templateVOList.get(0); }catch (Throwable e){ throw new VciBaseException(e.getMessage()); } List needowDataList = rowDataList.stream().filter(cbo -> { String rowIndex = cbo.getRowIndex(); return !errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); //checkTemplateSync(sheetDataSetList, templateVO,i); //这里不除去默认的属性 List attrVOS = templateVO.getAttributes(); Map fieldIndexMap = new HashMap<>(); Map attrNameIdMap = attrVOS.stream().collect(Collectors.toMap(s -> s.getName(), t -> t.getId())); String idFieldName = attrVOS.stream().filter(s -> VciQueryWrapperForDO.ID_FIELD.equalsIgnoreCase(s.getId())).findFirst().orElseGet(() -> new CodeClassifyTemplateAttrVO()).getName(); getFieldIndexMap(titleRowData, attrNameIdMap, fieldIndexMap); //先不用管属性是否都存在,先转换一下数据 List cboList = new ArrayList<>(); String fullPath = getFullPath(classifyFullInfo); //我们需要获取到所有的下级分类的oid的路径,因为后面需要 Map childOidPathMap = getChildClassifyPathMap(classifyFullInfo, fullPath); excelToCbo(classifyFullInfo, fieldIndexMap, needowDataList, templateVO, cboList, fullPath, false); Map classifyVOMap = Optional.ofNullable(childClassifyVOs).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t)); classifyVOMap.put(classifyFullInfo.getCurrentClassifyVO().getOid(), classifyFullInfo.getCurrentClassifyVO()); pathMap.put("#current#", classifyFullInfo.getCurrentClassifyVO()); //判断编号在excel里本身就重复的 Map idCountMap = cboList.stream().collect(Collectors.groupingBy(ClientBusinessObject::getId, Collectors.counting())); List repeatIdList = new ArrayList<>(); idCountMap.forEach((id, count) -> { if (count > 1) { repeatIdList.add(id); } }); if (!CollectionUtils.isEmpty(repeatIdList)) { cboList.stream().filter(s -> repeatIdList.contains(s.getId())).map(s -> s.getAttributeValue(IMPORT_ROW_INDEX)).forEach(rowIndex -> { errorMap.put(rowIndex, "编号在当前excel中重复;"); }); } //我们需要判断这些分类的模板是不是一样的,只需要校验,不用获取 //检查分类的路径 checkClassifyPathInHistory(cboList, errorMap, pathMap, childOidPathMap); //检查规则 Map ruleOidMap = new ConcurrentHashMap(); List unExistRuleClassifyOidList = new CopyOnWriteArrayList<>(); checkRuleOidInHistory(classifyVOMap, ruleOidMap, unExistRuleClassifyOidList); //如果出错了,我们依然执行有效的数据,无效的数据写回到excel中 //我们根据出错的分类的主键,去找行号 if (!CollectionUtils.isEmpty(unExistRuleClassifyOidList)) { cboList.stream().forEach(cbo -> { if (unExistRuleClassifyOidList.contains(cbo.getAttributeValue(CODE_CLASSIFY_OID_FIELD))) { String row_index = cbo.getAttributeValue(IMPORT_ROW_INDEX); errorMap.put(row_index, errorMap.getOrDefault(row_index, "") + ";根据分类路径对应的分类,没有设置编码规则"); } }); } //判断必输项 batchCheckRequiredAttrOnOrder(templateVO, cboList, errorMap); //有限校验编码是否存在 batchCheckIdExistOnOrder(templateVO, cboList, errorMap); //boolean reSwitchBooleanAttrOnOrder(attrVOS, cboList); // 枚举的内容需要根据名称转换为枚举的值 batchSwitchEnumAttrOnOrder(attrVOS, cboList, errorMap); batchSwitchReferAttrOnOrder(attrVOS, cboList, errorMap); //6.处理分类注入 batchSwitchClassifyAttrOnOrder(attrVOS, cboList, classifyFullInfo,true); //设置默认值 batchSwitchAttrDefault(attrVOS, cboList); //7.处理组合规则 batchSwitchComponentAttrOnOrder(attrVOS, cboList); //3.判断关键属性 CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList); Set selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList(); Set keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList(); if (!CollectionUtils.isEmpty(selfRepeatRowIndexList)) { selfRepeatRowIndexList.stream().forEach(rowIndex -> { errorMap.put(rowIndex, errorMap.getOrDefault(rowIndex, "") + ";在当前excel文件中关键属性重复"); }); } if (!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)) { keyAttrRepeatRowIndexList.stream().forEach(rowIndex -> { errorMap.put(rowIndex, errorMap.getOrDefault(rowIndex, "") + ";关键属性与系统中的重复"); }); } //4.校验规则 batchCheckVerifyOnOrder(attrVOS, cboList, errorMap); //6.时间的,必须统一为yyyy-MM-dd HH:mm:ss batchSwitchDateAttrOnOrder(attrVOS, cboList, errorMap); if (CollectionUtils.isEmpty(ruleOidMap.values())) { throw new VciBaseException("导入的数据所选择的分类都没有设置编码规则"); } Map ruleVOMap = ruleService.listCodeRuleByIds(ruleOidMap.values(), true).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t)); //校验编码规则和码段是否正确 Map> ruleRowIndexMap = new ConcurrentHashMap<>(); checkSecLengthInHistory(cboList, classifyVOMap, ruleVOMap, ruleOidMap, errorMap, ruleRowIndexMap); ruleRowIndexMap.keySet().parallelStream().forEach(ruleOid -> { List rowIndexList = ruleRowIndexMap.get(ruleOid); List thisCbos = cboList.stream().filter(cbo -> rowIndexList.contains(cbo.getAttributeValue(IMPORT_ROW_INDEX)) && !errorMap.containsKey(cbo.getAttributeValue(IMPORT_ROW_INDEX))).collect(Collectors.toList()); //我们需要先查询一下,内容是否已经存在 if(!CollectionUtils.isEmpty(thisCbos)){ List existIds = new ArrayList<>(); VciBaseUtil.switchCollectionForOracleIn(thisCbos).stream().forEach(cbos -> { List codeAllCodeList= codeAllCodeService.selectByWrapper(Wrappers.query().lambda().eq(CodeAllCode::getCodeRuleOid, ruleOid) .notIn(CodeAllCode::getId,cbos.stream().map(s -> s.getId()).collect(Collectors.toSet()).toArray(new String[0])) .notIn(CodeAllCode::getLcStatus,CodeAllCodeLC.TASK_BACK.getValue() + "','" + CodeAllCodeLC.OBSOLETED.getValue()) ); existIds.addAll(Optional.ofNullable(codeAllCodeList).orElseGet(() -> new ArrayList<>()).stream().map(s -> { String id = s.getId(); if (StringUtils.isBlank(id)) { id = s.getId(); } return id; }).collect(Collectors.toList())); }); List existIdCbos = thisCbos.stream().filter(s -> { String id = s.getId(); if (StringUtils.isBlank(id)) { id = s.getAttributeValue("id"); } return existIds.contains(id); }).map(s -> s.getAttributeValue(IMPORT_ROW_INDEX)).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(existIdCbos)) { thisCbos = thisCbos.stream().filter(s -> { String id = s.getId(); if (StringUtils.isBlank(id)) { id = s.getAttributeValue("id"); } return !existIdCbos.contains(id); }).collect(Collectors.toList()); existIdCbos.stream().forEach(rowIndex -> { errorMap.put(rowIndex, errorMap.getOrDefault(rowIndex, "") + ";【" + idFieldName + "】在系统中已经被占用"); }); } } }); Map rowIndexCboMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getAttributeValue((IMPORT_ROW_INDEX)), t -> t)); if (errorMap.size() > 0) { isExport=true; createRedisDatas(uuid + "-error", templateVO, rowIndexCboMap, dataSet, fieldIndexMap, errorMap, false); } createWriteExcelData(rowDataList, errorMap, new ArrayList<>(), titleRowData, shetNameMap, templateVO); List needSaveCboList = cboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return !errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); //相似校验 Map resembleMap = new HashMap<>(); List dataResembleVOS = new ArrayList<>(); String btmtypeid = classifyFullInfo.getTopClassifyVO().getBtmtypeid(); bathcResembleQuery(templateVO.getCodeclassifyoid(), templateVO, needSaveCboList, resembleMap, btmtypeid, dataResembleVOS); if (resembleMap.size() > 0) { if (!CollectionUtils.isEmpty(dataResembleVOS)) { bladeRedis.set(uuid + "-resemble-data", dataResembleVOS); createRedisDatas(uuid + "-resemble", templateVO, rowIndexCboMap, dataSet, fieldIndexMap, resembleMap, false); } } //生成class缓存 Map rowIndexClsOidMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getAttributeValue((IMPORT_ROW_INDEX)), t -> t.getAttributeValue(CODE_CLASSIFY_OID_FIELD))); createRedisByCodeClassify(uuid + "-class",templateVO,dataSet,fieldIndexMap,true); //获取编码,查询在系统中是否被其他的引用了 //排除错误的,剩下正确的 Map newErrorMap = new HashMap<>(); newErrorMap.putAll(resembleMap); newErrorMap.putAll(errorMap); //要把以上的错误的都抛出后,再继续处理时间和组合规则 needSaveCboList = cboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return !newErrorMap.containsKey(rowIndex); }).collect(Collectors.toList()); if((errorMap.size()>0&&needSaveCboList.size()>0)||resembleMap.size()>0){ isCreateUUid=true; } List needRowIndexList = needSaveCboList.stream().filter(s -> errorMap.containsKey(s.getAttributeValue(IMPORT_ROW_INDEX))).map(s -> s.getAttributeValue(IMPORT_ROW_INDEX)).collect(Collectors.toList()); if (isExport||newErrorMap.size() > 0) { createRedisDatas(uuid + "-ok", templateVO, rowIndexCboMap, dataSet, fieldIndexMap, newErrorMap, true); } else { List dataCBOIdList=new ArrayList<>(); //SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo(); List finalNeedSaveCboList = needSaveCboList; CodeClassifyTemplateVO finalTemplateVO = templateVO; ruleRowIndexMap.keySet().parallelStream().forEach(ruleOid -> { //VciBaseUtil.setCurrentUserSessionInfo(sessionInfo); List rowIndexList = ruleRowIndexMap.get(ruleOid); List thisCbos = finalNeedSaveCboList.stream().filter(cbo -> rowIndexList.contains(cbo.getAttributeValue(IMPORT_ROW_INDEX)) && !errorMap.containsKey(cbo.getAttributeValue(IMPORT_ROW_INDEX))).collect(Collectors.toList()); List dataCBOList=new ArrayList<>(); thisCbos.stream().forEach(clientBusinessObject -> { BaseModel baseModel=new BaseModel(); BeanUtil.convert(clientBusinessObject,baseModel); baseModel.setData(VciBaseUtil.objectToMapString(clientBusinessObject)); dataCBOList.add(baseModel); dataCBOIdList.add(baseModel.getOid()); }); if (!CollectionUtils.isEmpty(thisCbos)) { try { productCodeService.productCodeAndSaveData(classifyFullInfo, finalTemplateVO, ruleVOMap.get(ruleOid), null, dataCBOList); } catch (Throwable e) { log.error("批量产生编码的时候出错了", e); thisCbos.stream().forEach(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); errorMap.put(rowIndex, errorMap.getOrDefault(rowIndex, "") + ";系统错误,存储数据的时候出错了"); }); } } }); engineService.batchSaveSelectChar(templateVO, dataCBOIdList); } } String excelFileName=""; if(isExport&&!CollectionUtils.isEmpty(shetNameMap)) { excelFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + "错误信息.xls"; WriteExcelOption eo = new WriteExcelOption(); shetNameMap.forEach((shetName, errorDataList) -> { eo.addSheetDataList(shetName, errorDataList); }); try { new File(excelFileName).createNewFile(); } catch (IOException e) { throw new VciBaseException(LangBaseUtil.getErrorMsg(e)); } ExcelUtil.writeDataToFile(excelFileName, eo); } CodeImProtRusultVO codeImProtRusultVO=new CodeImProtRusultVO(); if(StringUtils.isNotBlank(excelFileName)) { codeImProtRusultVO.setFilePath(excelFileName); codeImProtRusultVO.setFileOid(""); } if(isCreateUUid){ codeImProtRusultVO.setRedisUuid(uuid); } return codeImProtRusultVO; } /*** * 从execl里构建对象 * @param rowDataList * @param errorMap * @param needRowIndexList * @param titleRowData * @param shetNameMap * @param templateVO */ private void createWriteExcelData(Collection rowDataList, Map errorMap, List needRowIndexList, List titleRowData, Map> shetNameMap, CodeClassifyTemplateVO templateVO){ List errorDataList=new ArrayList<>(); Map rowIndexDataMap = rowDataList.stream().filter(s -> !needRowIndexList.contains(s.getRowIndex())).collect(Collectors.toMap(s -> s.getRowIndex(), t -> t)); errorDataList.add(new WriteExcelData(0,0,"错误信息")); for (int i = 0; i < titleRowData.size(); i++) { //错误信息在最后 errorDataList.add(new WriteExcelData(0,i+1,titleRowData.get(i))); } Integer[] newRowIndex = new Integer[]{1}; errorMap.forEach((index,error)->{ //错误信息全部组合到一起 SheetRowData rowData = rowIndexDataMap.getOrDefault(index, null); if(rowData!=null){ errorDataList.add(new WriteExcelData(newRowIndex[0],0,error)); rowData.getData().forEach((colIndex,value)->{ errorDataList.add(new WriteExcelData(newRowIndex[0],colIndex+1,value)); }); newRowIndex[0]++; } }); shetNameMap.put(templateVO.getName(),errorDataList); } /*** * * @param currentTemplateVO * @param templateColumnVOMap */ private void createTemplate(CodeClassifyTemplateVO currentTemplateVO,Map>templateColumnVOMap){ List templateAttrVOS = currentTemplateVO.getAttributes().stream().filter(s -> !DEFAULT_ATTR_LIST.contains(s.getId()) && StringUtils.isBlank(s.getComponentRule()) && StringUtils.isBlank(s.getClassifyInvokeAttr()) && (VciBaseUtil.getBoolean(s.getFormDisplayFlag())) ).collect(Collectors.toList()); if(CollectionUtils.isEmpty(templateAttrVOS)){ throw new VciBaseException("模板没有配置任何【表单显示】为【是】的属性"); } List columnVOList=new ArrayList<>(); ColumnVO errorMsgColumnVO=new ColumnVO(); errorMsgColumnVO.setTitle("错误信息"); errorMsgColumnVO.setField("errorMsg"); columnVOList.add(errorMsgColumnVO); ColumnVO pathColumnVO=new ColumnVO(); pathColumnVO.setTitle("分类路径"); pathColumnVO.setField("codeclsfid"); columnVOList.add(pathColumnVO); templateAttrVOS.stream().forEach(codetemplateAttr ->{ String field=codetemplateAttr.getId(); String name=codetemplateAttr.getName(); ColumnVO columnVO=new ColumnVO(); columnVO.setTitle(name); columnVO.setField(field); columnVO.setWidth(codetemplateAttr.getAttrTableWidth()==0?columnVO.getWidth():codetemplateAttr.getAttrTableWidth()); columnVOList.add(columnVO); }); templateColumnVOMap.put(currentTemplateVO.getOid(),columnVOList); log.info("模板"+currentTemplateVO.getName()+"对应的属性"+columnVOList.size()); } /** * 错误信息返回excel * @param rowDataList 所有的导入数据 * @param errorMap 错误的信息 * @param needRowIndexList 需要写入的数据的行号 * @param titleRowData 标题行 * * @return 错误的excel文件,没有错误会返回空 */ private String returnErrorToExcel(Collection rowDataList, Map errorMap, List needRowIndexList,List titleRowData){ if(CollectionUtils.isEmpty(errorMap)){ return ""; } Map rowIndexDataMap = rowDataList.stream().filter(s -> !needRowIndexList.contains(s.getRowIndex())).collect(Collectors.toMap(s -> s.getRowIndex(), t -> t)); List errorDataList = new ArrayList<>(); errorDataList.add(new WriteExcelData(0,0,"错误信息")); for (int i = 0; i < titleRowData.size(); i++) { //错误信息在最后 errorDataList.add(new WriteExcelData(0,i+1,titleRowData.get(i))); } Integer[] newRowIndex = new Integer[]{1}; errorMap.forEach((index,error)->{ //错误信息全部组合到一起 SheetRowData rowData = rowIndexDataMap.getOrDefault(index, null); if(rowData!=null){ errorDataList.add(new WriteExcelData(newRowIndex[0],0,error)); rowData.getData().forEach((colIndex,value)->{ errorDataList.add(new WriteExcelData(newRowIndex[0],colIndex+1,value)); }); newRowIndex[0]++; } }); String excelFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + "错误信息.xls"; WriteExcelOption eo = new WriteExcelOption(errorDataList); try { new File(excelFileName).createNewFile(); } catch (IOException e) { throw new VciBaseException(LangBaseUtil.getErrorMsg(e)); } ExcelUtil.writeDataToFile(excelFileName,eo); return excelFileName; } /** * 校验模板是否为同步的 * @param sheetDataSetList excel里的内容 * @param templateVO 模板的信息 */ private void checkTemplateSync(List sheetDataSetList,CodeClassifyTemplateVO templateVO,int i){ String templateOidInExcel = ""; String templateName=""; if(!CollectionUtils.isEmpty(sheetDataSetList) && sheetDataSetList.size()>1 && !CollectionUtils.isEmpty(sheetDataSetList.get(sheetDataSetList.size()-1).getColName())){ List rowData= sheetDataSetList.get(sheetDataSetList.size()-1).getRowData(); templateName=rowData.get(i).getData().get(2); templateOidInExcel=rowData.get(i).getData().get(0); //templateOidInExcel = sheetDataSetList.get(sheetDataSetList.size()-1).getColName().get(sheetDataSetList.size()-i); } /* if(!CollectionUtils.isEmpty(sheetDataSetList) && sheetDataSetList.size()>1 && !CollectionUtils.isEmpty(sheetDataSetList.get(sheetDataSetList.size()-1).getColName())){ List rowData= sheetDataSetList.get(sheetDataSetList.size()-1).getRowData(); templateOidInExcel=rowData.get(i).getData().get(0); //templateOidInExcel = sheetDataSetList.get(sheetDataSetList.size()-1).getColName().get(sheetDataSetList.size()-i); }*/ if(StringUtils.isBlank(templateOidInExcel) || !templateOidInExcel.equalsIgnoreCase(templateVO.getOid())){ throw new VciBaseException("模板【"+templateName+"】中的数据获取的模版信息与当前模板不匹配,请确保excel文件里有【模板信息-请勿移动或删除】的工作表,且确保每次导入都是先下载的导入模板后添加的数据"); } } /*** * 批量处理申请数据 * @param orderDTO * @param templateVO * @param dataSet * @return */ private String batchImportCodes(CodeOrderDTO orderDTO,CodeClassifyTemplateVO templateVO,SheetDataSet dataSet,Map errorMap,boolean isEnumType){ List codeList=new ArrayList<>(); CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid()); //规则的主键需要去获取 CodeRuleVO ruleVO = engineService.getCodeRuleByClassifyFullInfo(classifyFullInfo); //1.判断规则中除了流水码段,是否有其他码段 engineService.checkSecValueOnOrder(ruleVO,orderDTO); List rowDataList = dataSet.getRowData(); //除去默认的属性.还有只有表单显示的字段才导入 List attrVOS = templateVO.getAttributes().stream().filter(s -> !DEFAULT_ATTR_LIST.contains(s.getId()) && VciBaseUtil.getBoolean(s.getFormDisplayFlag()) ).collect(Collectors.toList()); Map fieldIndexMap = new HashMap<>(); List titleRowData = dataSet.getColName(); Map attrNameIdMap = attrVOS.stream().collect(Collectors.toMap(s -> s.getName(), t -> t.getId().toLowerCase(Locale.ROOT),(o1, o2)->o2)); getFieldIndexMap(titleRowData,attrNameIdMap,fieldIndexMap); //需要判断是否所有的属性都在模板上了 List unExistAttrVOs = attrVOS.stream().filter(s -> !fieldIndexMap.containsValue(s.getId().toLowerCase(Locale.ROOT)) && StringUtils.isBlank(s.getComponentRule()) && StringUtils.isBlank(s.getClassifyInvokeAttr())//组合规则和分类注入确实没给用户导出去 ).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(unExistAttrVOs)){ throw new VciBaseException("【" + unExistAttrVOs.stream().map(CodeClassifyTemplateAttrVO::getName) + "】这些属性在列表中没有找到"); } List cboList = new ArrayList<>(); String fullPath = getFullPath(classifyFullInfo); excelToCbo(classifyFullInfo,fieldIndexMap,rowDataList,templateVO,cboList,fullPath,true); //都转换完了。需要批量检查 //如果出错了,我们依然执行有效的数据,无效的数据写回到excel中 //2.判断必输项。。需要全部的属性,如果是必输,但是表单里面不显示的,只能是分类注入或者组合规则 batchCheckRequiredAttrOnOrder(templateVO,cboList,errorMap); //3.判断关键属性 CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList); Set selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList(); Set keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList(); if(!CollectionUtils.isEmpty(selfRepeatRowIndexList)){ selfRepeatRowIndexList.stream().forEach(rowIndex->{ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";在当前处理的数据文件中关键属性重复" ); }); } if(!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)){ keyAttrRepeatRowIndexList.stream().forEach(rowIndex->{ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" ); }); } //分类注入 batchSwitchClassifyAttrOnOrder(attrVOS,cboList,classifyFullInfo,false); //boolean reSwitchBooleanAttrOnOrder(attrVOS,cboList); //4.校验规则 batchCheckVerifyOnOrder(attrVOS, cboList,errorMap); if(isEnumType) {//是否需要校验枚举/参照 //5.校验枚举是否正确 batchSwitchEnumAttrOnOrder(attrVOS, cboList, errorMap); //7.处理参照的情况 batchSwitchReferAttrOnOrder(attrVOS,cboList,errorMap); } //6.时间格式的验证 //6.时间的,必须统一为yyyy-MM-dd HH:mm:ss batchSwitchDateAttrOnOrder(attrVOS,cboList,errorMap); //最后弄组合规则 batchSwitchComponentAttrOnOrder(attrVOS,cboList); String uuid=VciBaseUtil.getPk(); Map rowIndexCboMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getAttributeValue((IMPORT_ROW_INDEX)), t -> t)); if(errorMap.size()>0) { createRedisDatas(uuid + "-error",templateVO, rowIndexCboMap, dataSet, fieldIndexMap, errorMap,false); } boolean isCreateUUid=false; List needSaveCboList = cboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return !errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); //相似校验 MapresembleMap=new HashMap<>(); List dataResembleVOS=new ArrayList<>(); String btmtypeid= classifyFullInfo.getTopClassifyVO().getBtmtypeid(); bathcResembleQuery(orderDTO.getCodeClassifyOid(),templateVO,needSaveCboList,resembleMap,btmtypeid,dataResembleVOS); if(resembleMap.size()>0) { isCreateUUid=true; if(!CollectionUtils.isEmpty(dataResembleVOS)) { bladeRedis.set(uuid + "-resemble-data", dataResembleVOS); createRedisDatas(uuid + "-resemble",templateVO, rowIndexCboMap, dataSet, fieldIndexMap, resembleMap, false); } } //排除错误的,剩下正确的 Map newErrorMap=new HashMap<>(); newErrorMap.putAll(resembleMap); newErrorMap.putAll(errorMap); needSaveCboList = cboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return !newErrorMap.containsKey(rowIndex); }).collect(Collectors.toList()); if((errorMap.size()>0&&needSaveCboList.size()>0)||resembleMap.size()>0){ isCreateUUid=true; } createRedisByCodeClassify(uuid + "-class",templateVO,dataSet,fieldIndexMap,false); if(newErrorMap.size()>0) { createRedisDatas(uuid + "-ok",templateVO, rowIndexCboMap, dataSet, fieldIndexMap, newErrorMap,true); }else { uuid=""; //要把以上的错误的都抛出后,再继续处理时间和组合规则 needSaveCboList = cboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return !newErrorMap.containsKey(rowIndex); }).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(needSaveCboList)) { //9.我们处理业务数据 //生成编码的内容 List dataCBOIdList=new ArrayList<>(); List dataCBOList=new ArrayList<>(); cboList.stream().forEach(clientBusinessObject -> { BaseModel baseModel=new BaseModel(); BeanUtil.convert(clientBusinessObject,baseModel); baseModel.setData(VciBaseUtil.objectToMapString(clientBusinessObject)); dataCBOList.add(baseModel); dataCBOIdList.add(baseModel.getOid()); }); try { codeList = productCodeService.productCodeAndSaveData(classifyFullInfo,templateVO,ruleVO, orderDTO.getSecDTOList(),dataCBOList); //如果是编码生成失败,则直接就失败了,其他的判断出来有错误的我们都统一返回到excel里面 engineService.batchSaveSelectChar(templateVO, dataCBOIdList); } catch (Exception e) { e.printStackTrace(); log.error("批了申请时失败"); } } } if(!isCreateUUid){ return uuid=""; } return uuid; } @Override public List gridclassifys(String redisOid) { List codeImportTemplateVOs=new ArrayList<>(); VciBaseUtil.alertNotNull(redisOid,"分类",redisOid,"分类缓存主键"); List redisServiceCacheObjects=bladeRedis.lRange(redisOid,0,-1); if(redisServiceCacheObjects!=null){ codeImportTemplateVOs= redisServiceCacheObjects; } return codeImportTemplateVOs; } /*** * 从缓存里获取到需要导入的相关数据 * @param codeClssifyOid * @param redisOid * @return */ @Override public DataGrid> gridDatas(String codeClssifyOid, String redisOid) { VciBaseUtil.alertNotNull(redisOid,"导入相似数据",redisOid,"数据缓存主键"); List codeImprotDataVOs = bladeRedis.lRange(redisOid+"-"+codeClssifyOid,0,-1); // redisService.getCacheList(redisOid+"-"+codeClssifyOid); CodeImprotDataVO codeImprotDataVO=new CodeImprotDataVO(); if(!CollectionUtils.isEmpty(codeImprotDataVOs)){ if(StringUtils.isNotBlank(codeClssifyOid)){ Map codeClassifyDatasMap = codeImprotDataVOs.stream().collect(Collectors.toMap(s -> s.getCodeClassifyOid(), t -> t,(o1, o2)->o2)); if(codeClassifyDatasMap.containsKey(codeClssifyOid)){ codeImprotDataVO= codeClassifyDatasMap.get(codeClssifyOid); }else{ codeImprotDataVO= codeImprotDataVOs.get(0); } } } DataGrid> dataGrid = new DataGrid<>(); List> dataList = new ArrayList<>(); if(codeImprotDataVO!=null){ dataList= codeImprotDataVO.getDatas(); } dataGrid.setData(dataList); if (!CollectionUtils.isEmpty(dataList)) { dataGrid.setTotal(dataList.size()); } return dataGrid; } /** * * @param oid * @param redisOid * @return */ @Override public DataGrid> gridRowResemble(String oid,String redisOid){ VciBaseUtil.alertNotNull(redisOid,"导入相似数据",redisOid,"数据缓存主键"); List codeImprotDataVOs = bladeRedis.lRange(redisOid,0,-1);; DataGrid> dataGrid = new DataGrid<>(); List> dataList = new ArrayList<>(); if(!CollectionUtils.isEmpty(codeImprotDataVOs)){ Map rowResembleDataMap = codeImprotDataVOs.stream().collect(Collectors.toMap(s -> s.getOid(), t -> t,(o1, o2)->o2)); if(rowResembleDataMap.containsKey(oid)){ DataResembleVO dataResembleVO= rowResembleDataMap.get(oid); dataList= dataResembleVO.getDataList(); } } dataGrid.setData(dataList); if (!CollectionUtils.isEmpty(dataList)) { dataGrid.setTotal(dataList.size()); } return dataGrid; } @Override public R batchImportData(List codeImprotSaveDatVOList, String classifyAttr, boolean isImprot) { List allNeedSaveCboList=new ArrayList<>(); codeImprotSaveDatVOList.stream().forEach(codeImprotSaveDatVO -> { List rowDataList = new ArrayList<>(); ListcboList=new ArrayList<>(); List colList=codeImprotSaveDatVO.getClos(); CodeOrderDTO orderDTO= codeImprotSaveDatVO.getOrderDTO(); List> dataList= codeImprotSaveDatVO.getDataList(); Map fieldIndexMap = new HashMap(); for (int i=0;i dataMap= dataList.get(i); Map data = new HashMap(); final int[] colIndex = {0}; Map finalFieldIndexMap = new HashMap<>(); dataMap.forEach((field, value)->{ if(!ROW_INDEX.equalsIgnoreCase(field) && !ERROR_MSG.equalsIgnoreCase(field)){ data.put(colIndex[0],value); finalFieldIndexMap.put(colIndex[0]++,field); } }); fieldIndexMap=finalFieldIndexMap; sheetRowData.setData(data); sheetRowData.setRowIndex(i+""); rowDataList.add(sheetRowData); } CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid()); log.info("分类:"+classifyFullInfo.getCurrentClassifyVO().getName()+"数据:"+codeImprotSaveDatVO.getDataList().size()); // CodeClassifyTemplateVO codeClassifyTemplateVO= engineService.getUsedTemplateByClassifyOid(orderDTO.getCodeClassifyOid()); CodeClassifyTemplateVO codeClassifyTemplateVO= templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid()); //规则的主键需要去获取 CodeRuleVO ruleVO = engineService.getCodeRuleByClassifyFullInfo(classifyFullInfo); //除去默认的属性.还有只有表单显示的字段才导入 List attrVOS = codeClassifyTemplateVO.getAttributes().stream().filter(s -> !DEFAULT_ATTR_LIST.contains(s.getId()) && VciBaseUtil.getBoolean(s.getFormDisplayFlag()) ).collect(Collectors.toList()); String fullPath = getFullPath(classifyFullInfo); excelToCbo(classifyFullInfo,fieldIndexMap,rowDataList, codeClassifyTemplateVO,cboList,fullPath,!isImprot); Map errorMap=new HashMap<>(); if(isImprot) { Map childOidPathMap = getChildClassifyPathMap(classifyFullInfo, fullPath); //都转换完了。需要批量检查 //找所有的分类路径,需要校验路径是否正确,是否都在当前的分类的下级 List childClassifyVOs = classifyService.listChildrenClassify(orderDTO.getCodeClassifyOid(), true, classifyAttr, true); Map pathMap = Optional.ofNullable(childClassifyVOs).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getPath().startsWith("#") ? s.getPath().substring(1) : s.getPath(), t -> t)); Map classifyVOMap = Optional.ofNullable(childClassifyVOs).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t)); classifyVOMap.put(classifyFullInfo.getCurrentClassifyVO().getOid(), classifyFullInfo.getCurrentClassifyVO()); pathMap.put("#current#", classifyFullInfo.getCurrentClassifyVO()); //我们需要判断这些分类的模板是不是一样的,只需要校验,不用获取 //检查分类的路径 checkClassifyPathInHistory(cboList, errorMap, pathMap, childOidPathMap); } //分类注入 batchSwitchClassifyAttrOnOrder(attrVOS,cboList,classifyFullInfo,isImprot); //boolean reSwitchBooleanAttrOnOrder(attrVOS,cboList); //4.校验规则 batchCheckVerifyOnOrder(attrVOS, cboList,errorMap); //5.校验枚举是否正确 batchSwitchEnumAttrOnOrder(attrVOS, cboList, errorMap); //7.处理参照的情况 batchSwitchReferAttrOnOrder(attrVOS,cboList,errorMap); //6.时间格式的验证 //6.时间的,必须统一为yyyy-MM-dd HH:mm:ss batchSwitchDateAttrOnOrder(attrVOS,cboList,errorMap); //设置默认值 batchSwitchAttrDefault(attrVOS, cboList); //最后弄组合规则 batchSwitchComponentAttrOnOrder(attrVOS,cboList); //3.判断关键属性 CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, codeClassifyTemplateVO, cboList); Set selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList(); Set keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList(); if(!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)){ keyAttrRepeatRowIndexList.stream().forEach(rowIndex->{ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" ); }); } //4.校验规则 batchCheckVerifyOnOrder(attrVOS, cboList,errorMap); //SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo(); ListneedSaveCboList = cboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return !errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); log.info("分类:"+classifyFullInfo.getCurrentClassifyVO().getName()+"数据:"+needSaveCboList.size()); if (!CollectionUtils.isEmpty(needSaveCboList)) { List dataCBOList=new ArrayList<>(); needSaveCboList.stream().forEach(clientBusinessObject -> { BaseModel baseModel=new BaseModel(); BeanUtil.convert(clientBusinessObject,baseModel); baseModel.setData(VciBaseUtil.objectToMapString(clientBusinessObject)); dataCBOList.add(baseModel); allNeedSaveCboList.add(baseModel.getOid()); }); try { //9.我们处理业务数据 if (isImprot) { productCodeService.productCodeAndSaveData(classifyFullInfo, codeClassifyTemplateVO, ruleVO, null, dataCBOList); }else { productCodeService.productCodeAndSaveData(classifyFullInfo, codeClassifyTemplateVO, ruleVO, orderDTO.getSecDTOList(), dataCBOList); } } catch (Exception e) { e.printStackTrace(); } } //如果是编码生成失败,则直接就失败了,其他的判断出来有错误的我们都统一返回到excel里面 engineService.batchSaveSelectChar(codeClassifyTemplateVO, allNeedSaveCboList); }); return R.success(isImprot?"批量历史导入成功":"批量申请成功"); } /*** *根据数据oid从缓存中移除数据 * @param redisOid redisid * @param codeClssifyOid 存储规则的oid * @param dataOids 所需删除的数据 * @return */ @Override public R deleteDatas(String redisOid,String codeClssifyOid,String dataOids) { VciBaseUtil.alertNotNull(redisOid, "数据删除", redisOid, "数据缓存主键"); VciBaseUtil.alertNotNull(codeClssifyOid, "数据删除", codeClssifyOid, "编码规则缓存主键"); VciBaseUtil.alertNotNull(dataOids, "数据删除", dataOids, "所需删除的数据主键"); try { List codeImprotDataVOs = bladeRedis.lRange(redisOid + "-" + codeClssifyOid,0,-1); List dataOidList = new ArrayList<>(); codeImprotDataVOs.stream().forEach(codeImprotDataVO -> { List> newDataList = new ArrayList<>(); List> dataList = codeImprotDataVO.getDatas(); dataList.stream().forEach(dataMap -> { String oid = dataMap.get("oid"); if (!dataOidList.contains(oid)) { newDataList.add(dataMap); } }); codeImprotDataVO.setDatas(newDataList); }); //重新缓存 bladeRedis.del(redisOid + "-" + codeClssifyOid); bladeRedis.set(redisOid + "-" + codeClssifyOid, codeImprotDataVOs); bladeRedis.expire(redisOid + "-" + codeClssifyOid, BATCHADD_REDIS_TIME); return R.success("删除缓存数据成功"); }catch (Throwable e){ return R.fail("删除缓存数据失败!"); } } /** * 集成批量申请数据 * @param orderDTO 分类的主键 * @param dataObjectVO 数据信息 * @param resultDataObjectDetailDOs 错误信息 * @return 有错误信息的excel */ @Override public void batchSyncApplyCode(CodeOrderDTO orderDTO, DataObjectVO dataObjectVO, LinkedList resultDataObjectDetailDOs) { Map errorMap=new HashMap<>(); VciBaseUtil.alertNotNull(orderDTO,"编码申请相关的数据",orderDTO.getCodeClassifyOid(),"主题库分类主键"); CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid()); //规则的主键需要去获取 CodeRuleVO ruleVO = engineService.getCodeRuleByClassifyFullInfo(classifyFullInfo); //1.判断规则中除了流水码段,是否有其他码段 //engineService.checkSecValueOnOrder(ruleVO,orderDTO); //查询分类和模板 //先找到每一行的标题,然后根据标题来获取对应的属性 List rowDataList = dataObjectVO.getRowData(); MaprowDataMap=new LinkedHashMap<>(); rowDataList.stream().forEach(rowData->{ rowDataMap.put(rowData.getRowIndex(),rowData); }); //找第一行,为了找标题 CodeClassifyTemplateVO templateVO = engineService.getUsedTemplateByClassifyOid(orderDTO.getCodeClassifyOid()); //校验模板是不是最新的 //checkTemplateSync(sheetDataSetList,templateVO); //除去默认的属性.还有只有表单显示的字段才导入 List attrVOS = templateVO.getAttributes().stream().filter(s ->!DEFAULT_SYNC_ATTR_LIST.contains(s.getId()) && VciBaseUtil.getBoolean(s.getFormDisplayFlag()) ).collect(Collectors.toList()); Map fieldIndexMap = new HashMap<>(); List titleRowData = dataObjectVO.getColName(); Map attrNameIdMap = attrVOS.stream().collect(Collectors.toMap(s -> s.getName(), t -> t.getId().toLowerCase(Locale.ROOT),(o1, o2)->o2)); getFieldIndexMap(titleRowData,attrNameIdMap,fieldIndexMap); //需要判断是否所有的属性都在模板上了 List unExistAttrVOs = attrVOS.stream().filter(s -> !fieldIndexMap.containsValue(s.getId().toLowerCase(Locale.ROOT)) && com.alibaba.cloud.commons.lang.StringUtils.isBlank(s.getComponentRule()) && com.alibaba.cloud.commons.lang.StringUtils.isBlank(s.getClassifyInvokeAttr())//组合规则和分类注入确实没给用户导出去 ).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(unExistAttrVOs)){ throw new VciBaseException("【" + unExistAttrVOs.stream().map(CodeClassifyTemplateAttrVO::getName) + "】这些属性在excel中没有找到"); } String fullPath = getFullPath(classifyFullInfo); // List codeClassifyProcessTempVOS=codeClassifyProcessTempService.listProcessTemplate(templateVO.getOid(),"code_cls_flow_use_order"); boolean isProcess=false; //注释掉此处下面所有都按照不判断流程存储状态了 /** if(!CollectionUtils.isEmpty(codeClassifyProcessTempVOS)){ isProcess=true; }***/ //List cboList = new ArrayList<>(); //Map codeOidToSystemOidMap=new HashMap<>();//存储编码数据和集成系统数据oid对照映射 //excelToCbo(classifyFullInfo,titleRowData,fieldIndexMap,rowDataList,templateVO,cboList,fullPath,isProcess,"create",errorMap,codeOidToSystemOidMap); //都转换完了。需要批量检查 //如果出错了,我们依然执行有效的数据,无效的数据写回到excel中 //2.判断必输项。。需要全部的属性,如果是必输,但是表单里面不显示的,只能是分类注入或者组合规则 } @Override public void batchSyncEditDatas(CodeClassifyVO codeClassifyVO, DataObjectVO dataObjectVO, LinkedList resultDataObjectDetailDOs) { } /** * 获取分类的全路径 * @param classifyFullInfo 分类的全部信息 * @return 全路径 */ private String getFullPath(CodeClassifyFullInfoBO classifyFullInfo){ String fullPath = ""; if(!CollectionUtils.isEmpty(classifyFullInfo.getParentClassifyVOs())){ fullPath = classifyFullInfo.getParentClassifyVOs().stream().sorted(((o1, o2) -> o1.getDataLevel().compareTo(o2.getDataLevel()))) .map(CodeClassifyVO::getOid).collect(Collectors.joining("##")); }else{ fullPath = classifyFullInfo.getCurrentClassifyVO().getOid(); } return fullPath; } /** * 检查码段的长度是否符合要求 * @param cboList 数据 * @param classifyVOMap 分类映射 * @param ruleVOMap 规则对象 * @param ruleOidMap 分类包含规则 * @param errorMap 错误的信息 * @param ruleRowIndexMap 规则包含的行号,key是规则主键,value是包含的全部行号 */ private void checkSecLengthInHistory(List cboList,Map classifyVOMap,Map ruleVOMap, Map ruleOidMap,Map errorMap,Map> ruleRowIndexMap){ cboList.stream().forEach(cbo-> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); String secLength = cbo.getAttributeValue(CODE_SEC_LENGTH_FIELD); //找分类 String classifyOid = cbo.getAttributeValue(CODE_CLASSIFY_OID_FIELD); CodeClassifyVO classifyVO = classifyVOMap.get(classifyOid); if (classifyVO != null) { //2#2#4#1这样的方式 CodeRuleVO ruleVO = ruleVOMap.getOrDefault(ruleOidMap.get(classifyVO.getOid()), null); if(ruleVO!=null){ String[] secValues = secLength.split("#"); //总长度和编码的长度 String code = cbo.getAttributeValue(CODE_FIELD); if(code.length() != Arrays.stream(secValues).mapToInt(s->VciBaseUtil.getInt(s)).sum()){ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";码段宽度与系统中的编码规则不同" ); }else if(secValues.length != ruleVO.getSecVOList().size()){ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";码段宽度与系统中的编码规则不同" ); } else { //每一个长度都不能超过码段的 boolean fined = false; for (int j = 0; j < ruleVO.getSecVOList().size(); j++) { CodeBasicSecVO secVO = ruleVO.getSecVOList().get(j); String length= secValues[j]; if(StringUtils.isNotBlank(secVO.getCodeSecLength())&&VciBaseUtil.getInt(length)>VciBaseUtil.getInt(secVO.getCodeSecLength())){ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";码段宽度与系统中的编码规则不同" ); fined = true; break; } } /**for (int i = 0; i < secValues.length; i++) { for (int j = 0; j < ruleVO.getSecVOList().size(); j++) { CodeBasicSecVO secVO = ruleVO.getSecVOList().get(j); if (VciBaseUtil.getInt(secValues[i]) > VciBaseUtil.getInt(secVO.getCodeSecLength())) { errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";码段宽度与系统中的编码规则不同" ); fined = true; break; } } if(fined){ break; } }***/ if(!fined){ //暂时不取流水的内容,因为调用produceCode的时候去处理 List rowIndexList = ruleRowIndexMap.getOrDefault(ruleVO.getOid(), new ArrayList<>()); rowIndexList.add(rowIndex); ruleRowIndexMap.put(ruleVO.getOid(),rowIndexList); } } }else{ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";分类没有设置编码规则" ); } } }); } /** * excel转换为cbo的对象 * @param classifyFullInfo 分类的全部信息 * @param codeImprotDataVO: 分类对应的数据 * @param cboList 数据的列表 * @param newCode 是否为批量申请 */ private void excelToCbo(CodeClassifyFullInfoBO classifyFullInfo,CodeImprotDataVO codeImprotDataVO,List cboList, boolean newCode){ String fullPath = getFullPath(classifyFullInfo); codeImprotDataVO.getDatas().stream().forEach(rowData -> { ClientBusinessObject cbo=new ClientBusinessObject(); DefaultAttrAssimtUtil.addDefaultAttrAssimt(cbo, classifyFullInfo.getTopClassifyVO().getBtmtypeid()); rowData.forEach((field,value)->{ try { cbo.setAttributeValueWithNoCheck(field,value); if(WebUtil.isDefaultField(field)){ WebUtil.setValueToField(field, cbo, value); } } catch (VciBaseException e) { log.error("设置属性的值错误",e); } }); try { cbo.setAttributeValue(CODE_TEMPLATE_OID_FIELD,codeImprotDataVO.getTemplateOid()); cbo.setAttributeValue(IMPORT_ROW_INDEX,rowData.get(IMPORT_ROW_INDEX)); if(newCode){ cbo.setAttributeValue(CODE_CLASSIFY_OID_FIELD,classifyFullInfo.getCurrentClassifyVO().getOid()); cbo.setAttributeValue(CODE_FULL_PATH_FILED,fullPath); //cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); /*int secret = VciBaseUtil.getInt(cbo.getAttributeValue(SECRET_FIELD)); if(secret == 0 || !secretService.checkDataSecret(secret) ){ Integer userSecret = VciBaseUtil.getCurrentUserSecret(); cbo.setAttributeValue(SECRET_FIELD,String.valueOf((userSecret==null || userSecret ==0)? UserSecretEnum.NONE.getValue():userSecret)); }*/ }else{ //此时还没有转换路径 //cbo.setAttributeValue(CODE_FULL_PATH_FILED, childOidPathMap.getOrDefault(rowData.getData().getOrDefault(CODE_CLASSIFY_OID_FIELD,""),fullPath)); cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue()); } rowData.put("oid",cbo.getOid()); }catch (Throwable e){ log.error("设置默认的属性的值错误",e); } cboList.add(cbo); }); } /** * excel转换为cbo的对象 * @param classifyFullInfo 分类的全部信息 * @param fieldIndexMap 字段的位置 * @param rowDataList excel里的行数据 * @param templateVO 模板的显示对象 * @param cboList 数据的列表 * @param fullPath 全路径 * @param newCode 是否为批量申请 */ private void excelToCbo(CodeClassifyFullInfoBO classifyFullInfo,Map fieldIndexMap,List rowDataList, CodeClassifyTemplateVO templateVO,List cboList, String fullPath,boolean newCode){ rowDataList.stream().forEach(rowData -> { ClientBusinessObject cbo=new ClientBusinessObject(); DefaultAttrAssimtUtil.addDefaultAttrAssimt(cbo, classifyFullInfo.getTopClassifyVO().getBtmtypeid()); rowData.getData().forEach((index,value)->{ String field = fieldIndexMap.get(index); if (StringUtils.isBlank(field)) { throw new VciBaseException("第" + (index + 1) + "列的标题在系统中不存在"); } try { cbo.setAttributeValueWithNoCheck(field, value); if (WebUtil.isDefaultField(field)) { WebUtil.setValueToField(field, cbo, value); } } catch (VciBaseException e) { log.error("设置属性的值错误", e); } }); try { cbo.setAttributeValue(CODE_TEMPLATE_OID_FIELD,templateVO.getOid()); cbo.setAttributeValue(IMPORT_ROW_INDEX,rowData.getRowIndex()); if(newCode){ cbo.setAttributeValue(CODE_CLASSIFY_OID_FIELD,classifyFullInfo.getCurrentClassifyVO().getOid()); cbo.setAttributeValue(CODE_FULL_PATH_FILED,fullPath); //cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); int secret = VciBaseUtil.getInt(cbo.getAttributeValue(SECRET_FIELD)); /*if(secret == 0 || !secretService.checkDataSecret(secret) ){ Integer userSecret = VciBaseUtil.getCurrentUserSecret(); cbo.setAttributeValue(SECRET_FIELD,String.valueOf((userSecret==null || userSecret ==0)? UserSecretEnum.NONE.getValue():userSecret)); }*/ }else{ //此时还没有转换路径 //cbo.setAttributeValue(CODE_FULL_PATH_FILED, childOidPathMap.getOrDefault(rowData.getData().getOrDefault(CODE_CLASSIFY_OID_FIELD,""),fullPath)); cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue()); } }catch (Throwable e){ log.error("设置默认的属性的值错误",e); } cboList.add(cbo); }); } /** * 检查校验规则没有通过的内容 * @param attrVOS 需要校验的属性 * @param dataList 数据的列表 * @param errorMap 错误的信息映射 * @return 校验不通过的行数 */ private void batchCheckVerifyOnOrder(Collection attrVOS, List dataList,Map errorMap) { Map verifyAttrVOMap = attrVOS.stream().filter(s -> StringUtils.isNotBlank(s.getVerifyRule()) && StringUtils.isBlank(s.getComponentRule()) &&StringUtils.isBlank(s.getClassifyInvokeAttr()) ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if(!CollectionUtils.isEmpty(verifyAttrVOMap)){ Map/**校验不通过的属性**/> unPassCheckMap = new HashMap<>(); verifyAttrVOMap.forEach((attrId,attrVO)->{ dataList.stream().forEach(cbo -> { String value = cbo.getAttributeValue(attrId); if(StringUtils.isNotBlank(value) && !value.matches(attrVO.getVerifyRule())){ String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); List unPassAttrs = unPassCheckMap.getOrDefault(rowIndex, new ArrayList<>()); unPassAttrs.add(attrVO.getName()); unPassCheckMap.put(rowIndex,unPassAttrs); } }); }); if(!CollectionUtils.isEmpty(unPassCheckMap)){ unPassCheckMap.forEach((rowIndex,unPassAttrs)->{ errorMap.put(rowIndex,";属性[" + unPassAttrs.stream().collect(Collectors.joining(",")) + "]内容不符合校验规则的要求"); }); } } } /** * 批量转换时间都为指定的格式 * @param attrVOS 模板属性 * @param cboList 数据的列表 * @param errorMap 错误的信息 */ private void batchSwitchDateAttrOnOrder(Collection attrVOS,List cboList,Map errorMap){ Map dateAttrVOMap =attrVOS.stream().filter(s -> StringUtils.isNotBlank(s.getCodeDateFormat()) && VciBaseUtil.getBoolean(s.getCodeDateFormat()) && StringUtils.isBlank(s.getComponentRule()) && StringUtils.isBlank(s.getClassifyInvokeAttr()) ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if(!CollectionUtils.isEmpty(dateAttrVOMap)) { dateAttrVOMap.forEach((attrId, attrVO) -> { cboList.stream().forEach(cbo -> { String value = cbo.getAttributeValue(attrId); if (value == null) { value = ""; } if (StringUtils.isNotBlank(value)) { boolean formated = false; if(StringUtils.isNotBlank(attrVO.getCodeDateFormat())){ try { Date date = VciDateUtil.str2Date(value, attrVO.getCodeDateFormat()); if(date!=null){ cbo.setAttributeValue(attrId,value); formated = true; } } catch (Exception e) { //说明不是这个格式 } } if(!formated) { try { DateConverter dateConverter = new DateConverter(); dateConverter.setAsText(value); value = VciDateUtil.date2Str(dateConverter.getValue(), VciDateUtil.DateTimeMillFormat); cbo.setAttributeValue(attrId,value); }catch (Throwable e){ //转换不了 String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";属性[" + attrVO.getName() + "]时间格式不正确" ); } } } }); }); } } /** * 系统模板中默认值设置 * @param attrVOS 模板属性 * @param dataList excel的数据内容 */ private void batchSwitchAttrDefault(Collection attrVOS,List dataList) { Map dateAttrVOMap = attrVOS.stream().filter(s -> StringUtils.isNotBlank(s.getDefaultValue())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if(!CollectionUtils.isEmpty(dateAttrVOMap)) { dateAttrVOMap.forEach((attrId, attrVO) -> { String defaultValue = attrVO.getDefaultValue(); dataList.stream().forEach(cbo -> { String dataValue= cbo.getAttributeValue(attrId); if(StringUtils.isBlank(dataValue)){ dataValue=defaultValue; } try { cbo.setAttributeValue(attrId, dataValue); }catch (Throwable e){ log.error("设置属性的错误",e); } }); }); } } /** * 转移boolean型的属性 * @param attrVOS 属性的对象 * @param dataList 数据 */ private void reSwitchBooleanAttrOnOrder(Collection attrVOS,List dataList){ Map booleanAttrMap = attrVOS.stream().filter( s -> VciFieldTypeEnum.VTBoolean.name().equalsIgnoreCase(s.getAttributeDataType()) ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(booleanAttrMap)) { booleanAttrMap.forEach((attrId, attrVO) -> { dataList.stream().forEach(cbo -> { String text = cbo.getAttributeValue(attrId); try { if (BooleanEnum.TRUE.getValue().equalsIgnoreCase(text) || "是".equalsIgnoreCase(text)) { cbo.setAttributeValue(attrId, BooleanEnum.TRUE.getValue()); } else { cbo.setAttributeValue(attrId, BooleanEnum.FASLE.getValue()); } }catch (Throwable e){ } }); }); } } /** * 处理组合规则 * @param attrVOS 模板属性 * @param dataList excel的数据内容 */ private void batchSwitchComponentAttrOnOrder(Collection attrVOS,List dataList) { Map dateAttrVOMap = attrVOS.stream().filter(s -> StringUtils.isNotBlank(s.getComponentRule())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if(!CollectionUtils.isEmpty(dateAttrVOMap)) { dateAttrVOMap.forEach((attrId, attrVO) -> { dataList.stream().forEach(cbo -> { //从excel上把属性转换为map Map thisRowDataMap = new HashMap<>(); copyValueToMapFromCbos(cbo,thisRowDataMap); //组合内容 String value = formulaService.getValueByFormula(thisRowDataMap,attrVO.getComponentRule()); if(value == null){ value = ""; } try { cbo.setAttributeValue(attrId, value); }catch (Throwable e){ log.error("设置属性的错误",e); } }); }); } } /** * 转换参照的值 * @param attrVOS 属性的显示对象 * @param dataList 数据列表 * @param errorMap 错误的信息 */ private void batchSwitchReferAttrOnOrder(Collection attrVOS,List dataList,Map errorMap){ Map referAttrVOMap = attrVOS.stream().filter( s -> (StringUtils.isNotBlank(s.getReferBtmId()) || StringUtils.isNotBlank(s.getReferConfig())) ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if(!CollectionUtils.isEmpty(referAttrVOMap)){ Map/**表格里的值**/>> linkValueMap = new HashMap<>(); referAttrVOMap.forEach((attrId,attrVO)->{ dataList.stream().forEach(cbo -> { String text = cbo.getAttributeValue(attrId); if(StringUtils.isNotBlank(text)){ UIFormReferVO referVO = getReferVO(attrVO); String valueField = getValueField(referVO); String showText = getTextField(referVO); String tableAndAttr = VciBaseUtil.getTableName(referVO.getReferType()) + "#" + valueField; Map> showTextMap = linkValueMap.getOrDefault(tableAndAttr, new HashMap<>()); List textList = showTextMap.getOrDefault(showText, new ArrayList<>()); if(!textList.contains(text)) { textList.add(text); } showTextMap.put(showText,textList); linkValueMap.put(tableAndAttr,showTextMap); } }); }); if(!CollectionUtils.isEmpty(linkValueMap)){ //需要逐个表的值字段,逐个查询 Map>> linkCboMap = new HashMap<>(); linkValueMap.forEach((tableAndAttr,showValueMap)->{ String[] split = tableAndAttr.split("#"); String table = split[0]; String valueField = split[1].toLowerCase(Locale.ROOT); Map> dataMap = new HashMap<>(); showValueMap.forEach((showText,valueList)->{ Map valueOidTextMap = new HashMap<>(); List> valueCollections = VciBaseUtil.switchListForOracleIn(valueList); String sql = "select " + valueField + "," + showText.toLowerCase(Locale.ROOT) +" from " + table + " where " + showText + " in (%s)"; valueCollections.stream().forEach(values->{ List> dataMapList = commonsMapper.queryByOnlySqlForMap(String.format(sql, VciBaseUtil.toInSql(values.toArray(new String[0])))); List cbos= ChangeMapTOClientBusinessObjects(dataMapList); if(!CollectionUtils.isEmpty(cbos)){ valueOidTextMap.putAll(cbos.stream().collect(Collectors.toMap(s->s.getAttributeValue(valueField),t->t.getAttributeValue(showText)))); } }); dataMap.put(showText,valueOidTextMap); }); linkCboMap.put(tableAndAttr,dataMap); }); referAttrVOMap.forEach((attrId,attrVO)->{ dataList.stream().forEach(cbo -> { String text = cbo.getAttributeValue(attrId); if (StringUtils.isNotBlank(text)) { UIFormReferVO referVO = getReferVO(attrVO); String valueField = getValueField(referVO); String showText = getTextField(referVO); String tableAndAttr = VciBaseUtil.getTableName(referVO.getReferType()) + "#" + valueField; if(!linkCboMap.containsKey(tableAndAttr)){ String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";参数属性[" + attrVO.getName() + "]的值在系统中不存在" ); }else{ Map> dataMap = linkCboMap.get(tableAndAttr); if(!dataMap.containsKey(showText)){ String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";参数属性[" + attrVO.getName() + "]的值在系统中不存在" ); }else{ Map data = dataMap.get(showText); final boolean[] fined = {false}; data.forEach((key,value)->{ if(value.equalsIgnoreCase(text)){ fined[0] = true; try { cbo.setAttributeValue(attrId, key); }catch (Throwable e){ } } }); if(!fined[0]){ String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";参数属性[" + attrVO.getName() + "]的值在系统中不存在" ); } } } } }); }); } } } /** * 批量检查企业编码是否存在 * @param templateVO 模板的显示对象 * @param cboList 数据的列表 * @param errorMap 错误的信息 */ private void batchCheckIdExistOnOrder(CodeClassifyTemplateVO templateVO,List cboList,Map errorMap){ List existIds = new ArrayList<>(); VciBaseUtil.switchCollectionForOracleIn(cboList).stream().forEach(cbos -> { Map conditionMap = new HashMap<>(); conditionMap.put("id", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(cbos.stream().map(s -> s.getId()).collect(Collectors.toSet()).toArray(new String[0])) + ")"); R r= btmTypeClient.getDetail(templateVO.getBtmTypeId()); BtmTypeVO btmTypeVO =r.getData(); String tableName=btmTypeVO.getTableName(); StringBuffer sb=new StringBuffer(); sb.append(" select id from "); sb.append(tableName); sb.append(" where 1=1 "); sb.append(" id in ("); sb.append(VciBaseUtil.toInSql(cbos.stream().map(s -> s.getId()).collect(Collectors.toSet()).toArray(new String[0]))); sb.append(")"); List idList= commonsMapper.selectById(sb.toString()); //业务数据如果码值回收会直接删除数据,所以这里直接判断是否存在即可 existIds.addAll(Optional.ofNullable(idList).orElseGet(() -> new ArrayList<>()).stream().map(s -> s.toLowerCase(Locale.ROOT)).collect(Collectors.toList())); }); if(!CollectionUtils.isEmpty(existIds)){ String idFieldName = templateVO.getAttributes().stream().filter(s -> VciQueryWrapperForDO.ID_FIELD.equalsIgnoreCase(s.getId())).findFirst().orElseGet(() -> new CodeClassifyTemplateAttrVO()).getName(); if(StringUtils.isBlank(idFieldName)){ idFieldName = "企业编码"; } String finalIdFieldName = idFieldName; cboList.stream().forEach(cbo->{ String id = cbo.getId(); if(StringUtils.isBlank(id)){ id = cbo.getAttributeValue("id"); } if(existIds.contains(id)){ String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); String msg = errorMap.getOrDefault(rowIndex, ""); msg+=";" + finalIdFieldName + "的值在系统中已经存在"; errorMap.put(rowIndex,msg); } }); } } /*** * 校验分类对应的模板信息 * @param titleRowData * @param sheetDataSetList * @param shetNumber * @param pathMap * @param errorMap * @return * @throws Throwable */ private LinkedList checkSamesTemplate(List titleRowData, List sheetDataSetList,int shetNumber,Map pathMap,MaperrorMap) throws Throwable { MappathOidMap =new HashMap<>(); Map templateIdRowIndex=new HashedMap(); SheetDataSet dataSet= sheetDataSetList.get(shetNumber); LinkedHashMap codeClassifyTemplateVOMap=new LinkedHashMap (); for (int i=0; i { String Path = sheetRowData.getData().get(finalI); String rowIndex=sheetRowData.getRowIndex(); if(StringUtils.isBlank(Path)){ Path= "#current#"; } CodeClassifyTemplateVO newTemplateVO=new CodeClassifyTemplateVO(); String templateOid=""; if(pathOidMap.containsKey(Path)){ templateOid= pathOidMap.get(Path) ; newTemplateVO=codeClassifyTemplateVOMap.get(templateOid); }else{ if (pathMap.containsKey(Path)) { CodeClassifyVO codeClassifyVO = pathMap.get(Path); newTemplateVO = engineService.getUsedTemplateByClassifyOid(codeClassifyVO.getOid()); if (newTemplateVO != null) { templateOid = newTemplateVO.getOid(); } else { errorMap.put(rowIndex, "第" + rowIndex + "行,分类路径未查询到相应的分类模板"); } } else { errorMap.put(rowIndex, "第" + rowIndex + "行,分类路径未查询到相应的分类"); } } pathOidMap.put(Path, templateOid); codeClassifyTemplateVOMap.put(templateOid, newTemplateVO); templateIdRowIndex.put(templateOid, templateIdRowIndex.getOrDefault(templateOid, "") + "," +rowIndex ); }); break; } } LinkedList codeClassifyTemplateVOList=new LinkedList<>(); StringBuffer sb=new StringBuffer(); codeClassifyTemplateVOMap.keySet().forEach(tempateOid->{ String templateOidInExcel=""; String tempateName=""; CodeClassifyTemplateVO t= codeClassifyTemplateVOMap.get(tempateOid); codeClassifyTemplateVOList.add(t); if(!CollectionUtils.isEmpty(sheetDataSetList) && sheetDataSetList.size()>1 && !CollectionUtils.isEmpty(sheetDataSetList.get(sheetDataSetList.size()-1).getColName())){ List rowData= sheetDataSetList.get(sheetDataSetList.size()-1).getRowData(); templateOidInExcel=rowData.get(shetNumber).getData().get(0); tempateName=rowData.get(shetNumber).getData().get(2); //templateOidInExcel = sheetDataSetList.get(sheetDataSetList.size()-1).getColName().get(sheetDataSetList.size()-i); } if(StringUtils.isBlank(templateOidInExcel) || !templateOidInExcel.equalsIgnoreCase(tempateOid)){ sb.append("模板【"+tempateName+"】中第"+templateIdRowIndex.get(tempateOid)+"行数据不属于当前模板的数据,请核对!"); } }); if(StringUtils.isNotBlank(sb.toString())){ throw new Throwable(sb.toString()); } if(codeClassifyTemplateVOList.size()>1){ String message="模板【"+dataSet.getSheetName()+"】根据分类路径判断,分类存在多个模板"; throw new Throwable(message); } if(codeClassifyTemplateVOList.size()==0){ String message="模板【"+dataSet.getSheetName()+"】根据数据分类路径判断,未匹配到对应模板"; throw new Throwable(message); } return codeClassifyTemplateVOList ; } /** * 从属性上获取参照的内容 * @param attrVO 属性的信息 * @return 参照的内容 */ private UIFormReferVO getReferVO(CodeClassifyTemplateAttrVO attrVO){ UIFormReferVO referVO = null; if(StringUtils.isNotBlank(attrVO.getReferConfig())){ referVO = JSONObject.parseObject(attrVO.getReferConfig(),UIFormReferVO.class); }else{ referVO = new UIFormReferVO(); referVO.setReferType(attrVO.getReferBtmId()); referVO.setValueField(VciQueryWrapperForDO.OID_FIELD); referVO.setTextField("name"); } return referVO; } /** * 获取参照中的值的字段 * @param referVO 参照的对象 * @return 默认为Oid,有多个的时候,获取第一个 */ private String getValueField(UIFormReferVO referVO){ String showText = referVO.getValueField(); if(StringUtils.isBlank(showText)){ return "oid"; } if(showText.contains(",")){ //防止万一有多个,看看有没有oid List strings = VciBaseUtil.str2List(showText); if(strings.contains("oid")){ showText = "oid"; }else{ showText = strings.get(0); } } return showText; } /** * 获取参照中的显示内容的字段 * @param referVO 参照的对象 * @return 默认为name,有多个的时候,获取第一个 */ private String getTextField(UIFormReferVO referVO){ String showText = referVO.getTextField(); if(StringUtils.isBlank(showText)){ return "name"; } if(showText.contains(",")){ //防止万一有多个,看看有没有name List strings = VciBaseUtil.str2List(showText); if(strings.contains("name")){ showText = "name"; }else{ showText = strings.get(0); } } return showText; } /** * 处理枚举的显示对象 * @param attrVOS 模板属性 * @param dataList excel的数据内容 * @param errorMap 错误信息的映射 */ private void batchSwitchEnumAttrOnOrder(Collection attrVOS,List dataList, Map errorMap ) { Map dateAttrVOMap = attrVOS.stream().filter( s -> (StringUtils.isNotBlank(s.getEnumString()) || StringUtils.isNotBlank(s.getEnumId())) ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(dateAttrVOMap)) { dateAttrVOMap.forEach((attrId, attrVO) -> { dataList.stream().forEach(cbo -> { String text = cbo.getAttributeValue(attrId); if(StringUtils.isNotBlank(text)){ List valueList = engineService.listComboboxItems(attrVO); boolean fined = false; for (int i = 0; i < valueList.size(); i++) { KeyValue keyValue = valueList.get(i); //if(keyValue.getValue().equalsIgnoreCase(text)){ if(keyValue.getValue().equalsIgnoreCase(text)||keyValue.getKey().equalsIgnoreCase(text)){ try { cbo.setAttributeValue(attrId, keyValue.getKey()); }catch (Throwable e){ log.error("设置属性出错"); } fined = true; break; } } if(!fined){ String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";属性[" + attrVO.getName() + "]的值不符合下拉的要求"); } } }); }); } } /** * 批量校验数据的信息 * @param templateVO 模板的显示对象 * @param cboList 数据的内容 */ private void batchCheckRequiredAttrOnOrder(CodeClassifyTemplateVO templateVO,List cboList,Map errorMap){ Map requiredAttrMap = templateVO.getAttributes().stream().filter(s -> VciBaseUtil.getBoolean(s.getRequireFlag()) && StringUtils.isBlank(s.getComponentRule()) && StringUtils.isBlank(s.getClassifyInvokeLevel())//不能是组合的和分类注入的 ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); //与MdmEngineServiceImpl里面的checkRequiredAttrOnOrder 逻辑应该相似 if(!CollectionUtils.isEmpty(requiredAttrMap)) { Set nullRowIndex = cboList.stream().filter(cbo -> requiredAttrMap.keySet().stream().anyMatch(attrId -> StringUtils.isBlank(cbo.getAttributeValue(attrId)))).map(cbo -> cbo.getAttributeValue(IMPORT_ROW_INDEX)).collect(Collectors.toSet()); if(!CollectionUtils.isEmpty(nullRowIndex)){ String checkAttr = requiredAttrMap.values().stream().map(CodeClassifyTemplateAttrVO::getName).collect(Collectors.joining(",")); nullRowIndex.stream().forEach(rowIndex->{ errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";校验规则不通过,有校验的属性为" + checkAttr); }); } } } /** * 处理分类注入 * @param attrVOS 模板属性 * @param dataList excel的数据内容 * @param classifyFullInfo 分类的全路径 */ private void batchSwitchClassifyAttrOnOrder(Collection attrVOS,List dataList, CodeClassifyFullInfoBO classifyFullInfo,boolean isImPort) { Map dateAttrVOMap = attrVOS.stream().filter( s -> StringUtils.isNotBlank(s.getClassifyInvokeAttr()) && StringUtils.isNotBlank(s.getClassifyInvokeAttr()) ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); Map classifyFullInfoMap=new HashMap<>(); classifyFullInfoMap.put(classifyFullInfo.getCurrentClassifyVO().getOid(),classifyFullInfo); if (!CollectionUtils.isEmpty(dateAttrVOMap)) { dataList.stream().forEach(cbo -> { dateAttrVOMap.forEach((attrId, attrVO) -> { //分类注入的编号或者名称, //层级包含指定层和最小层 CodeClassifyVO classifyVO = null; if(!CodeLevelTypeEnum.MIN.getValue().equalsIgnoreCase(attrVO.getClassifyInvokeLevel()) && !"min".equalsIgnoreCase(attrVO.getClassifyInvokeLevel())) { //指定了层级的 //注意,因为查询上级分类出来的层级是倒序的,即顶层节点是最大的值 if(isImPort){ if(!classifyFullInfoMap.containsKey(cbo.getAttributeValue(CODE_CLASSIFY_OID_FIELD))) { CodeClassifyFullInfoBO currentClassifyFullInfo = classifyService.getClassifyFullInfo(cbo.getAttributeValue(CODE_CLASSIFY_OID_FIELD)); classifyFullInfoMap.put(currentClassifyFullInfo.getCurrentClassifyVO().getOid(), currentClassifyFullInfo); } } CodeClassifyFullInfoBO newClassifyFullInfo= classifyFullInfoMap.get(cbo.getAttributeValue(CODE_CLASSIFY_OID_FIELD)); List classifyVOS = newClassifyFullInfo.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel()))).collect(Collectors.toList()); int level = VciBaseUtil.getInt(attrVO.getClassifyInvokeLevel()); if (classifyVOS.size()>=level && level > 0 ) { classifyVO = classifyVOS.get(level-1); } }else{ //当前的分类 classifyVO = classifyFullInfo.getCurrentClassifyVO(); } try { if (classifyVO == null) { //说明层级有误 cbo.setAttributeValue(attrId, "分类树上没有层级[" + attrVO.getClassifyInvokeLevel() + "]"); } else { Map classifyDataMap = VciBaseUtil.objectToMapString(classifyVO); String value = classifyDataMap.getOrDefault(attrVO.getClassifyInvokeAttr(), ""); cbo.setAttributeValue(attrId, value); } } catch (Throwable e) { log.error("设置属性错误", e); } }); }); } } /** * 校验关键属性 * @param classifyFullInfo 分类的全部信息 * @param templateVO 模板的内容,必须包含模板属性 * @param cboList 批量的数据 */ private CodeImportResultVO batchCheckKeyAttrOnOrder(CodeClassifyFullInfoBO classifyFullInfo, CodeClassifyTemplateVO templateVO, List cboList) { //与MdmEngineServiceImpl里的checkKeyAttrOnOrder相似 //先获取关键属性的规则,也利用继承的方式 CodeKeyAttrRepeatVO keyRuleVO = keyRuleService.getRuleByClassifyFullInfo(classifyFullInfo); //注意的是keyRuleVO可能为空,表示不使用规则控制 //获取所有的关键属性 Map ketAttrMap = templateVO.getAttributes().stream().filter(s -> VciBaseUtil.getBoolean(s.getKeyAttrFlag())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); boolean trimAll =keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnoreallspaceflag()); //全部去空的优先级大于去空 boolean trim =keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnorespaceflag()); boolean ignoreCase = keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnorecaseflag()); boolean ignoreWidth = keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnorewidthflag()); //1. 我们需要先判断excel导入的内容是否正确 CodeImportResultVO resultVO = new CodeImportResultVO(); resultVO.setKeyAttrRuleInfo(String.format(keyRuleVO ==null?"":"查询规则:去除空格--{0},忽略大小写--{1},忽略全半角--{2},忽略全部空格--{3}", new String[]{trim?"是":"否",ignoreCase?"是":"否",ignoreWidth?"是":"否",trimAll?"是":"否"})); resultVO.setSelfRepeatRowIndexList(getSelfRepeatRowIndex(ketAttrMap,cboList,keyRuleVO)); if(!CollectionUtils.isEmpty(resultVO.getSelfRepeatRowIndexList())){ //我们移除本身重复的数据 cboList = cboList.stream().filter(s->!resultVO.getSelfRepeatRowIndexList().contains(s.getAttributeValue(IMPORT_ROW_INDEX))).collect(Collectors.toList()); } //2.判断关键属性在系统里是否重复 //因为数据量很大,所以得想办法并行 //SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo(); Map> indexTODataMap=new HashMap<>(); List repeatDataMap = cboList.parallelStream().filter(cbo -> { //每行都得查询.如果其中出现了错误,我们就直接抛出异常,其余的显示 //VciBaseUtil.setCurrentUserSessionInfo(sessionInfo); Map conditionMap = new HashMap<>(); ketAttrMap.forEach((attrId, attrVO) -> { String value =cbo.getAttributeValue(attrId.toLowerCase(Locale.ROOT)); if (value == null) { value = ""; } value= value.replace(REQUIRED_CHAR,SPECIAL_CHAR); engineService.wrapperKeyAttrConditionMap(value, keyRuleVO, attrId, trim, ignoreCase, ignoreWidth, trimAll, conditionMap); }); if (!CollectionUtils.isEmpty(ketAttrMap)) { CodeTemplateAttrSqlBO sqlBO = engineService.getSqlByTemplateVO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), templateVO, conditionMap, null); boolean isKeyCheck= commonsMapper.queryCountBySql(sqlBO.getSqlCount()) > 0; if(isKeyCheck){ List> newDataList= commonsMapper.queryByOnlySqlForMap(sqlBO.getSqlUnPage()); List newCboList= ChangeMapTOClientBusinessObjects(newDataList); indexTODataMap.put(cbo.getAttributeValue(IMPORT_ROW_INDEX),newCboList); } return isKeyCheck; }else{ return false; } }).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(repeatDataMap)){ resultVO.setKeyAttrRepeatRowIndexList(repeatDataMap.stream().map(s->s.getAttributeValue(IMPORT_ROW_INDEX)).collect(Collectors.toSet())); } //resultVO.setIndexTODataMap(indexTODataMap); //resultVO.setSuccess(true); return resultVO; } /** * 检查分类的路径是否存在 * @param cboList 业务数据 * @param errorMap 错误信息 * @param pathMap 路径和分类的映射 */ private void checkClassifyPathInHistory(List cboList, Map errorMap, Map pathMap, Map childOidPathMap) { cboList.parallelStream().forEach(cbo -> { String classifyPath = cbo.getAttributeValue(CODE_CLASSIFY_OID_FIELD); //如果path为空,则表示是导入当前分类 if(StringUtils.isBlank(classifyPath)){ classifyPath = "#current#"; } if ( !pathMap.containsKey(classifyPath)) { String row_index = cbo.getAttributeValue(IMPORT_ROW_INDEX); errorMap.put(row_index,errorMap.getOrDefault(row_index,"") + ";分类路径不存在"); } else { //转一下分类的主键 try { String classifyOid = pathMap.get(classifyPath).getOid(); cbo.setAttributeValueWithNoCheck(CODE_CLASSIFY_OID_FIELD, classifyOid); cbo.setAttributeValue(CODE_FULL_PATH_FILED, childOidPathMap.getOrDefault(classifyOid,classifyPath)); } catch (VciBaseException e) { log.error("设置属性的错误", e); } } }); } /** * 检查分类以及子分类是否都有编码规则 * @param classifyVOMap 分类的显示对象映射 * @param ruleOidMap 规则的主键映射 * @param unExistRuleClassifyOidList 不存在编码规则的分类的主键 */ private void checkRuleOidInHistory( Map classifyVOMap, Map ruleOidMap, List unExistRuleClassifyOidList ){ if(!CollectionUtils.isEmpty(classifyVOMap)){ classifyVOMap.values().parallelStream().forEach(classifyVO->{ if(StringUtils.isNotBlank(classifyVO.getCoderuleoid())){ ruleOidMap.put(classifyVO.getOid(),classifyVO.getCoderuleoid()); }else{ //递归找上级 List ruleOidList = new ArrayList<>(); recursionRule(classifyVOMap,classifyVO.getParentcodeclassifyoid(),ruleOidList); if(!CollectionUtils.isEmpty(ruleOidList)){ ruleOidMap.put(classifyVO.getOid(),ruleOidList.get(0)); }else{ unExistRuleClassifyOidList.add(classifyVO.getOid()); } } }); } log.info(";;;;"); } /** * 递归找编码规则 * @param classifyVOMap 分类的显示对象映射 * @param classifyOid 分类的主键 * @param ruleOidList 规则的主键list */ private void recursionRule(Map classifyVOMap,String classifyOid,List ruleOidList){ if(classifyVOMap.containsKey(classifyOid)){ CodeClassifyVO classifyVO = classifyVOMap.get(classifyOid); if(StringUtils.isNotBlank(classifyVO.getCoderuleoid())){ ruleOidList.add(classifyVO.getCoderuleoid()); return; }else{ recursionRule(classifyVOMap,classifyVO.getParentcodeclassifyoid(),ruleOidList); } }else{ Map parentClassifyVOMap=new HashMap<>(); CodeClassifyVO codeClassifyVO= this.classifyService.getObjectByOid(classifyOid); parentClassifyVOMap.put(codeClassifyVO.getOid(),codeClassifyVO); recursionRule(parentClassifyVOMap,codeClassifyVO.getOid(),ruleOidList); } } /** * 获取子分类的路径 * @param classifyFullInfo 分类全部信息 * @param fullPath 分类的全路径 * @return 子分类的路径,key是分类的主键 */ private Map getChildClassifyPathMap(CodeClassifyFullInfoBO classifyFullInfo,String fullPath){ List childPathVOs = classifyService.listChildrenClassify(classifyFullInfo.getCurrentClassifyVO().getOid(), true, VciQueryWrapperForDO.OID_FIELD, true); Map childOidPathMap = new ConcurrentHashMap<>(); if(!CollectionUtils.isEmpty(childPathVOs)){ childPathVOs.parallelStream().forEach(childPath->{ // String thisClassifyPath = fullPath + "##" + childPath.getPath().replace("#" + classifyFullInfo.getCurrentClassifyVO().getOid() + "#","").replace("#","##"); List list=Arrays.asList(childPath.getPath().split("#")); List newPahtList= list.stream().sorted(Comparator.comparing(s -> s,Comparator.reverseOrder())).collect(Collectors.toList()); String thisClassifyPath=StringUtils.join(newPahtList,"##")+fullPath; childOidPathMap.put(childPath.getOid(),thisClassifyPath); }); } return childOidPathMap; } /** * 获取导入的内容中关键属性重复的行号 * @param ketAttrMap 关键属性的映射 * @param dataList 导入的数据 * @param keyRuleVO 关键属性控制规则 * @return 重复的行号 */ private Set getSelfRepeatRowIndex(Map ketAttrMap, List dataList,CodeKeyAttrRepeatVO keyRuleVO){ Set selfRepeatRowIndexList = new CopyOnWriteArraySet<>(); boolean trimAll =keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnoreallspaceflag()); //全部去空的优先级大于去空 boolean trim =keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnorespaceflag()); boolean ignoreCase = keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnorecaseflag()); boolean ignoreWidth = keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnorewidthflag()); //必须将属性按照顺序排序好 List attrVOList = ketAttrMap.values().stream().sorted(((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()))).collect(Collectors.toList()); Map rowIndexKeyStringMap = new HashMap<>(); dataList.parallelStream().forEach(cbo-> { String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); StringBuilder sb = new StringBuilder(); for (int i = 0; i < attrVOList.size(); i++) { CodeClassifyTemplateAttrVO attrVO = attrVOList.get(i); String attrId = attrVO.getId().toLowerCase(Locale.ROOT); String value = cbo.getAttributeValue( attrId); if (value == null) { value = ""; } if(trim){ value = value.trim(); } if(trimAll){ value = value.replace(" ",""); } if(ignoreCase){ value = value.toLowerCase(Locale.ROOT); } if(ignoreWidth){ value = VciBaseUtil.toDBC(value); } sb.append(value).append("${ks}"); } String keyString = sb.toString(); if(rowIndexKeyStringMap.containsValue(keyString) && StringUtils.isNotBlank(keyString)){ selfRepeatRowIndexList.add(rowIndex); }else { rowIndexKeyStringMap.put(rowIndex, sb.toString()); } }); //因为只是关键属性重复,所以我们不能重复的多条选一条来报错 return selfRepeatRowIndexList; } /** * excel的标题上获取字段所在的位置 * @param titleRowData 标题的内容 * @param attrNameIdMap 模板中属性名称和英文的映射 * @param fieldIndexMap 位置和英文字段的映射 */ private void getFieldIndexMap(List titleRowData,Map attrNameIdMap,Map fieldIndexMap){ for (int i = 0; i < titleRowData.size(); i++) { String title = titleRowData.get(i); String id = attrNameIdMap.getOrDefault(title.replace(KEY_ATTR_CHAR,"").replace(REQUIRED_CHAR ,""),""); if(com.alibaba.cloud.commons.lang.StringUtils.isBlank(id) && "分类路径".equalsIgnoreCase(title)){ id = CODE_CLASSIFY_OID_FIELD; } if(com.alibaba.cloud.commons.lang.StringUtils.isBlank(id) && "码段宽度".equalsIgnoreCase(title)){ id = CODE_SEC_LENGTH_FIELD; } if(com.alibaba.cloud.commons.lang.StringUtils.isBlank(id) && "企业编码".equalsIgnoreCase(title)){ id = CODE_FIELD; } if(com.alibaba.cloud.commons.lang.StringUtils.isNotBlank(id)){ fieldIndexMap.put(i,id); } } } private List ChangeMapTOClientBusinessObjects(List> oldDataMap){ List clientBusinessObjectList=new CopyOnWriteArrayList<>(); oldDataMap.parallelStream().forEach(dataMap->{ ClientBusinessObject clientBusinessObject=new ClientBusinessObject(); DefaultAttrAssimtUtil.copplyDefaultAttrAssimt(dataMap,clientBusinessObject); dataMap.forEach((key,value)->{ clientBusinessObject.setAttributeValue(key,value); }); }); return clientBusinessObjectList; } /*** * 根据不同模板组织execl数据 * @param dataSet * @param pathMap * @param errorMap */ private void createExeclClassData(SheetDataSet dataSet,Map pathMap,MaperrorMap,List codeClassifyDatas){ Map pathDatas=new HashMap<>(); List titleRowData= dataSet.getColName(); List rowDataList= dataSet.getRowData(); LinkedHashMap codeClassifyTemplateVOMap=new LinkedHashMap (); LinkedHashMap codeRuleVOVOMap=new LinkedHashMap (); for (int i=0;i { CodeImprotDataVO dataVO=new CodeImprotDataVO(); String Path = sheetRowData.getData().get(finalI); String rowIndex=sheetRowData.getRowIndex(); Map execlData= sheetRowData.getData(); CodeClassifyTemplateVO newTemplateVO=new CodeClassifyTemplateVO(); CodeRuleVO codeRuleVO=new CodeRuleVO(); if(StringUtils.isEmpty(Path)){ Path="#current#"; } if(pathMap.containsKey(Path)){ CodeClassifyVO codeClassifyVO=pathMap.get(Path); if(codeClassifyTemplateVOMap.containsKey(Path)){ newTemplateVO= codeClassifyTemplateVOMap.get(Path); codeRuleVO= codeRuleVOVOMap.get(Path); if(newTemplateVO==null||StringUtils.isBlank(newTemplateVO.getOid())){ errorMap.put(rowIndex,"第"+rowIndex+"行,分类路径未查询到相应的分类模板"); } if(codeRuleVO==null||StringUtils.isBlank(codeRuleVO.getOid())){ errorMap.put(rowIndex,"第"+rowIndex+"行,分类路径未查询到相应的分类规则"); } }else{ newTemplateVO =engineService.getUsedTemplateByClassifyOid(codeClassifyVO.getOid()); if(newTemplateVO==null||StringUtils.isBlank(newTemplateVO.getOid())){ errorMap.put(rowIndex,"第"+rowIndex+"行,分类路径未查询到相应的分类模板"); } codeRuleVO=engineService.getCodeRuleByClassifyOid(codeClassifyVO.getOid()); if(codeRuleVO==null||StringUtils.isBlank(codeRuleVO.getOid())){ errorMap.put(rowIndex,"第"+rowIndex+"行,分类路径未查询到相应的分类规则"); } } if(pathMap.containsKey(Path)){ dataVO=pathDatas.getOrDefault(Path,dataVO); } dataVO.setTemplateOid(newTemplateVO==null?"":newTemplateVO.getOid()); dataVO.setCodeClassifyTemplateVO(newTemplateVO); dataVO.setCodeClassifyVO(codeClassifyVO); dataVO.setCodeRuleVO(codeRuleVO); dataVO.setRowIndex(rowIndex); dataVO.setCodeClassifyOid(codeClassifyVO.getOid());//设置分类oid dataVO.setCodeRuleOid(codeRuleVO==null?"":codeRuleVO.getOid()); createExeclClassData(titleRowData,newTemplateVO,execlData,dataVO); pathDatas.put(Path,dataVO); codeClassifyTemplateVOMap.put(Path, newTemplateVO); codeRuleVOVOMap.put(Path,codeRuleVO); }else{ errorMap.put(rowIndex,"第"+rowIndex+"行,分类路径未查询到相应的分类"); } }); break; } } List newCodeImprotDataVO= pathDatas.values().stream().collect(Collectors.toList()); codeClassifyDatas.addAll(newCodeImprotDataVO); log.info("222"); } /*** * @param titleRowData * @param newTemplateVO * @param execlData * @param codeImprotDataVO */ private void createExeclClassData(List titleRowData, CodeClassifyTemplateVO newTemplateVO, Map execlData, CodeImprotDataVO codeImprotDataVO){ //除去默认的属性.还有只有表单显示的字段才导入 List attrVOS = newTemplateVO.getAttributes().stream().filter(s -> !DEFAULT_ATTR_LIST.contains(s.getId()) && VciBaseUtil.getBoolean(s.getFormDisplayFlag()) ).collect(Collectors.toList()); Map attrNameIdMap = attrVOS.stream().collect(Collectors.toMap(s -> s.getName(), t -> t.getId())); List fields=new ArrayList<>(); Map filedValueMap=new HashMap<>(); List colNames=new ArrayList<>(); for (int i = 0; i < titleRowData.size(); i++) { String title = titleRowData.get(i); title=title.replace(KEY_ATTR_CHAR,"").replace(REQUIRED_CHAR,""); String id = attrNameIdMap.getOrDefault(title,""); if(StringUtils.isBlank(id) && "分类路径".equalsIgnoreCase(title)){ id = CODE_CLASSIFY_OID_FIELD; } if(StringUtils.isBlank(id) && "码段宽度".equalsIgnoreCase(title)){ id = CODE_SEC_LENGTH_FIELD; } if(StringUtils.isBlank(id) && "企业编码".equalsIgnoreCase(title)){ id = CODE_FIELD; } if(StringUtils.isNotBlank(id)){ // fieldIndexMap.put(i,id);id fields.add(id); colNames.add(title); String value= StringUtils.isNotBlank(execlData.get(i))?execlData.get(i):""; filedValueMap.put(id,value); } } // filedValueMap.put(CODE_CLASSIFY_OID_FIELD,codeImprotDataVO.getCodeClassifyOid());//将当前分类oid存入字段中 filedValueMap.put("codeclassifyid",codeImprotDataVO.getCodeClassifyOid()); filedValueMap.put(IMPORT_ROW_INDEX,codeImprotDataVO.getRowIndex()); filedValueMap.put("codetemplateoid",newTemplateVO.getOid()); codeImprotDataVO.setFields(fields); codeImprotDataVO.setColNames(colNames); codeImprotDataVO.getDatas().add(filedValueMap); } /*** * 正确错误数据redis缓存 * @param uuid * @param templateVO * @param rowIndexCbo * @param dataSet * @param fieldIndexMap * @param errorMap * @param isok */ private void createRedisDatas(String uuid,CodeClassifyTemplateVO templateVO,Map rowIndexCbo, SheetDataSet dataSet, Map fieldIndexMap,Map errorMap,boolean isok){ List needsheetRowDataList =new ArrayList<>(); if(errorMap.size()>0) { //要把以上的错误的都抛出后,再继续处理时间和组合规则 needsheetRowDataList = dataSet.getRowData().stream().filter(cbo -> { String rowIndex=cbo.getRowIndex(); return isok? !errorMap.containsKey(rowIndex):errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); }else{ needsheetRowDataList= dataSet.getRowData(); } Map rowIdexDataMap = needsheetRowDataList.stream().collect(Collectors.toMap(s -> s.getRowIndex(), t -> t,(o1, o2)->o2)); Map clsfDataMap=new HashMap<>(); rowIndexCbo .forEach((rowIndex, cbo) -> { CodeImprotDataVO codeImprotDataVO = new CodeImprotDataVO(); codeImprotDataVO.setTemplateOid(templateVO.getOid()); List> dataList = new ArrayList<>(); if(rowIdexDataMap.containsKey(rowIndex)){ SheetRowData sheetRowData=rowIdexDataMap.get(rowIndex); Map dataMap = new HashMap<>(); Map data = sheetRowData.getData(); fieldIndexMap.forEach((integer, s) -> { String field = fieldIndexMap.get(integer); if (data.containsKey(integer)) { String vlues = data.get(integer); dataMap.put(field, vlues); } }); dataMap.put("oid",cbo.getOid()); dataList.add(dataMap); } if(clsfDataMap.containsKey(templateVO.getOid())){ codeImprotDataVO=clsfDataMap.get(templateVO.getOid()); dataList.addAll(codeImprotDataVO.getDatas()); } codeImprotDataVO.setColNames(dataSet.getColName()); codeImprotDataVO.setDatas(dataList); clsfDataMap.put(templateVO.getOid(),codeImprotDataVO); }); if(!CollectionUtils.isEmpty(clsfDataMap)) { Collection codeImprotDataVOS=clsfDataMap.values(); List codeImprotDataVOList=new ArrayList<>(); codeImprotDataVOList.addAll(codeImprotDataVOS); bladeRedis.set(uuid+"-"+templateVO.getOid(), codeImprotDataVOList); bladeRedis.expire(uuid+"-"+templateVO.getOid(),BATCHADD_REDIS_TIME);//redis过期时间 } } /****** * 根据编码规则缓存数据 * @param uuid * @param codeImprotDataVOs * @param errorMap * @param isok */ private void createRedisDatas(String uuid, List codeImprotDataVOs, Map errorMap, boolean isok){ codeImprotDataVOs.stream().forEach(codeImprotDataVO -> { List> dataLists=new ArrayList<>(); CodeImprotDataVO newCodeImprotDataVO=new CodeImprotDataVO(); if(errorMap.size()>0) { //要把以上的错误的都抛出后,再继续处理时间和组合规则 dataLists = codeImprotDataVO.getDatas().stream().filter(cbo -> { String rowIndex=cbo.get(IMPORT_ROW_INDEX); String msg=StringUtils.isBlank(errorMap.get(rowIndex))?"":errorMap.get(rowIndex); cbo.put("errorMsg",msg); return isok? !errorMap.containsKey(rowIndex):errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); }else{ dataLists= codeImprotDataVO.getDatas(); } BeanUtilForVCI.copyPropertiesIgnoreCase(codeImprotDataVO,newCodeImprotDataVO); newCodeImprotDataVO.setDatas(dataLists); List codeImprotDataVOList=new ArrayList<>(); codeImprotDataVOList.add(newCodeImprotDataVO); /***update 更改成以规则分组*****/ String codeRuleOid=codeImprotDataVO.getCodeRuleOid(); log.info(uuid+"-"+codeRuleOid+":条目数"+codeImprotDataVOList.size()); if(codeImprotDataVOList.size()>0) { bladeRedis.set(uuid + "-" + codeRuleOid, codeImprotDataVOList); bladeRedis.expire(uuid + "-" + codeRuleOid, BATCHADD_REDIS_TIME);//redis过期时间 } /*** String codeClassifyOid=codeImprotDataVO.getCodeClassifyOid(); redisService.setCacheList(uuid+"-"+codeClassifyOid,codeImprotDataVOList); logger.info(uuid+"-"+codeClassifyOid+":条目数"+codeImprotDataVOList.size()); redisService.expire(uuid+"-"+codeClassifyOid,BATCHADD_REDIS_TIME);//redis过期时间***/ }); } /**** * 数据相似项数据校验redis缓存 * @param codeClassifyOid * @param templateVO * @param cboList * @param resembleMap * @param btmtypeid * @param dataResembleVOS */ private void bathcResembleQuery(String codeClassifyOid, CodeClassifyTemplateVO templateVO, List cboList,MapresembleMap,String btmtypeid,List dataResembleVOS){ CodeClassifyFullInfoBO fullInfoBO = classifyService.getClassifyFullInfo(codeClassifyOid); Map conditionMap = new HashMap<>(); CodeResembleRuleVO resembleRuleVO = Optional.ofNullable(engineService.getUseResembleRule(fullInfoBO, fullInfoBO.getCurrentClassifyVO())).orElseGet(() -> new CodeResembleRuleVO()); //需要获取是否有相似查询属性 Map attrVOs = templateVO.getAttributes().stream().filter(s -> VciBaseUtil.getBoolean(s.getSameRepeatAttrFlag())).collect(Collectors.toMap(s -> s.getId(), t -> t)); if (CollectionUtils.isEmpty(attrVOs)) { return; } Map codeImprotResembleVOMap=new HashMap<>(); List codeImprotResembleVOList=new ArrayList<>(); Map rowIndePathMap=new HashMap<>(); cboList.stream().forEach(clientBusinessObject -> { CodeImprotResembleVO codeImprotResembleVO=new CodeImprotResembleVO(); final String[] path = {""}; List fieldList=new ArrayList<>(); List rowIndeList=new ArrayList<>(); String rowIndex = clientBusinessObject.getAttributeValue(IMPORT_ROW_INDEX); attrVOs.forEach((attrId, attrVO) -> { String value=""; /*if (VciQueryWrapperForDO.BASIC_FIELD_MAP.containsKey(attrId)) { value = WebUtil.getStringValueFromObject(WebUtil.getValueFromField(WebUtil.getFieldForObject(attrId, orderDTO.getClass()).getName(), orderDTO)); }else {*/ value= clientBusinessObject.getAttributeValue(attrId); // } fieldList.add(attrId); value=StringUtils.isBlank(value)?"":value; path[0] +=value+"#"; engineService.wrapperResembleConditionMap(value, resembleRuleVO, attrId, conditionMap); }); List> dataMap=new ArrayList<>(); if(codeImprotResembleVOMap.containsKey(path[0])) { codeImprotResembleVO=codeImprotResembleVOMap.get(path[0]); rowIndeList=codeImprotResembleVO.getRownIndex(); dataMap= codeImprotResembleVO.getDataList(); resembleMap.put(rowIndex, "存在相似数据"); }else{ if (!CollectionUtils.isEmpty(conditionMap)) { Map andConditionMap = new HashMap<>(); andConditionMap.put("islastr", "1"); andConditionMap.put("islastv", "1"); conditionMap.putAll(andConditionMap); PageHelper pageHelper = new PageHelper(-1); pageHelper.addDefaultDesc("id"); CodeTemplateAttrSqlBO sqlBO = engineService.getSqlByTemplateVO(btmtypeid, templateVO, conditionMap, pageHelper); List> dataMapList=commonsMapper.queryByOnlySqlForMap(sqlBO.getSqlUnPage()); List resembleCboList= ChangeMapTOClientBusinessObjects(dataMapList); if(!CollectionUtils.isEmpty(resembleCboList)) { List> finalDataMap = dataMap; resembleCboList.stream().forEach(cbo->{ Map resembDataMap=new HashMap<>(); fieldList.stream().forEach(field->{ String value=cbo.getAttributeValue(field); value=StringUtils.isBlank(value)?"":value; resembDataMap.put(field,value); }); resembDataMap.put("codetemplateoid",templateVO.getOid()); resembDataMap.put("id",StringUtils.isBlank(cbo.getAttributeValue("id"))?"":cbo.getAttributeValue("id")); resembDataMap.put("rowIndex",""); resembDataMap.put("oid",cbo.getOid()); finalDataMap.add(resembDataMap); }); resembleMap.put(rowIndex, "存在相似数据"); } } } rowIndePathMap.put(rowIndex,path[0]); rowIndeList.add(rowIndex); codeImprotResembleVO.setPath(path[0]); codeImprotResembleVO.setRownIndex(rowIndeList); codeImprotResembleVO.setConditionMap(conditionMap); codeImprotResembleVO.setFields(fieldList); codeImprotResembleVO.setDataList(dataMap); codeImprotResembleVOMap.put(path[0],codeImprotResembleVO); }); Map cboMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getAttributeValue((IMPORT_ROW_INDEX)), t -> t)); if(!CollectionUtils.isEmpty(rowIndePathMap)){ rowIndePathMap.forEach((rowIndex, path) -> { if(codeImprotResembleVOMap.containsKey(path)){ CodeImprotResembleVO codeImprotResembleVO= codeImprotResembleVOMap.get(path); List fieldList=codeImprotResembleVO.getFields(); List rownIndexList= codeImprotResembleVO.getRownIndex(); List newRownIndexList = rownIndexList.stream().filter(cbo -> { return rowIndex!=cbo; }).collect(Collectors.toList()); newRownIndexList.stream().forEach(s -> { resembleMap.put(s, "存在相似数据"); }); List>newDataList=new ArrayList<>(); DataResembleVO dataResembleVO=new DataResembleVO(); dataResembleVO.setOid(cboMap.get(rowIndex).getOid()); List needSaveCboList = cboList.stream().filter(cbo -> { String newRowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); return rownIndexList.contains(newRowIndex)&&(!newRowIndex.equalsIgnoreCase(rowIndex)); }).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(needSaveCboList)) { needSaveCboList.stream().forEach(cbo -> { String newRowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX); Map resembDataMap = new HashMap<>(); fieldList.stream().forEach(field -> { String value = cbo.getAttributeValue(field); value = StringUtils.isBlank(value) ? "" : value; resembDataMap.put(field, value); }); resembDataMap.put("codetemplateoid",templateVO.getOid()); resembDataMap.put("id",StringUtils.isBlank(cbo.getAttributeValue("id"))?"":cbo.getAttributeValue("id")); resembDataMap.put("rowIndex", newRowIndex); resembDataMap.put("oid",cbo.getOid()); newDataList.add(resembDataMap); }); } List>dataList=codeImprotResembleVO.getDataList(); newDataList.addAll(dataList); dataResembleVO.setDataList(newDataList); dataResembleVOS.add(dataResembleVO); } }); } } /*** * 存储分类对象及其列名 * @param uuid * @param templateVOList * @param dataSet * @param fieldIndexMap * @param iscContain */ private void createRedisByCodeClassify(String uuid,CodeClassifyTemplateVO templateVOList,SheetDataSet dataSet, Map fieldIndexMap,boolean iscContain){ List columnVOList = new ArrayList<>(); List outNameList = dataSet.getColName(); fieldIndexMap.forEach((integer, s) -> { ColumnVO columnVOS = new ColumnVO(); String field = fieldIndexMap.get(integer); String outName = outNameList.get(integer); columnVOS.setField(field); columnVOS.setTitle(outName); columnVOList.add(columnVOS); }); CodeImportTemplateVO codeImportTemplateVO=new CodeImportTemplateVO(); codeImportTemplateVO.setCodeClassifyTemplateVO(templateVOList); codeImportTemplateVO.setCloNamesList(columnVOList); List codeImportTemplateVOs= new ArrayList<>(); codeImportTemplateVOs.add(codeImportTemplateVO); if(codeImportTemplateVOs.size()>0) { bladeRedis.set(uuid, codeImportTemplateVOs); bladeRedis.expire(uuid, BATCHADD_REDIS_TIME);//redis过期时间 } } /** * 拷贝业务类型到map * @param cbo 业务数据 * @param map map */ public static void copyValueToMapFromCbos(ClientBusinessObject cbo,Map map){ if(cbo!=null){ copyValueToMapFromBos(cbo,map); } } /** * 拷贝业务类型到map * @param bo 业务数据 * @param map map */ public static void copyValueToMapFromBos(ClientBusinessObject bo,Map map){ if(bo!=null ){ //先把所有的字段映射找到 AttributeValue[] newAList = bo.newAttrValList; AttributeValue[] hisAList = bo.hisAttrValList; if(hisAList!=null&&hisAList.length>0){// for(int i = 0 ; i < hisAList.length;i++){ AttributeValue av = hisAList[i]; String attrName = av.attrName.toLowerCase(); map.put(attrName, av.attrVal); } } if(newAList!=null&&newAList.length>0){//NEW的优先级高些 for(int i = 0 ; i < newAList.length;i++){ AttributeValue av = newAList[i]; String attrName = av.attrName.toLowerCase(); map.put(attrName, av.attrVal); } } } } }