package com.vci.ubcs.code.service.impl; import com.alibaba.fastjson.JSONObject; import com.vci.ubcs.code.constant.MdmBtmTypeConstant; import com.vci.ubcs.code.constant.MdmEngineConstant; import com.vci.ubcs.code.enumpack.CodeLevelTypeEnum; import com.vci.ubcs.code.lifecycle.CodeAllCodeLC; import com.vci.ubcs.code.lifecycle.CodeDefaultLC; import com.vci.code.service.*; import com.vci.ubcs.code.vo.pagemodel.*; import com.vci.ubcs.code.vo.universalInter.attrmap.DataObjectVO; import com.vci.ubcs.code.vo.universalInter.attrmap.RowDatas; import com.vci.ubcs.code.vo.universalInter.result.xml.XMLResultDataObjectDetailDO; import com.vci.corba.common.VCIError; import com.vci.file.util.VciZipUtil; import com.vci.starter.poi.bo.*; import com.vci.starter.poi.util.ExcelUtil; import com.vci.starter.web.constant.QueryOptionConstant; import com.vci.starter.web.enumpck.BooleanEnum; import com.vci.starter.web.enumpck.UserSecretEnum; import com.vci.starter.web.enumpck.VciFieldTypeEnum; import com.vci.starter.web.exception.VciBaseException; import com.vci.starter.web.pagemodel.BaseResult; import com.vci.starter.web.pagemodel.DataGrid; import com.vci.starter.web.pagemodel.PageHelper; import com.vci.starter.web.pagemodel.SessionInfo; import com.vci.starter.web.toolmodel.DateConverter; import com.vci.starter.web.util.*; import com.vci.starter.web.wrapper.VciQueryWrapperForDO; import com.vci.ubcs.code.service.*; import com.vci.web.pageModel.BatchCBO; import com.vci.web.pageModel.KeyValue; import com.vci.web.pageModel.OsLifeCycleVO; import com.vci.web.pageModel.UIFormReferVO; import com.vci.web.redis.RedisService; import com.vci.web.service.OsLifeCycleServiceI; import com.vci.web.service.WebBoServiceI; import com.vci.web.service.WebSecretServiceI; import com.vci.web.service.impl.FormulaServiceImpl; import com.vci.web.util.PlatformClientUtil; import com.vci.web.util.WebUtil; import org.apache.commons.collections.map.HashedMap; import org.apache.commons.lang3.StringUtils; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO; import com.vci.ubcs.code.bo.CodeTemplateAttrSqlBO; import com.vci.ubcs.code.dto.CodeExportAttrDTO; import com.vci.ubcs.code.dto.CodeOrderDTO; import org.springblade.code.service.*; import org.springblade.code.vo.pagemodel.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import plm.bs.bom.clientobject.ClientBusinessObject; import java.io.File; import java.io.IOException; import java.text.MessageFormat; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.stream.Collectors; /** * 主数据导入导出服务 * @author weidy * @date 2022-3-6 */ @Service public class MdmIOServiceImpl implements MdmIOServiceI { @Value("${batchadd.exportattr.type:基本信息}") public String BATCHADD_EXCEPORT_ATTR_TYPE; /** * 生命周期的服务 */ @Autowired private OsLifeCycleServiceI lifeCycleService; @Autowired private PlatformClientUtil platformClientUtil; /** * 分类使用的流程模板 服务 */ @Autowired private CodeClassifyProcessTempServiceI codeClassifyProcessTempService; /** * 主题库分类的服务 */ @Autowired private CodeClassifyServiceI classifyService; @Autowired private CodeClassifyTemplateServiceI templateServiceI; /** * 主数据引擎的服务 */ @Autowired private MdmEngineServiceI engineService; /** * 规则的服务 */ @Autowired private CodeRuleServiceI ruleService; /** * 数据的服务 */ @Autowired @Lazy private WebBoServiceI boService; /** * 公式的服务 */ @Autowired private FormulaServiceImpl formulaService; /** * 缓存服务 */ @Autowired private RedisService redisService; /** * 关键属性 */ public static final String KEY_ATTR_CHAR = "☆"; /** * 字段 */ public static final String ROW_INDEX = "LAY_TABLE_INDEX"; /** * 必输 */ public static final String REQUIRED_CHAR = "*"; /** * 替换字符 */ public static final String SPECIAL_CHAR = "VCI"; /** * 强制分页的数量 */ public static final int LIMIT = 10000; /** * 日志 */ private Logger logger = LoggerFactory.getLogger(getClass()); /** * 关键属性的配置 */ @Autowired private CodeKeyAttrRepeatRuleServiceI keyRuleService; /** * 编码生成服务类 */ @Autowired private MdmProductCodeServiceI productCodeService; /** * 模板的服务 */ @Autowired private CodeClassifyTemplateServiceI templateService; /** * 密级的服务 */ @Autowired private WebSecretServiceI secretService; /** * 导出主题库的数据 * * @param exportAttrDTO 导出相关的配置,必须要有主题库分类的主键 * @return 导出的excel的文件 */ @Override public String exportCode(CodeExportAttrDTO exportAttrDTO) { VciBaseUtil.alertNotNull(exportAttrDTO,"导出的配置",exportAttrDTO.getCodeClassifyOid(),"主题库分类的主键"); CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(exportAttrDTO.getCodeClassifyOid()); //获取最新的模板 CodeClassifyTemplateVO templateVO = engineService.getUsedTemplateByClassifyOid(exportAttrDTO.getCodeClassifyOid()); //先查询数据 String btmTypeId = classifyFullInfo.getTopClassifyVO().getBtmtypeid(); Map conditionMap = exportAttrDTO.getConditionMap(); if(conditionMap == null){ conditionMap = new HashMap<>(); } if(conditionMap.containsKey(VciQueryWrapperForDO.OID_FIELD)){ conditionMap.put(VciQueryWrapperForDO.OID_FIELD,QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(conditionMap.get(VciQueryWrapperForDO.OID_FIELD)) + ")"); } PageHelper pageHelper = new PageHelper(exportAttrDTO.getLimit()==null?-1:exportAttrDTO.getLimit()); pageHelper.setPage(exportAttrDTO.getPage()==null?1:exportAttrDTO.getPage()); pageHelper.setSort(exportAttrDTO.getSort()); pageHelper.setOrder(exportAttrDTO.getOrder()); pageHelper.addDefaultDesc("createTime"); conditionMap.put("codeclsfpath","*" + exportAttrDTO.getCodeClassifyOid() + "*"); //先查询总数 int total = 0; if(exportAttrDTO.getEndPage()!=null && exportAttrDTO.getEndPage()>0 &&exportAttrDTO.getPage() !=null && exportAttrDTO.getPage() >0 &&exportAttrDTO.getEndPage()>exportAttrDTO.getPage()){ //从多少页到多少页的查询方式, for(int i = exportAttrDTO.getPage() ;i <= exportAttrDTO.getEndPage();i++){ PageHelper thisPage = new PageHelper(exportAttrDTO.getLimit()==null?-1:exportAttrDTO.getLimit()); thisPage.setPage(exportAttrDTO.getPage()==null?1:exportAttrDTO.getPage()); thisPage.setSort(exportAttrDTO.getSort()); thisPage.setOrder(exportAttrDTO.getOrder()); thisPage.addDefaultDesc("createTime"); total += boService.queryCount(btmTypeId, conditionMap); } }else{ total=boService.queryCount(btmTypeId, conditionMap); } List selectFieldList = new ArrayList<>(); if(!CollectionUtils.isEmpty(exportAttrDTO.getAttrIdIndexMap())){ selectFieldList = exportAttrDTO.getAttrIdIndexMap().values().stream().map(s->s.toLowerCase(Locale.ROOT)).collect(Collectors.toList()); }else{ selectFieldList = templateVO.getAttributes().stream().filter(s->VciBaseUtil.getBoolean(s.getFormdisplayflag()) ||VciBaseUtil.getBoolean(s.getTabledisplayflag())).map(s->s.getId().toLowerCase(Locale.ROOT)).collect(Collectors.toList()); } //参照让平台直接查询就行 List finalSelectFieldList = selectFieldList; List referAttrVOs = templateVO.getAttributes().stream().filter( s -> StringUtils.isNotBlank(s.getReferbtmid()) && (finalSelectFieldList.size() ==0 || finalSelectFieldList.contains(s.getId().toLowerCase(Locale.ROOT))) ).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(referAttrVOs)){ for (int i = 0; i < referAttrVOs.size(); i++) { selectFieldList.add(referAttrVOs.get(i).getId() + ".name"); } } List excelNameList = new CopyOnWriteArrayList<>(); String tempFolder = LocalFileUtil.getDefaultTempFolder(); if(total>LIMIT){ //分组来执行 int queryCount = (total-total%LIMIT)/LIMIT; if(total%LIMIT>0){ queryCount = queryCount + 1; } List indexList = new ArrayList<>(); for (int i = 0; i finalConditionMap = conditionMap; //并行查询看看 SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo(); indexList.parallelStream().forEach(index->{ //线程的方式,所以需要设置当前用户 VciBaseUtil.setCurrentUserSessionInfo(sessionInfo); PageHelper thisPage = new PageHelper(LIMIT); thisPage.setPage(index+1); thisPage.setSort(exportAttrDTO.getSort()); thisPage.setOrder(exportAttrDTO.getOrder()); thisPage.addDefaultDesc("createTime"); selectDataAndExportExcelName(btmTypeId, finalConditionMap,thisPage,finalSelectFieldList, classifyFullInfo,templateVO,exportAttrDTO, excelNameList,tempFolder,index); }); }else{ pageHelper.setLimit(total); pageHelper.setPage(1); selectDataAndExportExcelName(btmTypeId,conditionMap,pageHelper,finalSelectFieldList, classifyFullInfo,templateVO,exportAttrDTO, excelNameList,tempFolder,1); } if(excelNameList.size() ==0){ throw new VciBaseException("没有数据可以被导出"); } if(excelNameList.size() == 1){ return excelNameList.get(0); } //是多个,我们需要打成压缩包 String zipFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + classifyFullInfo.getCurrentClassifyVO().getId() + "_" + classifyFullInfo.getCurrentClassifyVO().getName() + "_导出_" + excelNameList.size()+".zip"; VciZipUtil zipUtil = new VciZipUtil(); File file = new File(tempFolder); zipUtil.addFileToZip(file,zipFileName); File[] files = file.listFiles(); for (int i = 0; i < files.length; i++) { LocalFileUtil.deleteTempFile(files[i],false); } LocalFileUtil.deleteTempFile(file,true); return zipFileName; } /** * 批量申请:选取选中分类下的所有模板关键属性,相似属性,必填属性,写入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 -> !MdmEngineConstant.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.setKeyattrflag(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 = templateVO.getAttributes().stream().filter(s -> !MdmEngineConstant.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 = templateVO.getAttributes().stream().filter(s -> s.getId().equalsIgnoreCase(MdmEngineConstant.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 codeClassifyOid 分类的主键 * @param isHistory 是否历史数据导入 * @return excel的文件地址 */ /*@Override public String createImportExcel(String codeClassifyOid,boolean isHistory) { CodeClassifyVO codeClassifyVO = classifyService.getObjectByOid(codeClassifyOid); if(isHistory && !templateService.checkChildHasSameTemplate(codeClassifyOid)){ throw new VciBaseException("当前选择的主题库分类的所有下级节点中存在不同的模板的情况"); } //找模板 CodeClassifyTemplateVO templateVO = engineService.getUsedTemplateByClassifyOid(codeClassifyVO.getOid()); //组合格式的不导入, //枚举的提供序列的选择 //时间全部统一为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()) && (isHistory || VciBaseUtil.getBoolean(s.getFormdisplayflag())) ).collect(Collectors.toList()); if(CollectionUtils.isEmpty(templateAttrVOS)){ throw new VciBaseException("模板没有配置任何【表单显示】为【是】的属性"); } List idAttrVOList = templateVO.getAttributes().stream().filter(s -> s.getId().equalsIgnoreCase(CODE_FIELD)).collect(Collectors.toList()); List excelDataList = new ArrayList<>(); 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); } } //增加模板的信息导入 List tempEDList = new ArrayList<>(); tempEDList.add(new WriteExcelData(0,0,templateVO.getOid())); tempEDList.add(new WriteExcelData(0,1,templateVO.getId())); tempEDList.add(new WriteExcelData(0,2,templateVO.getName())); String excelName = LocalFileUtil.getDefaultTempFolder() + File.separator + codeClassifyVO.getName() + (isHistory?"_历史数据导入模板.xls": "_导入模板.xls"); WriteExcelOption eo = new WriteExcelOption(excelDataList); eo.addSheetDataList("模板信息【请勿删除或移动】",tempEDList); ExcelUtil.writeDataToFile(excelName,eo); return excelName; }*/ /** * 批量申请编码数据 * * @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 codeImProtRusultVO; } /*** * 批量处理申请数据 * @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 -> !MdmEngineConstant.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=redisService.getUUIDEveryDay(); Map rowIndexCboMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getAttributeValue((MdmEngineConstant.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(MdmEngineConstant.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)) { redisService.setCacheList(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(MdmEngineConstant.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(MdmEngineConstant.IMPORT_ROW_INDEX); return !newErrorMap.containsKey(rowIndex); }).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(needSaveCboList)) { //9.我们处理业务数据 //生成编码的内容 codeList = productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(), needSaveCboList); //如果是编码生成失败,则直接就失败了,其他的判断出来有错误的我们都统一返回到excel里面 engineService.batchSaveSelectChar(templateVO, needSaveCboList); } } if(!isCreateUUid){ return uuid=""; } return uuid; } /*** * 存储分类对象及其列名 * @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); redisService.setCacheList(uuid,codeImportTemplateVOs); redisService.expire(uuid,6000000);//redis过期时间 logger.info(""); } 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); redisService.setCacheList(uuid+"-"+templateVO.getOid(), codeImprotDataVOList); redisService.expire(uuid+"-"+templateVO.getOid(),6000000);//redis过期时间 } } /*** * 批量处理申请数据 * @param orderDTO * @param templateVO * @param dataSet * @return */ @Override public List batchImportCode(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 -> !MdmEngineConstant.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); //要把以上的错误的都抛出后,再继续处理时间和组合规则 List needSaveCboList = cboList.stream().filter(cbo -> { String rowIndex =cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX); return !errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(needSaveCboList)) { //9.我们处理业务数据 //生成编码的内容 codeList= productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(), needSaveCboList); //如果是编码生成失败,则直接就失败了,其他的判断出来有错误的我们都统一返回到excel里面 engineService.batchSaveSelectChar(templateVO,needSaveCboList); } return codeList; } 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(); 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)){ 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 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 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); 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=redisService.getUUIDEveryDay(); List codeImportTemplateVOS=new ArrayList<>(); //按照模板去整理数据 templateDatasMap.keySet().stream().forEach(templateVOOid->{ List codeImprotDataVOS= templateDatasMap.get(templateVOOid); CodeClassifyTemplateVO templateVO= templateServiceI.getObjectHasAttrByOid(templateVOOid); //除去默认的属性.还有只有表单显示的字段才导入 List attrVOS = templateVO.getAttributes().stream().filter(s -> !MdmEngineConstant.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<>(); ListcolumnVOList =new ArrayList(); codeImprotDataVOS.stream().forEach(codeImprotDataVO -> { CodeImportTemplateVO codeImportTemplateVO=new CodeImportTemplateVO(); codeImprotDataVO.getFields().stream().forEach(field->{ ColumnVO columnVOS = new ColumnVO(); String outName=fieldNameMap.get(field); columnVOS.setField(field); columnVOS.setTitle(outName); columnVOList.add(columnVOS); }); codeImportTemplateVO.setCodeClassifyVO( codeImprotDataVO.getCodeClassifyVO()); codeImportTemplateVO.setCodeClassifyTemplateVO( codeImprotDataVO.getCodeClassifyTemplateVO()); List colNames=codeImprotDataVO.getColNames(); codeImportTemplateVO.setCloNamesList(columnVOList); codeImportTemplateVOS.add(codeImportTemplateVO); List cboList=new ArrayList<>(); excelToCbo(classifyFullInfo,codeImprotDataVO,cboList,true); allCboList.addAll(cboList); }); //都转换完了。需要批量检查 //如果出错了,我们依然执行有效的数据,无效的数据写回到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); //最后弄组合规则 batchSwitchComponentAttrOnOrder(attrVOS,allCboList); Map rowIndexCboMap = allCboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getAttributeValue((MdmEngineConstant.IMPORT_ROW_INDEX)), t -> t)); if(errorMap.size()>0) { createRedisDatas(uuid + "-error",templateVO,codeImprotDataVOS, errorMap,false); } List needSaveCboList = allCboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(MdmEngineConstant.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)) { redisService.setCacheList(uuid + "-resemble-data", dataResembleVOS); createRedisDatas(uuid + "-resemble",templateVO, codeImprotDataVOS, resembleMap, false); } } //排除错误的,剩下正确的 Map newErrorMap=new HashMap<>(); newErrorMap.putAll(resembleMap); newErrorMap.putAll(errorMap); needSaveCboList = allCboList.stream().filter(cbo -> { String rowIndex = cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX); return !newErrorMap.containsKey(rowIndex); }).collect(Collectors.toList()); createRedisDatas(uuid + "-ok",templateVO,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); redisService.setCacheList(uuid + "-class",codeImportTemplateVOS); // redisService.expire(uuid + "-class",6000000); } return codeImProtRusultVO; } /*** * 根据不同模板组织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 (); 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(); if(StringUtils.isEmpty(Path)){ Path="#current#"; } if(pathMap.containsKey(Path)){ CodeClassifyVO codeClassifyVO=pathMap.get(Path); if(codeClassifyTemplateVOMap.containsKey(Path)){ newTemplateVO= codeClassifyTemplateVOMap.get(Path); }else{ newTemplateVO =engineService.getUsedTemplateByClassifyOid(codeClassifyVO.getOid()); if(newTemplateVO==null){ errorMap.put(rowIndex,"第"+rowIndex+"行,分类路径未查询到相应的分类模板"); } } if(pathMap.containsKey(Path)){ dataVO=pathDatas.getOrDefault(Path,dataVO); } dataVO.setTemplateOid(newTemplateVO.getOid()); dataVO.setCodeClassifyTemplateVO(newTemplateVO); dataVO.setCodeClassifyVO(codeClassifyVO); dataVO.setRowIndex(rowIndex); dataVO.setCodeClassifyOid(codeClassifyVO.getOid());//设置分类oid dataVO.setCodeRuleOid(codeClassifyVO.getCoderuleoid()); createExeclClassData(titleRowData,newTemplateVO,execlData,dataVO); pathDatas.put(Path,dataVO); codeClassifyTemplateVOMap.put(Path, newTemplateVO); }else{ errorMap.put(rowIndex,"第"+rowIndex+"行,分类路径未查询到相应的分类"); } }); break; } } List newCodeImprotDataVO= pathDatas.values().stream().collect(Collectors.toList()); codeClassifyDatas.addAll(newCodeImprotDataVO); logger.info("222"); } /** * 导入历史数据 * * @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 = redisService.getUUIDEveryDay(); 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<>(); 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(MdmEngineConstant.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(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD))) { String row_index = cbo.getAttributeValue(MdmEngineConstant.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); //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.listCodeRuleByOids(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(MdmEngineConstant.IMPORT_ROW_INDEX)) && !errorMap.containsKey(cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX))).collect(Collectors.toList()); //我们需要先查询一下,内容是否已经存在 if(!CollectionUtils.isEmpty(thisCbos)){ List existIds = new ArrayList<>(); VciBaseUtil.switchCollectionForOracleIn(thisCbos).stream().forEach(cbos -> { Map conditionMap = new HashMap<>(); conditionMap.put("coderuleoid", ruleOid); conditionMap.put("id", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(cbos.stream().map(s -> s.getId()).collect(Collectors.toSet()).toArray(new String[0])) + ")"); conditionMap.put(VciQueryWrapperForDO.LC_STATUS_FIELD, QueryOptionConstant.NOTIN + "('" + CodeAllCodeLC.TASK_BACK.getValue() + "','" + CodeAllCodeLC.OBSOLETED.getValue() + "')"); existIds.addAll(Optional.ofNullable(boService.queryCBO(MdmBtmTypeConstant.CODE_ALL_CODE, conditionMap, new PageHelper(-1), Arrays.stream(new String[]{"id"}) .collect(Collectors.toList()))).orElseGet(() -> new ArrayList<>()).stream().map(s -> { String id = s.getId(); if (StringUtils.isBlank(id)) { id = s.getAttributeValue("id"); } 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(MdmEngineConstant.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((MdmEngineConstant.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(MdmEngineConstant.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)) { redisService.setCacheList(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((MdmEngineConstant.IMPORT_ROW_INDEX)), t -> t.getAttributeValue(MdmEngineConstant.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(MdmEngineConstant.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(MdmEngineConstant.IMPORT_ROW_INDEX))).map(s -> s.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX)).collect(Collectors.toList()); if (isExport||newErrorMap.size() > 0) { createRedisDatas(uuid + "-ok", templateVO, rowIndexCboMap, dataSet, fieldIndexMap, newErrorMap, true); } else { 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(MdmEngineConstant.IMPORT_ROW_INDEX)) && !errorMap.containsKey(cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX))).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(thisCbos)) { try { productCodeService.productCodeAndSaveData(classifyFullInfo, finalTemplateVO, ruleVOMap.get(ruleOid), null, thisCbos); } catch (Throwable e) { logger.error("批量产生编码的时候出错了", e); thisCbos.stream().forEach(cbo -> { String rowIndex = cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX); errorMap.put(rowIndex, errorMap.getOrDefault(rowIndex, "") + ";系统错误,存储数据的时候出错了"); }); } } }); engineService.batchSaveSelectChar(templateVO, cboList); } } 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; } 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 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(MdmEngineConstant.IMPORT_ROW_INDEX); String secLength = cbo.getAttributeValue(MdmEngineConstant.CODE_SEC_LENGTH_FIELD); //找分类 String classifyOid = cbo.getAttributeValue(MdmEngineConstant.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(MdmEngineConstant.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 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 = boService.createCBOByBtmName(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 (VCIError e) { logger.error("设置属性的值错误",e); } }); try { if(newCode){ cbo.setAttributeValue(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD,classifyFullInfo.getCurrentClassifyVO().getOid()); cbo.setAttributeValue(MdmEngineConstant.CODE_FULL_PATH_FILED,fullPath); //cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); int secret = VciBaseUtil.getInt(cbo.getAttributeValue(MdmEngineConstant.SECRET_FIELD)); if(secret == 0 || !secretService.checkDataSecret(secret) ){ Integer userSecret = VciBaseUtil.getCurrentUserSecret(); cbo.setAttributeValue(MdmEngineConstant.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()); } cbo.setAttributeValue(MdmEngineConstant.CODE_TEMPLATE_OID_FIELD,templateVO.getOid()); cbo.setAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX,rowData.getRowIndex()); }catch (Throwable e){ logger.error("设置默认的属性的值错误",e); } cboList.add(cbo); }); } /** * excel转换为cbo的对象 * @param classifyFullInfo 分类的全部信息 * @param fieldIndexMap 字段的位置 * @param rowDataList excel里的行数据 * @param templateVO 模板的显示对象 * @param cboList 数据的列表 * @param fullPath 全路径 * @param operation 操作类型 * @param errorMap 错误信息记录 */ private void excelToCbo(CodeClassifyFullInfoBO classifyFullInfo,List titleRowData,Map fieldIndexMap,List rowDataList, CodeClassifyTemplateVO templateVO,List cboList, String fullPath,boolean isProcess,String operation,Map errorMap,Map codeOidToSystemOidMap){ rowDataList.stream().forEach(rowData -> { String oid=rowData.getOid(); String rowNumber=rowData.getRowIndex(); ClientBusinessObject cbo = boService.createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()); rowData.getData().forEach((index,value)->{ String field = fieldIndexMap.get(index); if(StringUtils.isBlank(field)){ errorMap.put(rowNumber,"属性:【" +titleRowData.get(index)+ "】在系统中不存在"); } try { cbo.setAttributeValueWithNoCheck(field,value); if(WebUtil.isDefaultField(field)){ WebUtil.setValueToField(field, cbo, value); } } catch (VCIError e) { logger.error("设置属性的值错误",e); errorMap.put(rowNumber,"属性:【" +titleRowData.get(index)+ "】在系统中不存在"); } }); try { if(operation.equals("create")){ logger.info("分类对象:"+classifyFullInfo.getCurrentClassifyVO()); logger.info("codeClassoid:"+classifyFullInfo.getCurrentClassifyVO().getOid()); cbo.setAttributeValue(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD,classifyFullInfo.getCurrentClassifyVO().getOid()); cbo.setAttributeValue(MdmEngineConstant.CODE_FULL_PATH_FILED,fullPath); int secret = VciBaseUtil.getInt(cbo.getAttributeValue(MdmEngineConstant.SECRET_FIELD)); if(secret == 0 || !secretService.checkDataSecret(secret) ){ Integer userSecret = VciBaseUtil.getCurrentUserSecret(); cbo.setAttributeValue(MdmEngineConstant.SECRET_FIELD,String.valueOf((userSecret==null || userSecret ==0)? UserSecretEnum.NONE.getValue():userSecret)); } if(rowData.getStatus().equals(CodeDefaultLC.DISABLE.getValue())){//停用 cbo.setLcStatus(CodeDefaultLC.DISABLE.getValue()); }else if(rowData.getStatus().equals(CodeDefaultLC.EDITING.getValue())){//编辑 cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); }else if(rowData.getStatus().equals(CodeDefaultLC.AUDITING.getValue())) {//审批中 cbo.setLcStatus(CodeDefaultLC.AUDITING.getValue()); }else if(rowData.getStatus().equals(CodeDefaultLC.TASK_BACK.getValue())){//回收 cbo.setLcStatus(CodeDefaultLC.TASK_BACK.getValue()); }else{ cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue());//发布 } /** if(!isProcess){ cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue()); }else { if(rowData.getStatus().equals(CodeDefaultLC.DISABLE.getValue())){//停用 cbo.setLcStatus(CodeDefaultLC.DISABLE.getValue()); }else if(rowData.getStatus().equals(CodeDefaultLC.EDITING.getValue())){//编辑 cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); }else {//发布 cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue()); } }***/ cbo.setCreator(rowData.getCreator()); cbo.setLastModifier(rowData.getEditor()==null?"":rowData.getEditor()); }else if(operation.equals("update")){ //此时还没有转换路径 //cbo.setAttributeValue(CODE_FULL_PATH_FILED, childOidPathMap.getOrDefault(rowData.getData().getOrDefault(CODE_CLASSIFY_OID_FIELD,""),fullPath)); if(rowData.getStatus().equals(CodeDefaultLC.DISABLE.getValue())){//停用 cbo.setLcStatus(CodeDefaultLC.DISABLE.getValue()); }else if(rowData.getStatus().equals(CodeDefaultLC.RELEASED.getValue())){//发布 cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue()); }else if(rowData.getStatus().equals(CodeDefaultLC.EDITING.getValue())){//编辑 cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); }else if(rowData.getStatus().equals(CodeDefaultLC.AUDITING.getValue())) {//审批中 cbo.setLcStatus(CodeDefaultLC.AUDITING.getValue()); }else if(rowData.getStatus().equals(CodeDefaultLC.TASK_BACK.getValue())){//回收 cbo.setLcStatus(CodeDefaultLC.TASK_BACK.getValue()); } cbo.setLastModifier(rowData.getEditor() == null ? "" : rowData.getEditor());//修改者 }else if(operation.equals("delete")){ if(rowData.getStatus().equals(CodeDefaultLC.TASK_BACK.getValue())){//回收 cbo.setLcStatus(CodeDefaultLC.TASK_BACK.getValue()); }else{ cbo.setLcStatus(CodeDefaultLC.DISABLE.getValue());//停用 } } cbo.setAttributeValue(MdmEngineConstant.CODE_TEMPLATE_OID_FIELD,templateVO.getOid()); cbo.setAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX,rowData.getRowIndex()); }catch (Throwable e){ logger.error("设置默认的属性的值错误",e); errorMap.put(rowNumber,"设置默认的属性的值错误"+e.getMessage()); }finally { codeOidToSystemOidMap.put(cbo.getOid(),oid); } cboList.add(cbo); }); } /** * 检查分类的路径是否存在 * @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(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD); //如果path为空,则表示是导入当前分类 if(StringUtils.isBlank(classifyPath)){ classifyPath = "#current#"; } if ( !pathMap.containsKey(classifyPath)) { String row_index = cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX); errorMap.put(row_index,errorMap.getOrDefault(row_index,"") + ";分类路径不存在"); } else { //转一下分类的主键 try { String classifyOid = pathMap.get(classifyPath).getOid(); cbo.setAttributeValueWithNoCheck(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD, classifyOid); cbo.setAttributeValue(MdmEngineConstant.CODE_FULL_PATH_FILED, childOidPathMap.getOrDefault(classifyOid,classifyPath)); } catch (VCIError e) { logger.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()); } } }); } logger.info(";;;;"); } /** * 获取子分类的路径 * @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 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 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 -> !MdmEngineConstant.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 = MdmEngineConstant.CODE_CLASSIFY_OID_FIELD; } if(StringUtils.isBlank(id) && "码段宽度".equalsIgnoreCase(title)){ id = MdmEngineConstant.CODE_SEC_LENGTH_FIELD; } if(StringUtils.isBlank(id) && "企业编码".equalsIgnoreCase(title)){ id = MdmEngineConstant.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(MdmEngineConstant.IMPORT_ROW_INDEX,codeImprotDataVO.getRowIndex()); codeImprotDataVO.setFields(fields); codeImprotDataVO.setColNames(colNames); codeImprotDataVO.getDatas().add(filedValueMap); } /** * 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(StringUtils.isBlank(id) && "分类路径".equalsIgnoreCase(title)){ id = MdmEngineConstant.CODE_CLASSIFY_OID_FIELD; } if(StringUtils.isBlank(id) && "码段宽度".equalsIgnoreCase(title)){ id = MdmEngineConstant.CODE_SEC_LENGTH_FIELD; } if(StringUtils.isBlank(id) && "企业编码".equalsIgnoreCase(title)){ id = MdmEngineConstant.CODE_FIELD; } if(StringUtils.isNotBlank(id)){ fieldIndexMap.put(i,id); } } } /** * 递归找编码规则 * @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); } } /** * 错误信息返回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; } /** * 获取属性在excel中的行数 * @param fieldIndexIdMap 列号-字段映射 * @param attrId 属性的编号 * @return 列号 */ private Integer getIndexInRowData(Map fieldIndexIdMap,String attrId){ return fieldIndexIdMap.keySet().stream().filter( index -> attrId.equalsIgnoreCase(fieldIndexIdMap.get(index))).findFirst().orElseGet(()->0); } /** * 处理枚举的显示对象 * @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){ logger.error("设置属性出错"); } fined = true; break; } } if(!fined){ String rowIndex = cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX); errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";属性[" + attrVO.getName() + "]的值不符合下拉的要求"); } } }); }); } } /** * 转移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 数据列表 * @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 cbos = boService.queryByOnlySql(String.format(sql, VciBaseUtil.toInSql(values.toArray(new String[0])))); 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(MdmEngineConstant.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(MdmEngineConstant.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(MdmEngineConstant.IMPORT_ROW_INDEX); errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";参数属性[" + attrVO.getName() + "]的值在系统中不存在" ); } } } } }); }); } } } /** * 从属性上获取参照的内容 * @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 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.getClassifyinvokelevel()) ).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(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD))) { CodeClassifyFullInfoBO currentClassifyFullInfo = classifyService.getClassifyFullInfo(cbo.getAttributeValue(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD)); classifyFullInfoMap.put(currentClassifyFullInfo.getCurrentClassifyVO().getOid(), currentClassifyFullInfo); } } CodeClassifyFullInfoBO newClassifyFullInfo= classifyFullInfoMap.get(cbo.getAttributeValue(MdmEngineConstant.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) { logger.error("设置属性错误", 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<>(); WebUtil.copyValueToMapFromCbos(cbo,thisRowDataMap); //组合内容 String value = formulaService.getValueByFormula(thisRowDataMap,attrVO.getComponentrule()); if(value == null){ value = ""; } try { cbo.setAttributeValue(attrId, value); }catch (Throwable e){ logger.error("设置属性的错误",e); } }); }); } } /** * 批量转换时间都为指定的格式 * @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.getFormdisplayflag()) && 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(MdmEngineConstant.IMPORT_ROW_INDEX); errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";属性[" + attrVO.getName() + "]时间格式不正确" ); } } } }); }); } } /** * 校验是否枚举的取值范围 * @param attrVOS 模板属性 * @param dataList 数据的列表 * @return 不符合枚举取值返回的行数 */ private Set batchCheckEnumOnOrder(Collection attrVOS, List dataList) { //如果枚举可以修改,则不需要校验是否符合枚举的选项 Map enumAttrVOMap = attrVOS.stream().filter(s -> (StringUtils.isNotBlank(s.getEnumString()) || StringUtils.isNotBlank(s.getEnumid())) && !VciBaseUtil.getBoolean(s.getEnumeditflag())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if(!CollectionUtils.isEmpty(enumAttrVOMap)){ return dataList.stream().filter(cbo-> enumAttrVOMap.keySet().stream().anyMatch(attrId-> { String value = cbo.getAttributeValue(attrId); if(StringUtils.isNotBlank(value)) { CodeClassifyTemplateAttrVO attrVO = enumAttrVOMap.get(attrId); List comboboxKVs = engineService.listComboboxItems(attrVO); return !comboboxKVs.stream().anyMatch(s -> value.equalsIgnoreCase(s.getValue())); }else{ return false; } })).map(s->s.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX)).collect(Collectors.toSet()); } return new HashSet<>(); } /** * 检查校验规则没有通过的内容 * @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(MdmEngineConstant.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(",")) + "]内容不符合校验规则的要求"); }); } } } 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(MdmEngineConstant.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 resembleCboList=boService.queryByOnlySql(sqlBO.getSqlUnPage()); 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("id",StringUtils.isBlank(cbo.getAttributeValue("id"))?"":cbo.getAttributeValue("id")); resembDataMap.put("rowIndex",""); 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((MdmEngineConstant.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(MdmEngineConstant.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(MdmEngineConstant.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("id",StringUtils.isBlank(cbo.getAttributeValue("id"))?"":cbo.getAttributeValue("id")); resembDataMap.put("rowIndex", newRowIndex); newDataList.add(resembDataMap); }); } List>dataList=codeImprotResembleVO.getDataList(); newDataList.addAll(dataList); dataResembleVO.setDataList(newDataList); dataResembleVOS.add(dataResembleVO); } }); } } /** * 校验关键属性 * @param classifyFullInfo 分类的全部信息 * @param templateVO 模板的内容,必须包含模板属性 * @param cboList 批量的数据 */ private CodeImportResultVO batchCheckKeyAttrOnOrder(CodeClassifyFullInfoBO classifyFullInfo, CodeClassifyTemplateVO templateVO, List cboList) { //与MdmEngineServiceImpl里的checkKeyAttrOnOrder相似 //先获取关键属性的规则,也利用继承的方式 CodeKeyAttrRepeatRuleVO 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(MdmEngineConstant.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= boService.queryCountBySql(sqlBO.getSqlCount(), new HashMap<>()) > 0; if(isKeyCheck){ List newCboList= boService.queryByOnlySql(sqlBO.getSqlUnPage()); indexTODataMap.put(cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX),newCboList); } return isKeyCheck; }else{ return false; } }).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(repeatDataMap)){ resultVO.setKeyAttrRepeatRowIndexList(repeatDataMap.stream().map(s->s.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX)).collect(Collectors.toSet())); } resultVO.setIndexTODataMap(indexTODataMap); resultVO.setSuccess(true); return resultVO; } /** * 获取导入的内容中关键属性重复的行号 * @param ketAttrMap 关键属性的映射 * @param dataList 导入的数据 * @param keyRuleVO 关键属性控制规则 * @return 重复的行号 */ private Set getSelfRepeatRowIndex(Map ketAttrMap, List dataList,CodeKeyAttrRepeatRuleVO 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(MdmEngineConstant.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; } /** * 导出的时候封装必输和关键属性 * @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; } /** * 查询数据并导出到excel * @param btmTypeId 业务类型 * @param conditionMap 查询条件 * @param pageHelper 分页 * @param selectFieldList 查询的字段 * @param classifyFullInfo 分类的全部信息 * @param templateVO 模板的信息 * @param exportAttrDTO 导出的属性 * @param excelNameList excel的文件名称 * @param tempFolder 临时文件夹 * @param excelIndex excel的顺序 */ private void selectDataAndExportExcelName(String btmTypeId, Map conditionMap, PageHelper pageHelper, List selectFieldList, CodeClassifyFullInfoBO classifyFullInfo, CodeClassifyTemplateVO templateVO, CodeExportAttrDTO exportAttrDTO, List excelNameList, String tempFolder, Integer excelIndex) { DataGrid> dataGrid = engineService.queryGrid(btmTypeId, templateVO, conditionMap, pageHelper); if(dataGrid == null || CollectionUtils.isEmpty(dataGrid.getData())){ return; } //转换数据 List> dataMap = dataGrid.getData(); //封装查询出来的数据 engineService.wrapperData(dataMap, templateVO, selectFieldList,false); //modify by weidy@2022-09-27 //因为在列表和表单的显示的时候,我们的开关类型页面会处理,但是在导出的时候,我们需要将true和false都替换成中文 engineService.wrapperBoolean(dataMap,templateVO); Map attrVOMap = templateVO.getAttributes().stream().filter(s->selectFieldList.contains(s.getId().toLowerCase(Locale.ROOT))).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); Map attrIdIndexMap = exportAttrDTO.getAttrIdIndexMap(); if (CollectionUtils.isEmpty(attrIdIndexMap)) { attrIdIndexMap = templateVO.getAttributes().stream().filter(s->selectFieldList.contains(s.getId().toLowerCase(Locale.ROOT))).collect(Collectors.toMap(s -> s.getOrdernum(), t -> t.getId())); } List indexList = attrIdIndexMap.keySet().stream().sorted().collect(Collectors.toList()); String excelName = tempFolder + File.separator + classifyFullInfo.getCurrentClassifyVO().getId() + "_" + classifyFullInfo.getCurrentClassifyVO().getName() + "_导出_" + excelIndex + ".xls"; try { new File(excelName).createNewFile(); } catch (Throwable e) { throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{excelName}, e); } excelNameList.add(excelName); List excelDataList = new ArrayList<>(); Workbook workbook = new HSSFWorkbook(); for (int i = 0; i < indexList.size(); i++) { String attrId = attrIdIndexMap.get(indexList.get(i)).toLowerCase(Locale.ROOT); if (attrVOMap.containsKey(attrId)) { CodeClassifyTemplateAttrVO attrVO = attrVOMap.get(attrId); Object text = attrVO.getName(); text = exportKeyAndRequired(workbook,attrVO,text); WriteExcelData excelData = new WriteExcelData(0, i, text); if(text instanceof RichTextString){ excelData.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex())); } excelDataList.add(excelData); } } final Integer[] rowIndex = {0}; Map finalAttrIdIndexMap = attrIdIndexMap; dataMap.stream().forEach(data -> { rowIndex[0]++; for (int i = 0; i < indexList.size(); i++) { Integer index = indexList.get(i); String attrId = finalAttrIdIndexMap.get(index).toLowerCase(Locale.ROOT); if (attrVOMap.containsKey(attrId)) { CodeClassifyTemplateAttrVO attrVO = attrVOMap.get(attrId); if (StringUtils.isNotBlank(attrVO.getEnumid()) || StringUtils.isNotBlank(attrVO.getEnumString())) { attrId = attrId + "Text"; } if (StringUtils.isNotBlank(attrVO.getReferbtmid()) || StringUtils.isNotBlank(attrVO.getReferConfig())) { attrId = attrId + "name"; } if(VciQueryWrapperForDO.LC_STATUS_FIELD.equalsIgnoreCase(attrId)){ attrId = VciQueryWrapperForDO.LC_STATUS_FIELD_TEXT.toLowerCase(Locale.ROOT); } excelDataList.add(new WriteExcelData(rowIndex[0], i, data.getOrDefault(attrId, ""))); } } }); WriteExcelOption excelOption = new WriteExcelOption(excelDataList); ExcelUtil.writeDataToFile(excelName, excelOption); } /** * 批量校验数据的信息 * @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.getClassifyinvokeattr())//不能是组合的和分类注入的 ).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(MdmEngineConstant.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 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])) + ")"); //业务数据如果码值回收会直接删除数据,所以这里直接判断是否存在即可 existIds.addAll(Optional.ofNullable(boService.queryCBO(templateVO.getBtmTypeId(), conditionMap, new PageHelper(-1), Arrays.stream(new String[]{"id"}) .collect(Collectors.toList()))).orElseGet(() -> new ArrayList<>()).stream().map(s -> s.getAttributeValue("id")).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(MdmEngineConstant.IMPORT_ROW_INDEX); String msg = errorMap.getOrDefault(rowIndex, ""); msg+=";" + finalIdFieldName + "的值在系统中已经存在"; errorMap.put(rowIndex,msg); } }); } } /** * 从map里获取值 * @param dataMap 值的映射 * @param attrId 属性的编号 * @return 值 */ private String getValueFormMap(Map dataMap,String attrId){ attrId = attrId.toLowerCase(Locale.ROOT); return dataMap.getOrDefault(attrId,""); } /** * 设置值到map中 * @param dataMap 值的映射内容 * @param attrId 属性的编号 * @param value 属性的值 */ private void setValueToMap(Map dataMap,String attrId,String value){ attrId = attrId.toLowerCase(Locale.ROOT); dataMap.put(attrId,value); } /** * 集成批量申请数据 * @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 ->!MdmEngineConstant.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)) && StringUtils.isBlank(s.getComponentrule()) && StringUtils.isBlank(s.getClassifyinvokeattr())//组合规则和分类注入确实没给用户导出去 ).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(unExistAttrVOs)){ throw new VciBaseException("【" + unExistAttrVOs.stream().map(CodeClassifyTemplateAttrVO::getName) + "】这些属性在excel中没有找到"); } List cboList = new ArrayList<>(); String fullPath = getFullPath(classifyFullInfo); // List codeClassifyProcessTempVOS=codeClassifyProcessTempService.listProcessTemplate(templateVO.getOid(),"code_cls_flow_use_order"); boolean isProcess=false; //注释掉此处下面所有都按照不判断流程存储状态了 /** if(!CollectionUtils.isEmpty(codeClassifyProcessTempVOS)){ isProcess=true; }***/ Map codeOidToSystemOidMap=new HashMap<>();//存储编码数据和集成系统数据oid对照映射 excelToCbo(classifyFullInfo,titleRowData,fieldIndexMap,rowDataList,templateVO,cboList,fullPath,isProcess,"create",errorMap,codeOidToSystemOidMap); //都转换完了。需要批量检查 //如果出错了,我们依然执行有效的数据,无效的数据写回到excel中 //2.判断必输项。。需要全部的属性,如果是必输,但是表单里面不显示的,只能是分类注入或者组合规则 batchCheckRequiredAttrOnOrder(templateVO,cboList,errorMap); /** * 关键熟悉错误提示 */ Map errorKeyMap=new HashMap<>(); //3.判断关键属性 CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList); Set selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList(); Set keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList(); if(!CollectionUtils.isEmpty(selfRepeatRowIndexList)){ selfRepeatRowIndexList.stream().forEach(rowIndex->{ /* //传入数据之间关键属性的校验 RowDatas rowData= rowDataMap.get(rowIndex); XMLResultDataObjectDetailDO resultDataObjectDetailDO=new XMLResultDataObjectDetailDO(); resultDataObjectDetailDO.setCode(""); resultDataObjectDetailDO.setId(rowData.getOid()); resultDataObjectDetailDO.setErrorid("1"); resultDataObjectDetailDO.setMsg(errorMap.getOrDefault(rowIndex,"") + ";关键属性重复"); resultDataObjectDetailDOs.add(resultDataObjectDetailDO); */ errorKeyMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";传入的数据中关键属性重复"); }); } /**** * 关键属性与系统中重复的判断 */ if(!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)){ keyAttrRepeatRowIndexList.stream().forEach(rowIndex->{ //传入数据之间关键属性的校验 /* RowDatas rowData= rowDataMap.get(rowIndex); XMLResultDataObjectDetailDO resultDataObjectDetailDO=new XMLResultDataObjectDetailDO(); resultDataObjectDetailDO.setCode(""); resultDataObjectDetailDO.setId(rowData.getOid()); resultDataObjectDetailDO.setErrorid("1"); resultDataObjectDetailDO.setMsg(errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" ); resultDataObjectDetailDOs.add(resultDataObjectDetailDO); */ errorKeyMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" ); }); } //分类注入 batchSwitchClassifyAttrOnOrder(attrVOS,cboList,classifyFullInfo,false); //boolean reSwitchBooleanAttrOnOrder(attrVOS,cboList); // cboList.stream().forEach(cbo->{ //4.校验规则 batchCheckVerifyOnOrder(attrVOS, cboList,errorMap); //5.校验枚举是否正确 batchSwitchEnumAttrOnOrder(attrVOS,cboList,errorMap); //6.时间格式的验证 //6.时间的,必须统一为yyyy-MM-dd HH:mm:ss batchSwitchDateAttrOnOrder(attrVOS,cboList,errorMap); //7.处理参照的情况 batchSwitchReferAttrOnOrder(attrVOS,cboList,errorMap); //校验属性是否正确错误信息 if(errorMap.size()>0){ String[] newMsg = {""}; cboList.stream().forEach(cbo -> { String rowIndex =cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX); if(errorMap.containsKey(rowIndex)){ String oid=cbo.getOid(); String sourceOid=oid; if(codeOidToSystemOidMap.containsKey(oid)){ sourceOid=codeOidToSystemOidMap.get(oid); } String code=""; String errorid="103"; String mes=errorMap.get(rowIndex); XMLResultDataObjectDetailDO resultDataObjectDetailDO=new XMLResultDataObjectDetailDO(); resultDataObjectDetailDO.setCode(code); resultDataObjectDetailDO.setId(sourceOid); resultDataObjectDetailDO.setErrorid(errorid); resultDataObjectDetailDO.setMsg(mes); resultDataObjectDetailDOs.add(resultDataObjectDetailDO); } }); } Map newKeyMap=new HashedMap(); if(errorKeyMap.size()>0 ) { errorKeyMap.keySet().forEach(key->{ if(!errorMap.containsKey(key)){ newKeyMap.put(key,errorKeyMap.get(key)); } }); if(newKeyMap.size()>0) { Set editBoList = new HashSet<>(); Map> indexTodataMap = keyResultVO.getIndexTODataMap(); cboList.stream().forEach(cbo -> { String rowIndex = cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX); if (indexTodataMap.containsKey(rowIndex)) { String oid = cbo.getOid(); String sourceOid = oid; String code = ""; String errorid = "201"; if(codeOidToSystemOidMap.containsKey(oid)){ sourceOid=codeOidToSystemOidMap.get(oid); } List newCboList = indexTodataMap.get(rowIndex); if (!CollectionUtils.isEmpty(newCboList)) { ClientBusinessObject newCbo= newCboList.get(0); String lcstatus =newCbo.getAttributeValue("lcstatus"); String newOid =newCbo.getAttributeValue("oid"); String ts =newCbo.getAttributeValue("ts"); code=newCbo.getAttributeValue("id"); String lastmodifier=newCbo.getAttributeValue("lastmodifier"); if (!lcstatus.equals(CodeDefaultLC.RELEASED.getValue())) { newCbo.setBusinessObject(cbo.getBusinessObject()); newCbo.setOid(newOid); newCbo.setLastModifier(lastmodifier); newCbo.setId(code); newCbo.setTs(ts); cbo.setLastModifier(cbo.getLastModifier()); editBoList.add(newCbo); } String mes = errorKeyMap.get(rowIndex); XMLResultDataObjectDetailDO resultDataObjectDetailDO = new XMLResultDataObjectDetailDO(); resultDataObjectDetailDO.setCode(code); resultDataObjectDetailDO.setId(sourceOid); resultDataObjectDetailDO.setErrorid(errorid); resultDataObjectDetailDO.setMsg(mes); resultDataObjectDetailDOs.add(resultDataObjectDetailDO); } } }); //关键熟悉更改 if (!CollectionUtils.isEmpty(editBoList)) { BatchCBO batchCbos = new BatchCBO(); batchCbos.setUpdateCbos(editBoList); this.boService.persistenceBatch(batchCbos);//更改数据 } errorMap.putAll(errorKeyMap); } } // }); //最后弄组合规则 batchSwitchComponentAttrOnOrder(attrVOS,cboList); //要把以上的错误的都抛出后,再继续处理时间和组合规则 List needSaveCboList = cboList.stream().filter(cbo -> { String rowIndex =cbo.getAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX); return !errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); List needRowIndexList = new ArrayList<>(); if(!CollectionUtils.isEmpty(needSaveCboList)) { //9.我们处理业务数据 //生成编码的内容 try { productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(), needSaveCboList); //如果是编码生成失败,则直接就失败了,其他的判断出来有错误的我们都统一返回到excel里面 engineService.batchSaveSelectChar(templateVO, needSaveCboList); // if(!isProcess){ needSaveCboList.stream().forEach(needSaveCbo->{ XMLResultDataObjectDetailDO resultDataObjectDetailDO=new XMLResultDataObjectDetailDO(); resultDataObjectDetailDO.setCode(needSaveCbo.getId()); String oid=needSaveCbo.getOid(); String sourceOid=oid; if(codeOidToSystemOidMap.containsKey(oid)){ sourceOid=codeOidToSystemOidMap.get(oid); } resultDataObjectDetailDO.setId(sourceOid); resultDataObjectDetailDO.setErrorid("0"); resultDataObjectDetailDO.setMsg("申请编码成功"); resultDataObjectDetailDOs.add(resultDataObjectDetailDO); }); /* }else{ needSaveCboList.stream().forEach(needSaveCbo->{ XMLResultDataObjectDetailDO resultDataObjectDetailDO=new XMLResultDataObjectDetailDO(); // resultDataObjectDetailDO.setCode(needSaveCbo.getId());//不用返回编码 String oid=needSaveCbo.getOid(); String sourceOid=oid; if(codeOidToSystemOidMap.containsKey(oid)){ sourceOid=codeOidToSystemOidMap.get(oid); } resultDataObjectDetailDO.setId(sourceOid); resultDataObjectDetailDO.setErrorid("204"); resultDataObjectDetailDO.setMsg("申请编码成功,等待编码系统发布!"); resultDataObjectDetailDOs.add(resultDataObjectDetailDO); }); }*/ }catch (Throwable e){ e.printStackTrace(); needSaveCboList.stream().forEach(needSaveCbo->{ XMLResultDataObjectDetailDO resultDataObjectDetailDO=new XMLResultDataObjectDetailDO(); resultDataObjectDetailDO.setCode(""); String oid=needSaveCbo.getOid(); String sourceOid=oid; if(codeOidToSystemOidMap.containsKey(oid)){ sourceOid=codeOidToSystemOidMap.get(oid); } resultDataObjectDetailDO.setId(sourceOid); resultDataObjectDetailDO.setErrorid("1"); resultDataObjectDetailDO.setMsg("保存出现问题:"+e.getMessage()); resultDataObjectDetailDOs.add(resultDataObjectDetailDO); }); } } } /*** * 集成批量同步更新接口 * @param codeClassifyVO; * @param dataObjectVO 数据信息 * @param resultDataObjectDetailDOs 错误信息 */ @Override public void batchSyncEditDatas(CodeClassifyVO codeClassifyVO,DataObjectVO dataObjectVO, LinkedList resultDataObjectDetailDOs) { String errorid=""; String msg=""; //查询分类和模板 //先找到每一行的标题,然后根据标题来获取对应的属性 List rowDataList = dataObjectVO.getRowData(); Map rowDataMap = new LinkedHashMap<>(); Map codeDataMap = new LinkedHashMap<>(); rowDataList.stream().forEach(rowData -> { rowDataMap.put(rowData.getRowIndex(), rowData); codeDataMap.put(rowData.getCode(), rowData); }); //找第一行,为了找标题 CodeClassifyTemplateVO templateVO = engineService.getUsedTemplateByClassifyOid(codeClassifyVO.getOid()); // 应该都是一个分类下的业务数据,找第一条的就行 CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(codeClassifyVO.getOid()); //校验模板是不是最新的 //checkTemplateSync(sheetDataSetList,templateVO); //除去默认的属性.还有只有表单显示的字段才导入 List attrVOS = templateVO.getAttributes().stream().filter(s -> !MdmEngineConstant.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); Map cboOidMap = new HashMap<>(); cboOidMap.put("id", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(codeDataMap.keySet().toArray(new String[0])) + ")"); List cboList = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), cboOidMap); Map codeSystemObjectMap = cboList.stream().filter(systeDataObject -> systeDataObject != null && StringUtils.isNotBlank(systeDataObject.getId())).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getId(), t -> t)); Map errorMap = new HashMap<>(); List codeOrderDTOList = new ArrayList<>(); this.getCodeOrderDTOs(codeClassifyVO, templateVO, codeDataMap, codeSystemObjectMap, codeOrderDTOList, errorMap); // List codeClassifyProcessTempVOS=codeClassifyProcessTempService.listProcessTemplate(templateVO.getOid(),"code_cls_flow_use_order"); boolean isProcess=false; /** if(!CollectionUtils.isEmpty(codeClassifyProcessTempVOS)){ isProcess=true; }**/ Map orderDTOMap = codeOrderDTOList.stream().filter(orderDTO -> orderDTO != null && StringUtils.isNotBlank(orderDTO.getId())).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getId(), t -> t)); List updateList = new ArrayList<>(); List deleteList = new ArrayList<>(); BatchCBO batchCBO = new BatchCBO(); CodeClassifyTemplateVO firstTemplateVO = templateService.getObjectHasAttrByOid(orderDTOMap.values().stream().findFirst().get().getTemplateOid()); Map cboMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getId(), t -> t)); // boolean finalIsProcess = isProcess; orderDTOMap.keySet().stream().forEach(code -> { CodeOrderDTO orderDTO = orderDTOMap.get(code); ClientBusinessObject cbo = cboMap.get(code); String dataStatus=cbo.getLcStatus(); RowDatas rowData=codeDataMap.get(code); String status=rowData.getStatus(); String operation=rowData.getOperation(); if (!cbo.getTs().contains(VciDateUtil.date2Str(orderDTO.getTs(), VciDateUtil.DateTimeFormat))) { // throw new VciBaseException("数据不是最新的,可能他人已经修改,请刷新后再试"); errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"")+";数据不是最新的,可能他人已经修改,请刷新后再试"); } /* if (!CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(cbo.getLcStatus()) && !orderDTO.isEditInProcess()) { throw new VciBaseException("数据不是{0}的状态,不允许修改", new String[]{CodeDefaultLC.EDITING.getText()}); }*/ if(operation.equals("update")) { //1. 判断必输项 checkRequiredAttrOnOrder(templateVO, orderDTO, errorMap); //2.先注入,再组合,最后校验 switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO, errorMap); //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的 switchComponentAttrOnOrder(templateVO, orderDTO); //4.校验规则 checkVerifyOnOrder(templateVO, orderDTO, errorMap); //5.判断关键属性 checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO, errorMap); //6.校验枚举的内容是否正确 checkEnumOnOrder(templateVO, orderDTO, errorMap); //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储 switchDateAttrOnOrder(templateVO, orderDTO); //默认的内容不能变,所以只需要拷贝自定义的相关属性即可 copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true, errorMap); //企业码和集团码的不修改 cbo.setDescription(orderDTO.getDescription()); cbo.setName(orderDTO.getName()); try { cbo.setAttributeValueWithNoCheck("description", orderDTO.getDescription()); cbo.setAttributeValue("name", orderDTO.getName()); // if(finalIsProcess){//在流程中不允许更改 // errorMap.put(code,errorMap.getOrDefault(code, errorMap.getOrDefault(code,"")+";数据"+code+"在流程中,不允许更改!")); // }else{ cbo.setLcStatus(status); cbo.setAttributeValue("lcstatus",status); // } } catch (VCIError e) { e.printStackTrace(); } updateList.add(cbo); }else if(operation.equals("delete")){//如果在流程中不允许删除,不在流程中状态为发布或者停用的数据不允许删除,将其更改为停用,其他的情况直接删除 // if(finalIsProcess){ // errorMap.put(code,errorMap.getOrDefault(code, errorMap.getOrDefault(code,"")+";数据"+code+"在流程中,不允许删除!")); //}else { try { Map condtionMap = new HashMap<>(); condtionMap.put("createcodeoid", cbo.getOid()); logger.info("oid:" + cbo.getOid()); List codeCbos = boService.queryCBO("codeallcode", condtionMap); logger.info("codeCbos size:" + codeCbos.size()); if (!CollectionUtils.isEmpty(codeCbos)) { ClientBusinessObject codeCbo = codeCbos.get(0); logger.info("codeCbos code:" + codeCbo.getId()); codeCbo.setLcStatus(CodeDefaultLC.TASK_BACK.getValue()); codeCbo.setAttributeValue("lcstatus", CodeDefaultLC.TASK_BACK.getValue()); updateList.add(codeCbo); } deleteList.add(cbo); }catch (VCIError e) { e.printStackTrace(); } // } }else if(operation.equals("editstatus")){ try { // if (finalIsProcess) { // errorMap.put(code, errorMap.getOrDefault(code, errorMap.getOrDefault(code, "") + ";数据" + code + "在流程中,不允许更改状态!")); // } else { cbo.setLcStatus(status); cbo.setAttributeValue("lcstatus", status); updateList.add(cbo); // } }catch (VCIError e) { e.printStackTrace(); } } }); /** * 错误信息输出 */ if(errorMap.size()>0){ errorMap.keySet().forEach(code->{ if(codeDataMap.containsKey(code)){ RowDatas rowDatas= codeDataMap.get(code); String dataMsg=errorMap.get(code); String oid=rowDatas.getOid(); XMLResultDataObjectDetailDO xmlResultDataObjectDetailDO=new XMLResultDataObjectDetailDO(); xmlResultDataObjectDetailDO.setErrorid("103"); xmlResultDataObjectDetailDO.setMsg(dataMsg); xmlResultDataObjectDetailDO.setId(oid); xmlResultDataObjectDetailDO.setCode(code); resultDataObjectDetailDOs.add(xmlResultDataObjectDetailDO); } }); }else { //存储数据 try { batchCBO.getUpdateCbos().addAll(updateList); batchCBO.getDeleteCbos().addAll(deleteList); boService.persistenceBatch(batchCBO); engineService.batchSaveSelectChar(firstTemplateVO, updateList); errorid="0"; msg="更新/状态更改/删除成功!"; }catch (Throwable e){ errorid="1"; msg="保存失败:"+e; }finally { String finalMsg = msg; String finalErrorid = errorid; cboList.stream().forEach(cbo->{ String code =cbo.getId(); if(codeDataMap.containsKey(code)) { RowDatas rowDatas=codeDataMap.get(code); String oid=rowDatas.getOid(); XMLResultDataObjectDetailDO xmlResultDataObjectDetailDO = new XMLResultDataObjectDetailDO(); xmlResultDataObjectDetailDO.setErrorid(finalErrorid); xmlResultDataObjectDetailDO.setMsg(finalMsg); xmlResultDataObjectDetailDO.setId(oid); xmlResultDataObjectDetailDO.setCode(code); resultDataObjectDetailDOs.add(xmlResultDataObjectDetailDO); } }); } } } /*** * 从缓存里获取到需要导入的相关数据 * @param codeClssifyOid * @param redisOid * @return */ @Override public DataGrid> gridDatas(String codeClssifyOid, String redisOid) { VciBaseUtil.alertNotNull(redisOid,"导入相似数据",redisOid,"数据缓存主键"); List codeImprotDataVOs = 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 = redisService.getCacheList(redisOid); 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 List gridclassifys(String redisOid) { List codeImportTemplateVOs=new ArrayList<>(); VciBaseUtil.alertNotNull(redisOid,"分类",redisOid,"分类缓存主键"); List redisServiceCacheObjects=redisService.getCacheList(redisOid); if(redisServiceCacheObjects!=null){ codeImportTemplateVOs= redisServiceCacheObjects; } return codeImportTemplateVOs; } @Override public BaseResult batchImportData(List codeImprotSaveDatVOList,String classifyAttr, boolean isImprot) { List rowDataList = new ArrayList<>(); List allNeedSaveCboList=new ArrayList<>(); codeImprotSaveDatVOList.stream().forEach(codeImprotSaveDatVO -> { 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)){ 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()); // CodeClassifyTemplateVO codeClassifyTemplateVO= engineService.getUsedTemplateByClassifyOid(orderDTO.getCodeClassifyOid()); CodeClassifyTemplateVO codeClassifyTemplateVO= templateServiceI.getObjectHasAttrByOid(orderDTO.getTemplateOid()); //规则的主键需要去获取 CodeRuleVO ruleVO = engineService.getCodeRuleByClassifyFullInfo(classifyFullInfo); //除去默认的属性.还有只有表单显示的字段才导入 List attrVOS = codeClassifyTemplateVO.getAttributes().stream().filter(s -> !MdmEngineConstant.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); //最后弄组合规则 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(MdmEngineConstant.IMPORT_ROW_INDEX); return !errorMap.containsKey(rowIndex); }).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(needSaveCboList)) { //9.我们处理业务数据 if (isImprot) { productCodeService.productCodeAndSaveData(classifyFullInfo, codeClassifyTemplateVO, ruleVO, null, needSaveCboList); }else { productCodeService.productCodeAndSaveData(classifyFullInfo, codeClassifyTemplateVO, ruleVO, orderDTO.getSecDTOList(), needSaveCboList); } allNeedSaveCboList.addAll(needSaveCboList); } //如果是编码生成失败,则直接就失败了,其他的判断出来有错误的我们都统一返回到excel里面 engineService.batchSaveSelectChar(codeClassifyTemplateVO, allNeedSaveCboList); }); return BaseResult.success(isImprot?"批量历史导入成功":"批量申请成功"); } /*** * * @param codeClassifyVO * @param templateVO * @param codeDataMap * @param codeSystemObjectMap * @param codeOrderDTOList * @param errorMap * @return */ private void getCodeOrderDTOs(CodeClassifyVO codeClassifyVO,CodeClassifyTemplateVO templateVO,MapcodeDataMap,Map codeSystemObjectMap,List codeOrderDTOList,Map errorMap){ codeDataMap.keySet().forEach(code->{ RowDatas rowDatas=codeDataMap.get(code); Map data= rowDatas.getFiledValue(); CodeOrderDTO orderDTO = new CodeOrderDTO(); if(codeSystemObjectMap.containsKey(code)){ ClientBusinessObject sysDataObject= codeSystemObjectMap.get(code); orderDTO.setCodeClassifyOid(codeClassifyVO.getOid());//分类主键 orderDTO.setOid(sysDataObject.getOid());//数据oid orderDTO.setLcStatus(rowDatas.getStatus());//状态 orderDTO.setId(code); orderDTO.setTs(VciDateUtil.getDateFromStringForVci(sysDataObject.getTs())); orderDTO.setBtmname(codeClassifyVO.getBtmname());//业务类型 orderDTO.setDescription("集成调用:更新");//数据描述 if(data.containsKey("name")){ String name=data.get("name"); orderDTO.setName(name);//名称属性值 } orderDTO.setData(data);//设置数据 orderDTO.setSecDTOList(null);//分类码段 orderDTO.setEditInProcess(false);//是否在流程中 orderDTO.setTemplateOid(templateVO.getOid()); }else{ errorMap.put("code","编码为:【"+code+"】的数据在系统中不存在"); } codeOrderDTOList.add(orderDTO); }); } /** * 拷贝数据到cbo对象上 * * @param classifyFullInfo 分类的全部信息 * @param cbo 业务数据 * @param orderDTO 编码申请的信息 * @param templateVO 模板的显示对象 * @param edit 是否为修改 */ private void copyValueToCBO(CodeClassifyFullInfoBO classifyFullInfo, ClientBusinessObject cbo, CodeOrderDTO orderDTO, CodeClassifyTemplateVO templateVO, boolean edit,Map errorMap) { String fullPath = ""; if (!CollectionUtils.isEmpty(classifyFullInfo.getParentClassifyVOs())) { fullPath = classifyFullInfo.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel()))) .map(CodeClassifyVO::getOid).collect(Collectors.joining("##")); } else { fullPath = classifyFullInfo.getCurrentClassifyVO().getOid(); } orderDTO.getData().forEach((key, value) -> { if (!edit || (!boService.checkUnAttrUnEdit(key) && !VciQueryWrapperForDO.LC_STATUS_FIELD.equalsIgnoreCase(key))) { try { cbo.setAttributeValue(key, value); } catch (VCIError e) { logger.error("设置属性的值错误", e); } } }); try { cbo.setAttributeValue(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD, classifyFullInfo.getCurrentClassifyVO().getOid()); cbo.setAttributeValue(MdmEngineConstant.CODE_TEMPLATE_OID_FIELD, templateVO.getOid()); cbo.setAttributeValue(MdmEngineConstant.CODE_FULL_PATH_FILED, fullPath); if (!edit && StringUtils.isBlank(orderDTO.getLcStatus())) { //找生命周期的起始状态, if (StringUtils.isNotBlank(cbo.getLctId())) { OsLifeCycleVO lifeCycleVO = lifeCycleService.getLifeCycleById(cbo.getLctId()); if (lifeCycleVO != null) { cbo.setLcStatus(lifeCycleVO.getStartStatus()); } else { cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); } } else { cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); } } int secret = VciBaseUtil.getInt(cbo.getAttributeValue(MdmEngineConstant.SECRET_FIELD)); if (secret == 0 || !secretService.checkDataSecret(secret)) { Integer userSecret = VciBaseUtil.getCurrentUserSecret(); cbo.setAttributeValue(MdmEngineConstant.SECRET_FIELD, String.valueOf((userSecret == null || userSecret == 0) ? UserSecretEnum.NONE.getValue() : userSecret)); } } catch (Throwable e) { logger.error("设置默认的属性的值错误", e); } } /** * 转换时间的格式 * * @param templateVO 模板的显示对象,需要包含属性 * @param orderDTO 编码申请的信息 */ private void switchDateAttrOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO) { Map dateAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getCodedateformat())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(dateAttrVOMap)) { dateAttrVOMap.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (StringUtils.isNotBlank(value)) { DateConverter dateConverter = new DateConverter(); dateConverter.setAsText(value); value = VciDateUtil.date2Str(dateConverter.getValue(), VciDateUtil.DateTimeMillFormat); setValueToOrderDTO(orderDTO, attrId, value); } }); } } /** * 设置新的值到申请对象上 * * @param orderDTO 编码申请对象 * @param attrId 属性的编号 * @param value 值 */ private void setValueToOrderDTO(CodeOrderDTO orderDTO, String attrId, String value) { attrId = attrId.toLowerCase(Locale.ROOT); if (VciQueryWrapperForDO.BASIC_FIELD_MAP.containsKey(attrId)) { WebUtil.setValueToField(WebUtil.getFieldForObject(attrId, orderDTO.getClass()).getName(), orderDTO, value); } else { orderDTO.getData().put(attrId, value); } } /** * 校验枚举的内容 * * @param templateVO 模板的显示对象,需要包含属性 * @param orderDTO 编码申请的信息 */ private void checkEnumOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO,Map errorMap) { //如果枚举可以修改,则不需要校验是否符合枚举的选项 Map enumAttrVOMap = templateVO.getAttributes().stream().filter(s -> (StringUtils.isNotBlank(s.getEnumString()) || StringUtils.isNotBlank(s.getEnumid())) && !VciBaseUtil.getBoolean(s.getEnumeditflag())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(enumAttrVOMap)) { enumAttrVOMap.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (StringUtils.isNotBlank(value)) { //有值才能校验 List comboboxKVs = this.engineService.listComboboxItems(attrVO); if (!comboboxKVs.stream().anyMatch(s -> value.equalsIgnoreCase(s.getKey()))) { errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"")+";属性【"+attrVO.getName()+"】的值不符合枚举的要求"); //throw new VciBaseException("属性【{0}】的值不符合枚举的要求", new String[]{attrVO.getName()}); } } }); } } /** * 校验关键属性 * * @param classifyFullInfo 分类的全部信息 * @param templateVO 模板的内容,必须包含模板属性 * @param orderDTO 编码申请的相关的信息 */ private void checkKeyAttrOnOrder(CodeClassifyFullInfoBO classifyFullInfo, CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO,Map errorMap) { //先获取关键属性的规则,也利用继承的方式 CodeKeyAttrRepeatRuleVO 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)); Map conditionMap = new HashMap<>(); 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()); ketAttrMap.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (value == null) { value = ""; } engineService.wrapperKeyAttrConditionMap(value, keyRuleVO, attrId, trim, ignoreCase, ignoreWidth, trimAll, conditionMap); }); //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可 if (!CollectionUtils.isEmpty(conditionMap)) { final String[] sql = {"select count(*) from " + VciBaseUtil.getTableName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()) + " where 1 = 1 "}; conditionMap.forEach((key, value) -> { sql[0] += " and " + key + " = " + value; }); if (StringUtils.isNotBlank(orderDTO.getOid())) { //修改的时候,需要排除自己 sql[0] += " and oid != '" + orderDTO.getOid() + "'"; } else if (StringUtils.isNotBlank(orderDTO.getCopyFromVersion())) { sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'"; } sql[0] += " and islastR = '1' and islastV = '1' "; if (boService.queryCountBySql(sql[0], new HashMap<>()) > 0) { String ruleInfoMsg = keyRuleVO == null ? "" : "查询规则:去除空格--{0},忽略大小写--{1},忽略全半角--{2},忽略全部空格--{3}"; String[] objs = new String[]{trim ? "是" : "否", ignoreCase ? "是" : "否", ignoreWidth ? "是" : "否", trimAll ? "是" : "否"}; String defaultValue=";根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。"; String errormsg=defaultValue+MessageFormat.format(ruleInfoMsg, objs); errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"")+errormsg); // throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。" + ruleInfoMsg, objs); } } } /** * 校验正则表达式是否正确 * * @param templateVO 模板的信息,必须包含属性的内容 * @param orderDTO 编码申请的相关的信息 */ private void checkVerifyOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO,Map errorMap) { Map verifyAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getVerifyrule())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(verifyAttrVOMap)) { verifyAttrVOMap.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (StringUtils.isNotBlank(value) && !value.matches(attrVO.getVerifyrule())) { errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"")+";属性["+attrVO.getName()+"]的值不符合校验规则的要求"); //校验正则表达式 // throw new VciBaseException("属性[{0}]的值不符合校验规则的要求", new String[]{attrVO.getName()}); } }); } } /** * 转换组合规则的值 * * @param templateVO 模板的显示对象,需要包含模板属性 * @param orderDTO 编码申请的信息 */ private void switchComponentAttrOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO) { Map compAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getComponentrule())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(compAttrVOMap)) { Map dataMap = WebUtil.objectToMapString(orderDTO); Map dataLowMap = new HashMap<>(); if (!CollectionUtils.isEmpty(dataMap)) { dataMap.forEach((key, value) -> { dataLowMap.put(key.toLowerCase(Locale.ROOT), value); }); } dataLowMap.putAll(orderDTO.getData()); compAttrVOMap.forEach((attrId, attrVO) -> { dataLowMap.put(attrId, formulaService.getValueByFormula(dataLowMap, attrVO.getComponentrule())); }); dataLowMap.forEach((key, value) -> { setValueToOrderDTO(orderDTO, key, value); }); } } /** * 处理分类注入的信息 * * @param templateVO 模板的显示对象,必须要后模板的属性 * @param classifyFullInfoBO 分类的全路径 * @param orderDTO 编码申请的信息 */ private void switchClassifyLevelOnOrder(CodeClassifyTemplateVO templateVO, CodeClassifyFullInfoBO classifyFullInfoBO, CodeOrderDTO orderDTO,Map errorMap) { Map classifyAttrVOMap = templateVO.getAttributes().stream().filter( s -> StringUtils.isNotBlank(s.getClassifyinvokeattr()) && StringUtils.isNotBlank(s.getClassifyinvokelevel()) ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (classifyFullInfoBO.getTopClassifyVO() == null) { //需要重新查询一下,因为这个是指定的分类进来的 } if (!CollectionUtils.isEmpty(classifyAttrVOMap)) { classifyAttrVOMap.forEach((attrId, attrVO) -> { //分类注入的编号或者名称, //层级包含指定层和最小层 CodeClassifyVO classifyVO = null; if (!CodeLevelTypeEnum.MIN.getValue().equalsIgnoreCase(attrVO.getClassifyinvokelevel()) && !"min".equalsIgnoreCase(attrVO.getClassifyinvokelevel())) { //指定了层级的 //注意,因为查询上级分类出来的层级是倒序的,即顶层节点是最大的值 List classifyVOS = classifyFullInfoBO.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 = classifyFullInfoBO.getCurrentClassifyVO(); } if (classifyVO == null) { //说明层级有误 errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"")+";分类树上没有层级[" + attrVO.getClassifyinvokelevel() + "]"); //orderDTO.getData().put(attrId, "分类树上没有层级[" + attrVO.getClassifyinvokelevel() + "]"); // classifyVO = classifyFullInfoBO.getCurrentClassifyVO(); } else { Map classifyDataMap = VciBaseUtil.objectToMapString(classifyVO); String value = classifyDataMap.getOrDefault(attrVO.getClassifyinvokeattr(), ""); orderDTO.getData().put(attrId, value); } }); } } /** * 校验属性是否为必输 * * @param templateVO 模板的显示对象,需要包含模板属性 * @param orderDTO 编码申请的信息 */ private void checkRequiredAttrOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO,Map errorMap) { Map requiredAttrMap = templateVO.getAttributes().stream().filter( s -> VciBaseUtil.getBoolean(s.getRequireflag()) && StringUtils.isBlank(s.getComponentrule()) && StringUtils.isBlank(s.getClassifyinvokeattr())) .collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(requiredAttrMap)) { requiredAttrMap.forEach((attrId, attrVO) -> { //只有企业编码,状态,备注,模板主键,分类主键这几个是固定的,其余都是自行配置的 if (StringUtils.isBlank(getValueFromOrderDTO(orderDTO, attrId))) { errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"") + ";属性【{"+attrVO.getName()+"}】必须要输入(选择)内容" ); // throw new VciBaseException("属性【{0}】必须要输入(选择)内容", new String[]{attrVO.getName()}); } }); } } /** * 从编码申请信息对象上获取某个属性的值 * * @param orderDTO 编码申请对象 * @param attrId 属性的编号 * @return 值 */ private String getValueFromOrderDTO(CodeOrderDTO orderDTO, String attrId) { attrId = attrId.toLowerCase(Locale.ROOT); String value = null; if (VciQueryWrapperForDO.BASIC_FIELD_MAP.containsKey(attrId)) { value = WebUtil.getStringValueFromObject(WebUtil.getValueFromField(WebUtil.getFieldForObject(attrId, orderDTO.getClass()).getName(), orderDTO)); } else { //说明是自行配置的 //前端必须要传递小写的属性 value = orderDTO.getData().getOrDefault(attrId, ""); } return value; } /** * 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 = boService.createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()); rowData.forEach((field,value)->{ try { cbo.setAttributeValueWithNoCheck(field,value); if(WebUtil.isDefaultField(field)){ WebUtil.setValueToField(field, cbo, value); } } catch (VCIError e) { logger.error("设置属性的值错误",e); } }); try { if(newCode){ cbo.setAttributeValue(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD,classifyFullInfo.getCurrentClassifyVO().getOid()); cbo.setAttributeValue(MdmEngineConstant.CODE_FULL_PATH_FILED,fullPath); //cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); int secret = VciBaseUtil.getInt(cbo.getAttributeValue(MdmEngineConstant.SECRET_FIELD)); if(secret == 0 || !secretService.checkDataSecret(secret) ){ Integer userSecret = VciBaseUtil.getCurrentUserSecret(); cbo.setAttributeValue(MdmEngineConstant.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()); cbo.setAttributeValue(MdmEngineConstant.CODE_TEMPLATE_OID_FIELD,codeImprotDataVO.getTemplateOid()); cbo.setAttributeValue(MdmEngineConstant.IMPORT_ROW_INDEX,rowData.get(MdmEngineConstant.IMPORT_ROW_INDEX)); }catch (Throwable e){ logger.error("设置默认的属性的值错误",e); } cboList.add(cbo); }); } private void createRedisDatas(String uuid, CodeClassifyTemplateVO templateVO, 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(MdmEngineConstant.IMPORT_ROW_INDEX); 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); redisService.setCacheList(uuid+"-"+codeImprotDataVO.getCodeClassifyOid(), codeImprotDataVOList); logger.info(uuid+"-"+codeImprotDataVO.getCodeClassifyOid()+":条目数"+codeImprotDataVOList.size()); //redisService.expire(uuid+"-"+codeImprotDataVO.getCodeClassifyOid(),6000000);//redis过期时间 }); } }