ludc
2023-11-24 b267ac7499877043675bbd25d1478b1731c12ec9
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmIOServiceImpl.java
@@ -3,6 +3,8 @@
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.protobuf.ServiceException;
import com.vci.ubcs.code.applyjtcodeservice.feign.IMdmInterJtClient;
import com.vci.ubcs.code.bo.AttributeValue;
import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO;
import com.vci.ubcs.code.bo.CodeTemplateAttrSqlBO;
@@ -11,6 +13,7 @@
import com.vci.ubcs.code.entity.CodeAllCode;
import com.vci.ubcs.code.enumpack.CodeDefaultLC;
import com.vci.ubcs.code.enumpack.CodeLevelTypeEnum;
import com.vci.ubcs.code.enumpack.sysIntegrationPushTypeEnum;
import com.vci.ubcs.code.lifecycle.CodeAllCodeLC;
import com.vci.ubcs.code.mapper.CommonsMapper;
import com.vci.ubcs.code.service.*;
@@ -63,6 +66,7 @@
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -95,18 +99,25 @@
   @Value("${batchadd.redis.time:6000000}")
   public int BATCHADD_REDIS_TIME;
   @Value("${batchadd.import_data_limit:5001}")
   private Integer IMPORT_DATA_LIMIT;
   /**
    * 主题库分类的服务
    */
   @Resource
   private ICodeClassifyService classifyService;
   @Resource
   private MdmEngineService mdmEngineService;
   /**
    * 通用查询
    */
   @Resource
   private CommonsMapper commonsMapper;
   /****
    * 码值服务
    */
@@ -154,7 +165,11 @@
    */
   @Autowired
   private IBtmTypeClient btmTypeClient;
   /***
    * 申请集团编码服务
    */
   @Resource
   private IMdmInterJtClient mdmInterJtClient;
   /***
    * 密级服务
    */
@@ -173,7 +188,7 @@
    * @return excel的文件地址
    */
   @Override
   public  String downloadTopImportExcel(String codeClassifyOid){
   public String downloadTopImportExcel(String codeClassifyOid){
      List<CodeClassifyTemplateVO> templateVOList=new ArrayList<>();
      VciBaseUtil.alertNotNull("导出模板","导出的配置",codeClassifyOid,"主题库分类的主键");
      CodeClassifyVO codeClassifyVO = classifyService.getObjectByOid(codeClassifyOid);
@@ -340,10 +355,12 @@
   @Override
   public String createImportExcel(String codeClassifyOid, boolean isHistory) {
      List<CodeClassifyTemplateVO> templateVOList=new ArrayList<>();
      VciBaseUtil.alertNotNull("导出模板","导出的配置",codeClassifyOid,"主题库分类的主键");
      CodeClassifyVO codeClassifyVO = classifyService.getObjectByOid(codeClassifyOid);
      //获取码段宽度
      //String secWidth = getCodeSegmentWidth(codeClassifyVO.getOid());
      if(isHistory){
         templateVOList= templateService.childTemplates(codeClassifyOid);
@@ -383,17 +400,17 @@
               && (isHistory || VciBaseUtil.getBoolean(s.getFormDisplayFlag()))
         ).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(templateAttrVOS)) {
               throw new VciBaseException("模板没有配置任何【表单显示】为【是】的属性");
            }
         if (CollectionUtils.isEmpty(templateAttrVOS)) {
            throw new VciBaseException("模板没有配置任何【表单显示】为【是】的属性");
         }
         List<CodeClassifyTemplateAttrVO> idAttrVOList = codeClassifyTemplateVO.getAttributes().stream().filter(s -> s.getId().equalsIgnoreCase(CODE_FIELD)).collect(Collectors.toList());
         LinkedList<WriteExcelData> 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():"企业编码"));
            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():"企业编码",idAttrVOList.get(0).getId()));
         }
         for (int i = 0; i < templateAttrVOS.size(); i++) {
            CodeClassifyTemplateAttrVO attrVO = templateAttrVOS.get(i);
@@ -401,7 +418,7 @@
            Object text = attrVO.getName();
            text = exportKeyAndRequired(workbook,attrVO,text);
            int colIndex = (isHistory?3:0) + i;
            WriteExcelData excelData = new WriteExcelData(0, colIndex, text);
            WriteExcelData excelData = new WriteExcelData(0, colIndex, text,attrVO.getId());
            if(StringUtils.isNotBlank(attrVO.getCodeDateFormat())
               || VciFieldTypeEnum.VTDateTime.name().equalsIgnoreCase(attrVO.getAttributeDataType())
               || VciFieldTypeEnum.VTDate.name().equalsIgnoreCase(attrVO.getAttributeDataType())
@@ -458,6 +475,30 @@
   }
   /**
    * 获取码段宽度
    * @param codeClassifyOid
    * @return
    */
   private String getCodeSegmentWidth(String codeClassifyOid){
      CodeClassifyVO codeClassifyVO = classifyService.getObjectByOid(codeClassifyOid);
      // 要获取码段宽度,先要获取规则,当前没有往上找
      CodeRuleVO codeRuleByClassifyFullInfo = mdmEngineService.getCodeRuleByClassifyFullInfo(classifyService.getClassifyFullInfo(codeClassifyOid));
      List<CodeBasicSecVO> secVOList = codeRuleByClassifyFullInfo.getSecVOList();
      if(secVOList.isEmpty()){
         return "";
      }
      StringBuffer secWidth = new StringBuffer("");
      for (int j = 0; j < secVOList.size(); j++) {
         CodeBasicSecVO secVO = secVOList.get(j);
         int width = VciBaseUtil.getInt(secVO.getCodeSecLength()) + ((secVO.getPrefixCode() + secVO.getSuffixCode()).length());
         secWidth.append(width).append("#");
      }
      return secWidth.toString().substring(0, secWidth.length() - 1);
   }
   /**
    * 导出的时候封装必输和关键属性
    * @param attrVO 属性的显示对象
    * @param text 单元格的值
@@ -489,7 +530,6 @@
      return text;
   }
   /**
    * 批量申请编码数据
    *
@@ -518,7 +558,7 @@
      //校验模板是不是最新的
      checkTemplateSync(sheetDataSetList,templateVO,0);
      //先不用管属性是否都存在,先转换一下数据
      Map<String,String> errorMap = new HashMap<>();
      Map<String,String> errorMap = new ConcurrentHashMap<>();
      String redisUUid=batchImportCodes(orderDTO,templateVO,dataSet,errorMap,true);
      CodeImProtRusultVO codeImProtRusultVO = new CodeImProtRusultVO();
      List<String> needRowIndexList = new ArrayList<>();
@@ -532,7 +572,6 @@
//      return null;
      return codeImProtRusultVO;
   }
   /***
    * 从顶层批量申请导入方法
@@ -639,13 +678,12 @@
         });
         //都转换完了。需要批量检查
         //如果出错了,我们依然执行有效的数据,无效的数据写回到excel中
         //2.判断必输项。。需要全部的属性,如果是必输,但是表单里面不显示的,只能是分类注入或者组合规则
         batchCheckRequiredAttrOnOrder(templateVO,allCboList,errorMap);
         //3.判断关键属性
         CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, allCboList);
         CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, allCboList,errorMap);
         Set<String> selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList();
         Set<String> keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList();
         if(!CollectionUtils.isEmpty(selfRepeatRowIndexList)){
@@ -655,7 +693,7 @@
         }
         if(!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)){
            keyAttrRepeatRowIndexList.stream().forEach(rowIndex->{
               errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" );
               errorMap.put(rowIndex, "关键属性与系统中的重复;" + errorMap.getOrDefault(rowIndex,"") );
            });
         }
         //分类注入
@@ -713,10 +751,8 @@
         createRedisDatas(uuid + "-ok",codeImprotDataVOS, newErrorMap,true);
      });
      //往物品节点上加模板
      List<String> needRowIndexList=new ArrayList<>();
      CodeImProtRusultVO codeImProtRusultVO = new CodeImProtRusultVO();
      if(errorMap.size()>0) {
@@ -786,10 +822,15 @@
      String uuid=VciBaseUtil.getPk();
      boolean isCreateUUid=false;
      boolean isExport=false;
      //long start = System.currentTimeMillis();
      for(int i=0;i<sheetDataSetList.size()-1;i++) {
         if (CollectionUtils.isEmpty(sheetDataSetList) || CollectionUtils.isEmpty(sheetDataSetList.get(i).getRowData())
            || sheetDataSetList.get(i).getRowData().size() < 1) {
            continue;
         }
         // 单次导入数量限制
         if(sheetDataSetList.get(i).getRowData().size() > IMPORT_DATA_LIMIT){
            throw new ServiceException("为了保证系统的稳定性,请一次不要导入超过"+IMPORT_DATA_LIMIT+"条的数据");
         }
         //历史导入的时候不处理编码
         //----逻辑内容----
@@ -803,7 +844,6 @@
         //     5.3 企业编码的长度,和编码规则的长度要对应上
         //     5.4 获取流水码段的值,去除填充的字符,看流水号是多少,然后将流水号和现在的最大流水号判断,小于就直接录入,大于则修改最大流水号
         //     5.5 存储企业编码到allcode中
         //查询分类和模板
         CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(codeClassifyOid);
@@ -814,7 +854,7 @@
         //找第一行,为了找标题
         CodeClassifyTemplateVO templateVO = new CodeClassifyTemplateVO();
         /**  if (!templateService.checkChildHasSameTemplate(classifyFullInfo.getCurrentClassifyVO().getOid())) {
          throw new VciBaseException("当前的分类以及下级分类的模板不相同");
             throw new VciBaseException("当前的分类以及下级分类的模板不相同");
          }***/
         //都转换完了。需要批量检查
         //找所有的分类路径,需要校验路径是否正确,是否都在当前的分类的下级
@@ -892,7 +932,7 @@
         //判断必输项
         batchCheckRequiredAttrOnOrder(templateVO, cboList, errorMap);
         //有限校验编码是否存在
         //优先校验编码是否存在
         batchCheckIdExistOnOrder(templateVO, cboList, errorMap);
         //boolean
@@ -902,15 +942,18 @@
         batchSwitchEnumAttrOnOrder(attrVOS, cboList, errorMap);
         batchSwitchReferAttrOnOrder(attrVOS, cboList, errorMap);
         //6.处理分类注入
         batchSwitchClassifyAttrOnOrder(attrVOS, cboList, classifyFullInfo,true);
         //设置默认值
         batchSwitchAttrDefault(attrVOS, cboList);
         //7.处理组合规则
         batchSwitchComponentAttrOnOrder(attrVOS, cboList);
         //3.判断关键属性
         CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList);
         CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList,errorMap);
         Set<String> selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList();
         Set<String> keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList();
         if (!CollectionUtils.isEmpty(selfRepeatRowIndexList)) {
@@ -920,7 +963,7 @@
         }
         if (!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)) {
            keyAttrRepeatRowIndexList.stream().forEach(rowIndex -> {
               errorMap.put(rowIndex, errorMap.getOrDefault(rowIndex, "") + ";关键属性与系统中的重复");
               errorMap.put(rowIndex, "关键属性与系统中的重复;" + errorMap.getOrDefault(rowIndex, ""));
            });
         }
         //4.校验规则
@@ -931,14 +974,15 @@
         if (CollectionUtils.isEmpty(ruleOidMap.values())) {
            throw new VciBaseException("导入的数据所选择的分类都没有设置编码规则");
         }
         Map<String, CodeRuleVO> ruleVOMap = ruleService.listCodeRuleByIds(ruleOidMap.values(), true).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
         // TODO: 该用oid查询规则的,别用id
         Map<String, CodeRuleVO> ruleVOMap = ruleService.listCodeRuleByOids(ruleOidMap.values()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
         //校验编码规则和码段是否正确
         Map<String, List<String>> ruleRowIndexMap = new ConcurrentHashMap<>();
         checkSecLengthInHistory(cboList, classifyVOMap, ruleVOMap, ruleOidMap, errorMap, ruleRowIndexMap);
         ruleRowIndexMap.keySet().parallelStream().forEach(ruleOid -> {
            List<String> rowIndexList = ruleRowIndexMap.get(ruleOid);
            List<ClientBusinessObject> thisCbos = cboList.stream().filter(cbo -> rowIndexList.contains(cbo.getAttributeValue(IMPORT_ROW_INDEX)) && !errorMap.containsKey(cbo.getAttributeValue(IMPORT_ROW_INDEX))).collect(Collectors.toList());
//我们需要先查询一下,内容是否已经存在
            //我们需要先查询一下,内容是否已经存在
            if(!CollectionUtils.isEmpty(thisCbos)){
               List<String> existIds = new ArrayList<>();
               VciBaseUtil.switchCollectionForOracleIn(thisCbos).stream().forEach(cbos -> {
@@ -1026,7 +1070,7 @@
               //VciBaseUtil.setCurrentUserSessionInfo(sessionInfo);
               List<String> rowIndexList = ruleRowIndexMap.get(ruleOid);
               List<ClientBusinessObject> thisCbos = finalNeedSaveCboList.stream().filter(cbo -> rowIndexList.contains(cbo.getAttributeValue(IMPORT_ROW_INDEX)) && !errorMap.containsKey(cbo.getAttributeValue(IMPORT_ROW_INDEX))).collect(Collectors.toList());
               List<BaseModel> dataCBOList=new ArrayList<>();
               List<BaseModel> dataCBOList=new CopyOnWriteArrayList<>();
               thisCbos.stream().forEach(clientBusinessObject -> {
                  BaseModel baseModel=new BaseModel();
                  BeanUtil.convert(clientBusinessObject,baseModel);
@@ -1037,12 +1081,13 @@
               if (!CollectionUtils.isEmpty(thisCbos)) {
                  try {
                     // TODO 多线程流问题
                     productCodeService.productCodeAndSaveData(classifyFullInfo, finalTemplateVO, ruleVOMap.get(ruleOid), null, dataCBOList);
                  } catch (Throwable e) {
                     log.error("批量产生编码的时候出错了", e);
                     thisCbos.stream().forEach(cbo -> {
                        String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX);
                        errorMap.put(rowIndex, errorMap.getOrDefault(rowIndex, "") + ";系统错误,存储数据的时候出错了");
                        errorMap.put(rowIndex, errorMap.getOrDefault(rowIndex, "") + ";系统错误,存储数据的时候出错了:"+e.getMessage());
                     });
                  }
@@ -1055,6 +1100,8 @@
            engineService.batchSaveSelectChar(templateVO, dataCBOIdList);
         }
      }
      //long end = System.currentTimeMillis();
      //log.info("=============for执行时间================="+String.valueOf((end-start)/1000));
      String excelFileName="";
      if(isExport&&!CollectionUtils.isEmpty(shetNameMap)) {
         excelFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + "错误信息.xls";
@@ -1080,6 +1127,7 @@
      return codeImProtRusultVO;
   }
   /*private void converBaseModels(List<ClientBusinessObject> clientBusinessObjects,List<BaseModel>dataCBOList){
      clientBusinessObjects.stream().forEach(clientBusinessObject -> {
         BaseModel baseModel=new BaseModel();
@@ -1093,6 +1141,7 @@
      });
   }*/
   /***
    * 从execl里构建对象
    * @param rowDataList
@@ -1132,7 +1181,6 @@
    * @param currentTemplateVO
    * @param templateColumnVOMap
    */
   private void createTemplate(CodeClassifyTemplateVO currentTemplateVO,Map<String,List<ColumnVO>>templateColumnVOMap){
      List<CodeClassifyTemplateAttrVO> templateAttrVOS = currentTemplateVO.getAttributes().stream().filter(s ->
@@ -1285,7 +1333,7 @@
      //2.判断必输项。。需要全部的属性,如果是必输,但是表单里面不显示的,只能是分类注入或者组合规则
      batchCheckRequiredAttrOnOrder(templateVO,cboList,errorMap);
      //3.判断关键属性
      CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList);
      CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList,errorMap);
      Set<String> selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList();
      Set<String> keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList();
      if(!CollectionUtils.isEmpty(selfRepeatRowIndexList)){
@@ -1295,7 +1343,7 @@
      }
      if(!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)){
         keyAttrRepeatRowIndexList.stream().forEach(rowIndex->{
            errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" );
            errorMap.put(rowIndex,"关键属性与系统中的重复;" + errorMap.getOrDefault(rowIndex,""));
         });
      }
      //分类注入
@@ -1522,7 +1570,6 @@
            total += commonsMapper.queryCountBySql(countSql);
         }
      }else{
         total = commonsMapper.queryCountBySql(countSql);
      }
      List<String> selectFieldList = new ArrayList<>();
@@ -1722,7 +1769,7 @@
         ).collect(Collectors.toList());
         String fullPath = getFullPath(classifyFullInfo);
         excelToCbo(classifyFullInfo,fieldIndexMap,rowDataList, codeClassifyTemplateVO,cboList,fullPath,!isImprot);
         Map<String,String> errorMap=new HashMap<>();
         Map<String,String> errorMap=new ConcurrentHashMap<>();
         Map<String/**路径**/, CodeClassifyVO> pathMap=new HashMap<>() ;
         //校验编码规则和码段是否正确
         Map<String, List<String>> ruleRowIndexMap = new ConcurrentHashMap<>();
@@ -1743,7 +1790,8 @@
            Map<String/**分类主键**/, String/**规则主键**/> ruleOidMap = new ConcurrentHashMap<String, String>();
            List<String> unExistRuleClassifyOidList = new CopyOnWriteArrayList<>();
            checkRuleOidInHistory(classifyVOMap, ruleOidMap, unExistRuleClassifyOidList);
            ruleVOMap = ruleService.listCodeRuleByIds(ruleOidMap.values(), true).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
            // TODO   改用oid查询的,这儿不该用id
            ruleVOMap = ruleService.listCodeRuleByOids(ruleOidMap.values()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
            checkSecLengthInHistory(cboList, classifyVOMap, ruleVOMap, ruleOidMap, errorMap, ruleRowIndexMap);
         }
@@ -1766,12 +1814,12 @@
         //最后弄组合规则
         batchSwitchComponentAttrOnOrder(attrVOS,cboList);
         //3.判断关键属性
         CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, codeClassifyTemplateVO, cboList);
         CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, codeClassifyTemplateVO, cboList,errorMap);
         Set<String> selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList();
         Set<String> keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList();
         if(!CollectionUtils.isEmpty(keyAttrRepeatRowIndexList)){
            keyAttrRepeatRowIndexList.stream().forEach(rowIndex->{
               errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" );
               errorMap.put(rowIndex,"关键属性与系统中的重复;" + errorMap.getOrDefault(rowIndex,""));
            });
         }
         //4.校验规则
@@ -1900,7 +1948,7 @@
    */
   @Override
   public void batchSyncApplyCode(CodeOrderDTO orderDTO, DataObjectVO dataObjectVO, LinkedList<XMLResultDataObjectDetailDO> resultDataObjectDetailDOs,boolean isCodeOrGroupCode) {
      Map<String,String> errorMap=new HashMap<>();
      Map<String,String> errorMap=new ConcurrentHashMap<>();
      VciBaseUtil.alertNotNull(orderDTO,"编码申请相关的数据",orderDTO.getCodeClassifyOid(),"主题库分类主键");
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      //规则的主键需要去获取
@@ -1932,7 +1980,8 @@
         && com.alibaba.cloud.commons.lang.StringUtils.isBlank(s.getComponentRule()) && com.alibaba.cloud.commons.lang.StringUtils.isBlank(s.getClassifyInvokeAttr())//组合规则和分类注入确实没给用户导出去
      ).collect(Collectors.toList());
      if(!CollectionUtils.isEmpty(unExistAttrVOs)){
         throw new VciBaseException("【" + unExistAttrVOs.stream().map(CodeClassifyTemplateAttrVO::getName) + "】这些属性在excel中没有找到");
         String message=unExistAttrVOs.stream().map(CodeClassifyTemplateAttrVO::getName).collect(Collectors.joining(SERIAL_UNIT_SPACE));
         throw new VciBaseException("【" + message + "】这些属性在excel中没有找到");
      }
      List<ClientBusinessObject> cboList = new ArrayList<>();
      String fullPath = getFullPath(classifyFullInfo);
@@ -1948,20 +1997,34 @@
      //都转换完了。需要批量检查
      //如果出错了,我们依然执行有效的数据,无效的数据写回到excel中
      Map<String,String> errorKeyMap=new HashMap<>();
      //1.分类注入
      batchSwitchClassifyAttrOnOrder(attrVOS,cboList,classifyFullInfo,false);
      //boolean
      reSwitchBooleanAttrOnOrder(attrVOS,cboList);
      // cboList.stream().forEach(cbo->{
      //2.校验规则
      batchCheckVerifyOnOrder(attrVOS, cboList,errorMap);
      //3.校验枚举是否正确
      batchSwitchEnumAttrOnOrder(attrVOS,cboList,errorMap);
      //4.时间格式的验证
      //4.时间的,必须统一为yyyy-MM-dd HH:mm:ss
      batchSwitchDateAttrOnOrder(attrVOS,cboList,errorMap);
      //5.处理参照的情况
      batchSwitchReferAttrOnOrder(attrVOS,cboList,errorMap);
      //6设置默认值
      batchSwitchAttrDefault(attrVOS, cboList);
      //2.判断必输项。。需要全部的属性,如果是必输,但是表单里面不显示的,只能是分类注入或者组合规则
      batchCheckRequiredAttrOnOrder(templateVO,cboList,errorMap);
      /**
       * 关键熟悉错误提示
       */
      Map<String,String> errorKeyMap=new HashMap<>();
      //最后弄组合规则
      batchSwitchComponentAttrOnOrder(attrVOS,cboList);
      //3.判断关键属性
      CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList);
      CodeImportResultVO keyResultVO = batchCheckKeyAttrOnOrder(classifyFullInfo, templateVO, cboList,errorKeyMap);
      Set<String> selfRepeatRowIndexList = keyResultVO.getSelfRepeatRowIndexList();
      Set<String> keyAttrRepeatRowIndexList = keyResultVO.getKeyAttrRepeatRowIndexList();
      Map<String,List<String>>keyAttrOkOidTORepeatOidMap= keyResultVO.getKeyAttrOkOidTORepeatOidMap();
      if(!CollectionUtils.isEmpty(selfRepeatRowIndexList)){
         selfRepeatRowIndexList.stream().forEach(rowIndex->{
               /* //传入数据之间关键属性的校验
@@ -1990,23 +2053,13 @@
                resultDataObjectDetailDO.setMsg(errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" );
                resultDataObjectDetailDOs.add(resultDataObjectDetailDO);
                */
            errorKeyMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";关键属性与系统中的重复" );
            Map<String, List<BaseModel>> indexTODataMap=keyResultVO.getIndexTODataMap();
            if(indexTODataMap.containsKey(rowIndex)){
               List<BaseModel> baseModelList= indexTODataMap.get(rowIndex);
            }
            errorKeyMap.put(rowIndex, "关键属性与系统中的重复;" + errorKeyMap.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 = {""};
@@ -2064,8 +2117,8 @@
                     String lcstatus =newCbo.getLcStatus();
                     String newOid =newCbo.getOid();
                     Date ts =newCbo.getTs();
                     groupCode=newCbo.getData().get("GROUPCODE");
                     code=newCbo.getId();
                     code = StringUtils.isBlank(newCbo.getId())?"":newCbo.getId();
                     groupCode=newCbo.getData().getOrDefault("GROUPCODE","");
                     String lastmodifier=newCbo.getLastModifier();
                     if (lcstatus!=null&&!lcstatus.equals(CodeDefaultLC.RELEASED.getValue())) {
                        newCbo.setOid(newOid);
@@ -2083,6 +2136,7 @@
                     XMLResultDataObjectDetailDO resultDataObjectDetailDO = new XMLResultDataObjectDetailDO();
                     if(isCodeOrGroupCode) {
                        if(StringUtils.isBlank(groupCode)){
                           errorid="1";
                           mes+=";申请的编码类型为集团码,等待集团编码赋值";
                        }
                        resultDataObjectDetailDO.setCode(groupCode);
@@ -2106,10 +2160,7 @@
      }
      //  });
      //设置默认值
      batchSwitchAttrDefault(attrVOS, cboList);
      //最后弄组合规则
      batchSwitchComponentAttrOnOrder(attrVOS,cboList);
      //要把以上的错误的都抛出后,再继续处理时间和组合规则
      List<ClientBusinessObject> needSaveCboList = cboList.stream().filter(cbo -> {
         String rowIndex =cbo.getAttributeValue(IMPORT_ROW_INDEX);
@@ -2125,38 +2176,46 @@
         needSaveCboList.stream().forEach(clientBusinessObject -> {
            BaseModel baseModel=new BaseModel();
            BeanUtil.convert(clientBusinessObject,baseModel);
         //(VciBaseUtil.objectToMapString(clientBusinessObject));
            //(VciBaseUtil.objectToMapString(clientBusinessObject));
            dataCBOList.add(baseModel);
            allNeedSaveCboList.add(baseModel.getOid());
         });
         try {
            List<String>applyGroupCodeIdList=new ArrayList<>();
            productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(), dataCBOList);
            //如果是编码生成失败,则直接就失败了,其他的判断出来有错误的我们都统一返回到excel里面
            engineService.batchSaveSelectChar(templateVO, dataCBOList);
            // if(!isProcess){
            dataCBOList.stream().forEach(needSaveCbo->{
               XMLResultDataObjectDetailDO resultDataObjectDetailDO=new XMLResultDataObjectDetailDO();
               String code=needSaveCbo.getId();
               String groupCode=needSaveCbo.getData().getOrDefault("GROUPCODE","");
               String code=StringUtils.isBlank(needSaveCbo.getId())?" ":needSaveCbo.getId();
               String groupCode=needSaveCbo.getData().getOrDefault("GROUPCODE"," ");
               //resultDataObjectDetailDO.setCode(needSaveCbo.getId());
               String msg="申请编码成功";
               String oid=needSaveCbo.getOid();
               String sourceOid=oid;
               applyGroupCodeIdList.add(oid);
               if(codeOidToSystemOidMap.containsKey(oid)){
                  sourceOid=codeOidToSystemOidMap.get(oid);
               }
               if(isCodeOrGroupCode) {
                  if(StringUtils.isBlank(groupCode)){
                     resultDataObjectDetailDO.setErrorid("1");
                     msg="申请的编码类型为集团码,等待集团编码赋值";
                  }
                  resultDataObjectDetailDO.setCode(groupCode);
               }else{
                  resultDataObjectDetailDO.setCode(code);
                  resultDataObjectDetailDO.setErrorid("0");
               }
               resultDataObjectDetailDO.setId(sourceOid);
               resultDataObjectDetailDO.setErrorid("0");
               resultDataObjectDetailDO.setMsg(msg);
               resultDataObjectDetailDOs.add(resultDataObjectDetailDO);
               //处理传送的数据中关键属性重复的,直接拿到已经申请到编码的数据编码直接将赋给关键属性重复的数据
               LinkedList<XMLResultDataObjectDetailDO> repeatDataObjectDetailDOS=handleApplyDataKeyAttrRepeat(keyAttrOkOidTORepeatOidMap,codeOidToSystemOidMap,needSaveCbo,isCodeOrGroupCode);
               resultDataObjectDetailDOs.addAll(repeatDataObjectDetailDOS);
            });
               /* }else{
                    needSaveCboList.stream().forEach(needSaveCbo->{
@@ -2174,6 +2233,13 @@
                    });
                }*/
            //是否调用集团接口申请接口
            if(isCodeOrGroupCode){
               if(!CollectionUtils.isEmpty(applyGroupCodeIdList)) {
                  this.sendApplyGroupcode(applyGroupCodeIdList, classifyFullInfo.getTopClassifyVO().getId(), sysIntegrationPushTypeEnum.ACCPET_APPCODE.getValue());
               }
            }
         }catch (Throwable e){
            e.printStackTrace();
            needSaveCboList.stream().forEach(needSaveCbo->{
@@ -2194,15 +2260,62 @@
      }
   }
   /***
    *给同一批申请编码存在关键属性的数据赋上一致编码
    * @param keyAttrOkOidTORepeatOidMap 一批申请数据关键属性一致的重复数据映射关系
    * @param codeOidToSystemOidMap
    * @param needSaveCbo
    * @param isCodeOrGroupCode
    */
   private LinkedList<XMLResultDataObjectDetailDO> handleApplyDataKeyAttrRepeat(Map<String,List<String>>keyAttrOkOidTORepeatOidMap,Map<String,String> codeOidToSystemOidMap,BaseModel needSaveCbo,boolean isCodeOrGroupCode){
      LinkedList<XMLResultDataObjectDetailDO> resultDataObjectDetailDOs=new LinkedList<>();
      String oid=needSaveCbo.getOid();
      if(keyAttrOkOidTORepeatOidMap.containsKey(oid)){
         List<String> repeatOidList= keyAttrOkOidTORepeatOidMap.get(oid);
         if(!CollectionUtils.isEmpty(repeatOidList)){
            String sourceNewOid=needSaveCbo.getOid();
            String sourceOid=sourceNewOid;
            if(codeOidToSystemOidMap.containsKey(oid)){
               sourceOid=codeOidToSystemOidMap.get(oid);
            }
            String code=StringUtils.isBlank(needSaveCbo.getId())?" ":needSaveCbo.getId();
            String groupCode=needSaveCbo.getData().getOrDefault("GROUPCODE"," ");
            String finalSourceOid = sourceOid;
            repeatOidList.stream().forEach(repeatOid->{
               if(codeOidToSystemOidMap.containsKey(repeatOid)){
                  XMLResultDataObjectDetailDO repeatresultDataObjectDetailDO=new XMLResultDataObjectDetailDO();
                  String repeatSourceOid=codeOidToSystemOidMap.get(repeatOid);
                  String repeatMsg="此数据与申请的编码数据id为【"+ finalSourceOid +"】的关键属性一致,则取相同编码";
                  if(isCodeOrGroupCode) {
                     if(StringUtils.isBlank(groupCode)){
                        repeatMsg="申请的编码类型为集团码,等待集团编码赋值";
                     }
                     repeatresultDataObjectDetailDO.setCode(groupCode);
                  }else{
                     repeatresultDataObjectDetailDO.setCode(code);
                  }
                  repeatresultDataObjectDetailDO.setId(repeatSourceOid);
                  repeatresultDataObjectDetailDO.setErrorid("0");
                  repeatresultDataObjectDetailDO.setMsg(repeatMsg);
                  resultDataObjectDetailDOs.add(repeatresultDataObjectDetailDO);
               }
            });
         }
      }
      return  resultDataObjectDetailDOs;
   }
   /***
    * 集成批量同步更新接口
    * @param codeClassifyVO;
    * @param dataObjectVO 数据信息
    * @param resultDataObjectDetailDOs 错误信息
    * @param isCodeOrGroupCode 是否更集团系统数据
    */
   @Transactional(rollbackFor = VciBaseException.class)
   @Override
   public void batchSyncEditDatas(CodeClassifyVO codeClassifyVO, DataObjectVO dataObjectVO, LinkedList<XMLResultDataObjectDetailDO> resultDataObjectDetailDOs) {
   public void batchSyncEditDatas(CodeClassifyVO codeClassifyVO, DataObjectVO dataObjectVO, LinkedList<XMLResultDataObjectDetailDO> resultDataObjectDetailDOs,boolean isCodeOrGroupCode) {
      String errorid="";
      String msg="";
      //查询分类和模板
@@ -2227,8 +2340,8 @@
      List<String> titleRowData = dataObjectVO.getColName();
      Map<String/**中文名称**/, String/**英文名称**/> attrNameIdMap = attrVOS.stream().collect(Collectors.toMap(s -> s.getName(), t -> t.getId().toLowerCase(Locale.ROOT), (o1, o2) -> o2));
      getFieldIndexMap(titleRowData, attrNameIdMap, fieldIndexMap);
      Map<String, String> cboOidMap = new HashMap<>();
      cboOidMap.put("id", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(codeDataMap.keySet().toArray(new String[0])) + ")");
      //Map<String, String> cboOidMap = new HashMap<>();
      //cboOidMap.put("id", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(codeDataMap.keySet().toArray(new String[0])) + ")");
      String tableName ="";
      try {
         R<BtmTypeVO> r = btmTypeClient.getAllAttributeByBtmId(templateVO.getBtmTypeId());
@@ -2258,15 +2371,26 @@
      sb.append(" select * from ");
      sb.append(tableName);
      sb.append(" where 1=1 ");
      sb.append(" id in (");
      sb.append(VciBaseUtil.toInSql(codeDataMap.keySet().toArray(new String[0])));
      sb.append(")");
      sb.append(" and lastr=1 and lastv=1" );
      if(isCodeOrGroupCode) {
         sb.append(" and ( groupcode in (");
         sb.append(VciBaseUtil.toInSql(codeDataMap.keySet().toArray(new String[0])));
         sb.append(")");
         sb.append(" or id in (");
         sb.append(VciBaseUtil.toInSql(codeDataMap.keySet().toArray(new String[0])));
         sb.append("))");
      }else{
         sb.append(" and id in (");
         sb.append(VciBaseUtil.toInSql(codeDataMap.keySet().toArray(new String[0])));
         sb.append(")");
      }
      List<Map<String,String>> dataMapList=commonsMapper.queryByOnlySqlForMap(sb.toString());
      List<ClientBusinessObject> cboList=   ChangeMapTOClientBusinessObjects(dataMapList);
      Map<String, ClientBusinessObject> codeSystemObjectMap = cboList.stream().filter(systeDataObject -> systeDataObject != null && StringUtils.isNotBlank(systeDataObject.getId())).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getId(), t -> t));
      Map<String, String> errorMap = new HashMap<>();
      List<CodeOrderDTO> codeOrderDTOList = new ArrayList<>();
      this.getCodeOrderDTOs(codeClassifyVO, templateVO, codeDataMap, codeSystemObjectMap, codeOrderDTOList, errorMap);
      this.getCodeOrderDTOs(codeClassifyVO, templateVO, codeDataMap, codeSystemObjectMap, codeOrderDTOList, errorMap,isCodeOrGroupCode);
      // List<CodeClassifyProcessTempVO> codeClassifyProcessTempVOS=codeClassifyProcessTempService.listProcessTemplate(templateVO.getOid(),"code_cls_flow_use_order");
      boolean isProcess=false;
      /**  if(!CollectionUtils.isEmpty(codeClassifyProcessTempVOS)){
@@ -2287,8 +2411,9 @@
         String dataStatus=cbo.getLcStatus();
         RowDatas rowData=codeDataMap.get(code);
         String status=rowData.getStatus();
         String lastModifier= rowData.getEditor();
         String operation=rowData.getOperation();
         if (cbo.getTs().compareTo(orderDTO.getTs())==0?true:false) {
         if (cbo.getTs().compareTo(orderDTO.getTs())==0?false:true) {
            // throw new VciBaseException("数据不是最新的,可能他人已经修改,请刷新后再试");
            errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"")+";数据不是最新的,可能他人已经修改,请刷新后再试");
         }
@@ -2296,20 +2421,20 @@
                throw new VciBaseException("数据不是{0}的状态,不允许修改", new String[]{CodeDefaultLC.EDITING.getText()});
            }*/
         if(operation.equals("update")) {
            //1. 判断必输项
            checkRequiredAttrOnOrder(templateVO, orderDTO, errorMap);
            //2.先注入,再组合,最后校验
            //1.先注入,再组合,最后校验
            switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO, errorMap);
            //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的
            //2.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的
            switchComponentAttrOnOrder(templateVO, orderDTO);
            //4.校验规则
            //3.校验规则
            checkVerifyOnOrder(templateVO, orderDTO, errorMap);
            //5.判断关键属性
            checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO, errorMap);
            //6.校验枚举的内容是否正确
            //4.校验枚举的内容是否正确
            checkEnumOnOrder(templateVO, orderDTO, errorMap);
            //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
            //5.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
            switchDateAttrOnOrder(templateVO, orderDTO);
            //6. 判断必输项
            checkRequiredAttrOnOrder(templateVO, orderDTO, errorMap);
            //7.判断关键属性
            checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO, errorMap);
            //默认的内容不能变,所以只需要拷贝自定义的相关属性即可
            copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true, errorMap);
            //企业码和集团码的不修改
@@ -2317,12 +2442,20 @@
            cbo.setName(orderDTO.getName());
            try {
               cbo.setAttributeValueWithNoCheck("description", orderDTO.getDescription());
               cbo.setAttributeValue("name", orderDTO.getName());
            //   cbo.setAttributeValue("name", orderDTO.getName());
               //  if(finalIsProcess){//在流程中不允许更改
               //     errorMap.put(code,errorMap.getOrDefault(code, errorMap.getOrDefault(code,"")+";数据"+code+"在流程中,不允许更改!"));
               //  }else{
               Date date=new Date();
               cbo.setLcStatus(status);
               cbo.setAttributeValue("lcstatus",status);
               cbo.setLastModifyTime(date);
               cbo.setLastModifier(lastModifier);
               cbo.setLastModifyTime(date);
               cbo.setAttributeValue("lastmodifier",lastModifier);
               cbo.setAttributeValue("lastmodifytime",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date));
               cbo.setTs(date);
               cbo.setAttributeValue("ts",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date));
               //  }
            } catch (VciBaseException e) {
               e.printStackTrace();
@@ -2330,7 +2463,7 @@
            List<CodeAllCode>newCodeAllCodeList= codeAllCodeService.selectByWrapper(Wrappers.<CodeAllCode>query().lambda().eq(CodeAllCode::getCreateCodeOid, cbo.getOid()));
            if (!CollectionUtils.isEmpty(newCodeAllCodeList)) {
               CodeAllCode codeCbo = codeAllCodeList.get(0);
               CodeAllCode codeCbo = newCodeAllCodeList.get(0);
               log.info("codeCbos code:" + codeCbo.getId());
               codeCbo.setLcStatus(status);
               codeAllCodeList.add(codeCbo);
@@ -2349,7 +2482,7 @@
               List<CodeAllCode>newCodeAllCodeList= codeAllCodeService.selectByWrapper(Wrappers.<CodeAllCode>query().lambda().eq(CodeAllCode::getCreateCodeOid, cbo.getOid()));
               log.info("codeCbos size:" + newCodeAllCodeList.size());
               if (!CollectionUtils.isEmpty(newCodeAllCodeList)) {
                  CodeAllCode codeCbo = codeAllCodeList.get(0);
                  CodeAllCode codeCbo = newCodeAllCodeList.get(0);
                  log.info("codeCbos code:" + codeCbo.getId());
                  codeCbo.setLcStatus(CodeDefaultLC.TASK_BACK.getValue());
                  codeAllCodeList.add(codeCbo);
@@ -2407,9 +2540,19 @@
         //存储数据
         try {
            engineService.updateBatchByBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId(),updateList);
            codeAllCodeService.saveBatch(codeAllCodeList);
            codeAllCodeService.saveOrUpdateBatch(codeAllCodeList);
            if(deleteList.size()>0) {
               commonsMapper.deleteByTaleAndOid(tableName, VciBaseUtil.array2String(deleteList.toArray(new String[]{})));
            }
            //是否调用集团接口申请接口
            if(isCodeOrGroupCode){
               List<String> IdList=resultDataObjectDetailDOs.stream().filter(xMLResultDataObjectDetailDO-> com.alibaba.cloud.commons.lang.StringUtils.isNotBlank(xMLResultDataObjectDetailDO.getId())).map(XMLResultDataObjectDetailDO::getId).distinct().collect(Collectors.toList());
               if(!CollectionUtils.isEmpty(IdList)) {
                  this.sendApplyGroupcode(IdList, classifyFullInfo.getTopClassifyVO().getBtmTypeId(),sysIntegrationPushTypeEnum.ACCPET_EDITCODE.getValue());
               }
            }
            errorid="0";
            msg="更新/状态更改/删除成功!";
@@ -2436,6 +2579,7 @@
         }
      }
   }
   /**
    * 校验属性是否为必输
    *
@@ -2457,6 +2601,7 @@
         });
      }
   }
   /**
    * 转换组合规则的值
    *
@@ -2503,6 +2648,7 @@
         });
      }
   }
   /**
    * 校验关键属性
    *
@@ -2531,29 +2677,55 @@
      });
      //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可
      if (!CollectionUtils.isEmpty(conditionMap)) {
         final String[] sql = {"select count(*) from " + VciBaseUtil.getTableName(classifyFullInfo.getTopClassifyVO().getBtmTypeId()) + " where 1 = 1 "};
         String tableName="";
         R<BtmTypeVO> r = btmTypeClient.getAllAttributeByBtmId(templateVO.getBtmTypeId());
         if(r.isSuccess()) {
            BtmTypeVO btmTypeVO = r.getData();
            if (btmTypeVO != null) {
               tableName = btmTypeVO.getTableName();
            }
         }
         if (StringUtils.isBlank(tableName)) {
            String errormsg="根据业务类型未查询到相关业务表";
            errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"")+errormsg);
            return;
         }
         //final String[] sql = {"select count(*) from " + tableName + " t where 1 = 1 "};
         final String[] sql = {"select t.id from " + tableName + " t where 1 = 1 "};
         conditionMap.forEach((key, value) -> {
            sql[0] += " and " + key + " = " + value;
            if(StringUtils.isBlank(value)||value.equals(QueryOptionConstant.ISNULL)){
               sql[0] += " and " + key + " is null ";
            }else{
               sql[0] += " and " + key + " = " + value;
            }
         });
         if (StringUtils.isNotBlank(orderDTO.getOid())) {
            //修改的时候,需要排除自己
            sql[0] += " and oid != '" + orderDTO.getOid() + "'";
            sql[0] += " and t.oid != '" + orderDTO.getOid() + "'";
         } else if (StringUtils.isNotBlank(orderDTO.getCopyFromVersion())) {
            sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'";
            sql[0] += " and t.oid != '" + orderDTO.getCopyFromVersion() + "'";
         }
         sql[0] += " and lastR = '1' and lastV = '1' ";
         if (commonsMapper.queryCountBySql(sql[0]) > 0) {
         // 不需要参与校验的规则oid
         String isParticipateCheckOids = classifyService.selectLeafByParentClassifyOid(classifyFullInfo.getTopClassifyVO().getOid(), classifyFullInfo.getCurrentClassifyVO().getOid());
         if(Func.isNotBlank(isParticipateCheckOids)){
            sql[0] += " and codeclsfid not in("+isParticipateCheckOids+")";
         }
         sql[0] += " and t.lastR = '1' and t.lastV = '1' ";
         List<String> repeatData = commonsMapper.selectList(sql[0]);
         if (!repeatData.isEmpty()) {
            String ruleInfoMsg = keyRuleVO == null ? "" : "查询规则:去除空格--{0},忽略大小写--{1},忽略全半角--{2},忽略全部空格--{3}";
            String[] objs = new String[]{trim ? "是" : "否", ignoreCase ? "是" : "否", ignoreWidth ? "是" : "否", trimAll ? "是" : "否"};
            String defaultValue=";根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。";
            String defaultValue=";根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了,数据的编号如下:"+repeatData.stream().collect(Collectors.joining(","))+"。请修正!。";
            String errormsg=defaultValue+ MessageFormat.format(ruleInfoMsg, objs);
            errorMap.put(orderDTO.getId(),errorMap.getOrDefault(orderDTO.getId(),"")+errormsg);
            // throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。" + ruleInfoMsg, objs);
         }
      }
   }
   /**
    * 校验枚举的内容
    *
@@ -2577,6 +2749,7 @@
         });
      }
   }
   /**
    * 转换时间的格式
    *
@@ -2638,10 +2811,10 @@
//               if (lifeCycleVO != null) {
//                  cbo.setLcStatus(lifeCycleVO.getStartStatus());
//               } else {
                  cbo.setLcStatus(CodeDefaultLC.EDITING.getValue());
               cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
//               }
            } else {
               cbo.setLcStatus(CodeDefaultLC.EDITING.getValue());
               cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
            }
         }
@@ -2669,6 +2842,7 @@
         orderDTO.getData().put(attrId, value);
      }
   }
   /**
    * 从编码申请信息对象上获取某个属性的值
    *
@@ -2688,6 +2862,7 @@
      }
      return value;
   }
   /**
    * 处理分类注入的信息
    *
@@ -2733,6 +2908,7 @@
         });
      }
   }
   /***
    *
    * @param codeClassifyVO
@@ -2743,13 +2919,19 @@
    * @param errorMap
    * @return
    */
   private void   getCodeOrderDTOs(CodeClassifyVO codeClassifyVO,CodeClassifyTemplateVO templateVO,Map<String ,RowDatas>codeDataMap,Map<String, ClientBusinessObject> codeSystemObjectMap,List<CodeOrderDTO> codeOrderDTOList,Map<String,String> errorMap){
      codeDataMap.keySet().forEach(code->{
         RowDatas rowDatas=codeDataMap.get(code);
         Map<String, String> data= rowDatas.getFiledValue();
   private void getCodeOrderDTOs(CodeClassifyVO codeClassifyVO,CodeClassifyTemplateVO templateVO,Map<String ,RowDatas>codeDataMap,Map<String, ClientBusinessObject> codeSystemObjectMap,List<CodeOrderDTO> codeOrderDTOList,Map<String,String> errorMap,boolean isCodeOrGroupCode){
      codeSystemObjectMap.keySet().forEach(code->{
         ClientBusinessObject sysDataObject= codeSystemObjectMap.get(code);
         if(isCodeOrGroupCode){
            code=sysDataObject.getAttributeValue("GROUPCODE");
            if(StringUtils.isBlank(code)){
               code=sysDataObject.getId();
            }
         }
         CodeOrderDTO orderDTO = new CodeOrderDTO();
         if(codeSystemObjectMap.containsKey(code)){
            ClientBusinessObject sysDataObject= codeSystemObjectMap.get(code);
         if(codeDataMap.containsKey(code)){
            RowDatas rowDatas=codeDataMap.get(code);
            Map<String, String> data= rowDatas.getFiledValue();
            orderDTO.setCodeClassifyOid(codeClassifyVO.getOid());//分类主键
            orderDTO.setOid(sysDataObject.getOid());//数据oid
            orderDTO.setLcStatus(rowDatas.getStatus());//状态
@@ -2823,7 +3005,7 @@
                  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())){
                     if(StringUtils.isNotBlank(secVO.getCodeSecLength())&&VciBaseUtil.getInt(length)>(VciBaseUtil.getInt(secVO.getCodeSecLength())+((secVO.getPrefixCode()+secVO.getSuffixCode()).length()))){
                        errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";码段宽度与系统中的编码规则不同" );
                        fined = true;
                        break;
@@ -2855,6 +3037,7 @@
         }
      });
   }
   /**
    * excel转换为cbo的对象
    * @param classifyFullInfo 分类的全部信息
@@ -2967,6 +3150,7 @@
      });
   }
   /**
    * excel转换为cbo的对象
    * @param classifyFullInfo 分类的全部信息
@@ -3001,7 +3185,7 @@
                  Integer userSecret = VciBaseUtil.getCurrentUserSecret();
                  cbo.setAttributeValue(SECRET_FIELD,String.valueOf((userSecret==null || userSecret ==0)? UserSecretEnum.NONE.getValue():userSecret));
               }
               cbo.setLcStatus(CodeDefaultLC.EDITING.getValue());
               cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
            }else{
               //此时还没有转换路径
               //cbo.setAttributeValue(CODE_FULL_PATH_FILED, childOidPathMap.getOrDefault(rowData.getData().getOrDefault(CODE_CLASSIFY_OID_FIELD,""),fullPath));
@@ -3016,6 +3200,7 @@
      });
   }
   /**
    * excel转换为cbo的对象
    * @param classifyFullInfo 分类的全部信息
@@ -3031,9 +3216,9 @@
                     String fullPath,boolean newCode){
      rowDataList.stream().forEach(rowData -> {
         ClientBusinessObject cbo=new ClientBusinessObject();
          DefaultAttrAssimtUtil.addDefaultAttrAssimt(cbo, classifyFullInfo.getTopClassifyVO().getBtmTypeId());
         DefaultAttrAssimtUtil.addDefaultAttrAssimt(cbo, classifyFullInfo.getTopClassifyVO().getBtmTypeId());
         rowData.getData().forEach((index,value)->{
            String field = fieldIndexMap.get(index);
               String field = fieldIndexMap.get(index);
            if (StringUtils.isBlank(field)) {
               throw new VciBaseException("第" + (index + 1) + "列的标题在系统中不存在");
            }
@@ -3058,7 +3243,7 @@
                  Integer userSecret = VciBaseUtil.getCurrentUserSecret();
                  cbo.setAttributeValue(SECRET_FIELD,String.valueOf((userSecret==null || userSecret ==0)? UserSecretEnum.NONE.getValue():userSecret));
               }
               cbo.setLcStatus(CodeDefaultLC.EDITING.getValue());
               cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
            }else{
               //此时还没有转换路径
               //cbo.setAttributeValue(CODE_FULL_PATH_FILED, childOidPathMap.getOrDefault(rowData.getData().getOrDefault(CODE_CLASSIFY_OID_FIELD,""),fullPath));
@@ -3104,6 +3289,7 @@
         }
      }
   }
   /**
    * 批量转换时间都为指定的格式
    * @param attrVOS 模板属性
@@ -3329,6 +3515,7 @@
      }
   }
   /**
    * 批量检查企业编码是否存在
    * @param templateVO 模板的显示对象
@@ -3390,6 +3577,7 @@
         });
      }
   }
   /***
    * 校验分类对应的模板信息
    * @param titleRowData
@@ -3473,6 +3661,7 @@
      }
      return codeClassifyTemplateVOList ;
   }
   /**
    * 从属性上获取参照的内容
    * @param attrVO 属性的信息
@@ -3534,6 +3723,7 @@
      }
      return showText;
   }
   /**
    * 处理枚举的显示对象
    * @param attrVOS 模板属性
@@ -3582,7 +3772,7 @@
    */
   private void batchCheckRequiredAttrOnOrder(CodeClassifyTemplateVO templateVO,List<ClientBusinessObject> cboList,Map<String,String> errorMap){
      Map<String, CodeClassifyTemplateAttrVO> requiredAttrMap = templateVO.getAttributes().stream().filter(s ->
         VciBaseUtil.getBoolean(s.getRequireFlag()) && StringUtils.isBlank(s.getComponentRule()) && StringUtils.isBlank(s.getClassifyInvokeLevel())//不能是组合的和分类注入的
         VciBaseUtil.getBoolean(s.getRequireFlag()) && StringUtils.isBlank(s.getComponentRule()) && (StringUtils.isBlank(s.getClassifyInvokeLevel())||s.getClassifyInvokeLevel().equals("none"))//不能是组合的和分类注入的
      ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      //与MdmEngineServiceImpl里面的checkRequiredAttrOnOrder 逻辑应该相似
      if(!CollectionUtils.isEmpty(requiredAttrMap)) {
@@ -3590,11 +3780,12 @@
         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);
               errorMap.put(rowIndex,errorMap.getOrDefault(rowIndex,"") + ";校验规则必填项不通过,如果有必填属性为空,则填【/】代替,有校验的属性为" + checkAttr);
            });
         }
      }
   }
   /**
    * 处理分类注入
    * @param attrVOS 模板属性
@@ -3624,7 +3815,8 @@
                     }
                  }
                  CodeClassifyFullInfoBO newClassifyFullInfo= classifyFullInfoMap.get(cbo.getAttributeValue(CODE_CLASSIFY_OID_FIELD));
                  List<CodeClassifyVO> classifyVOS = newClassifyFullInfo.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel()))).collect(Collectors.toList());
                  List<CodeClassifyVO> 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);
@@ -3656,7 +3848,7 @@
    * @param cboList 批量的数据
    */
   private CodeImportResultVO batchCheckKeyAttrOnOrder(CodeClassifyFullInfoBO classifyFullInfo, CodeClassifyTemplateVO templateVO,
                                          List<ClientBusinessObject> cboList) {
                                          List<ClientBusinessObject> cboList,Map<String,String> errorMap) {
      //与MdmEngineServiceImpl里的checkKeyAttrOnOrder相似
      //先获取关键属性的规则,也利用继承的方式
      CodeKeyAttrRepeatVO keyRuleVO = keyRuleService.getRuleByClassifyFullInfo(classifyFullInfo);
@@ -3683,7 +3875,9 @@
      //2.判断关键属性在系统里是否重复
      //因为数据量很大,所以得想办法并行
      //SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo();
      Map<String,List<BaseModel>> indexTODataMap=new HashMap<>();
      Map<String,List<BaseModel>> indexTODataMap=new ConcurrentHashMap<>();
      // 查询不需要参与关键属性校验的除自己以外的所有分类oid
      final String isParticipateCheckOids = classifyService.selectLeafByParentClassifyOid(classifyFullInfo.getTopClassifyVO().getOid(), classifyFullInfo.getCurrentClassifyVO().getOid());
      List<ClientBusinessObject> repeatDataMap = cboList.parallelStream().filter(cbo -> {
         //每行都得查询.如果其中出现了错误,我们就直接抛出异常,其余的显示
         //VciBaseUtil.setCurrentUserSessionInfo(sessionInfo);
@@ -3697,22 +3891,29 @@
            engineService.wrapperKeyAttrConditionMap(value, keyRuleVO, attrId, trim, ignoreCase, ignoreWidth, trimAll, conditionMap);
         });
         if (!CollectionUtils.isEmpty(ketAttrMap)) {
            // 添加不参与关键属性校验的分类oid判断
            if(Func.isNotBlank(isParticipateCheckOids)){
               conditionMap.put("t.codeclsfid",QueryOptionConstant.NOTIN+isParticipateCheckOids);
            }
            CodeTemplateAttrSqlBO sqlBO = engineService.getSqlByTemplateVO(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), templateVO, conditionMap, null);
            boolean isKeyCheck= commonsMapper.queryCountBySql(sqlBO.getSqlCount()) > 0;
            if(isKeyCheck){
               List<Map<String,String>> newDataList=  commonsMapper.queryByOnlySqlForMap(sqlBO.getSqlUnPage());
               //List<ClientBusinessObject> newCboList=   ChangeMapTOClientBusinessObjects(newDataList);
               List<BaseModel> newCboList=new ArrayList<>();
            List<String> repeatData = commonsMapper.selectList(sqlBO.getSqlId());
            if(!repeatData.isEmpty()){
               final List<Map<String,String>> newDataList = commonsMapper.queryByOnlySqlForMap(sqlBO.getSqlUnPage());
               //List<ClientBusinessObject> newCboList=ChangeMapTOClientBusinessObjects(newDataList);
               List<BaseModel> newCboList = new ArrayList<>();
               newDataList.stream().forEach(stringStringMap -> {
                  BaseModel baseModel=new BaseModel();
                  DefaultAttrAssimtUtil.copplyDefaultAttrAssimt(stringStringMap,baseModel);
                  newCboList.add(baseModel);
               });
               // 添加错误值
               String rowIndex = cbo.getAttributeValue(IMPORT_ROW_INDEX);
               errorMap.put(rowIndex, "重复的记录编号为:"+repeatData.stream().collect(Collectors.joining(",")));
               if(!CollectionUtils.isEmpty(newCboList)) {
                  indexTODataMap.put(cbo.getAttributeValue(IMPORT_ROW_INDEX), newCboList);
               }
            }
            return isKeyCheck;
            return !repeatData.isEmpty();
         }else{
            return false;
         }
@@ -3740,7 +3941,7 @@
         if(StringUtils.isBlank(classifyPath)){
            classifyPath = "#current#";
         }
         if ( !pathMap.containsKey(classifyPath)) {
         if (!pathMap.containsKey(classifyPath)) {
            String row_index = cbo.getAttributeValue(IMPORT_ROW_INDEX);
            errorMap.put(row_index,errorMap.getOrDefault(row_index,"") + ";分类路径不存在");
         } else {
@@ -3823,9 +4024,11 @@
            childOidPathMap.put(childPath.getOid(),thisClassifyPath);
         });
      }
      String path=classifyFullInfo.getCurrentClassifyVO().getId();
      //根据客户选择的分类路径未id,还是name确定路径拼接
      childOidPathMap.put(classifyFullInfo.getCurrentClassifyVO().getOid(),fullPath);
      return childOidPathMap;
   }
   /**
    * 获取导入的内容中关键属性重复的行号
@@ -3835,7 +4038,7 @@
    * @return 重复的行号
    */
   private void getSelfRepeatRowIndex(Map<String/**属性的编号**/, CodeClassifyTemplateAttrVO> ketAttrMap,
                                   List<ClientBusinessObject> dataList,CodeKeyAttrRepeatVO keyRuleVO,CodeImportResultVO resultVO){
                              List<ClientBusinessObject> dataList,CodeKeyAttrRepeatVO keyRuleVO,CodeImportResultVO resultVO){
      Set<String> selfRepeatRowIndexList = new CopyOnWriteArraySet<>();
      Map<String,List<String>> keyAttrOkOidTORepeatOidMap=new HashMap<>();
      boolean trimAll =keyRuleVO ==null?false: VciBaseUtil.getBoolean(keyRuleVO.getIgnoreallspaceflag());
@@ -3876,11 +4079,11 @@
         if(rowIndexKeyStringMap.containsValue(keyString) && StringUtils.isNotBlank(keyString)){
            selfRepeatRowIndexList.add(rowIndex);
            String okOid=okOidKeyStringMap.getOrDefault(keyString,"");
            if(StringUtils.isBlank(okOid)){
            if(StringUtils.isNotBlank(okOid)){
               List<String>newOidList=new ArrayList<>();
               newOidList.add(oid);
               if(keyAttrOkOidTORepeatOidMap.containsKey(okOid)){
                  List<String> oldOidList=   keyAttrOkOidTORepeatOidMap.get(okOid);
                  List<String> oldOidList = keyAttrOkOidTORepeatOidMap.get(okOid);
                  newOidList.addAll(oldOidList);
               }
@@ -3895,6 +4098,7 @@
      resultVO.setKeyAttrRepeatRowIndexList(selfRepeatRowIndexList);
      resultVO.setKeyAttrOkOidTORepeatOidMap(keyAttrOkOidTORepeatOidMap);
   }
   /**
    * excel的标题上获取字段所在的位置
    * @param titleRowData 标题的内容
@@ -3927,7 +4131,7 @@
         DefaultAttrAssimtUtil.copplyDefaultAttrAssimt(dataMap,clientBusinessObject);
         for (String key:dataMap.keySet()){
            Object value= dataMap.getOrDefault(key,"");
            clientBusinessObject.setAttributeValue(key,value.toString());
            clientBusinessObject.setAttributeValue(key.toLowerCase(Locale.ROOT),value==null?"":value.toString());
         }
         clientBusinessObjectList.add(clientBusinessObject);
      });
@@ -4009,6 +4213,7 @@
      codeClassifyDatas.addAll(newCodeImprotDataVO);
      log.info("222");
   }
   /***
    *  @param titleRowData
    * @param newTemplateVO
@@ -4054,7 +4259,8 @@
      codeImprotDataVO.setColNames(colNames);
      codeImprotDataVO.getDatas().add(filedValueMap);
   }
   /***
   /**
    * 正确错误数据redis缓存
    * @param uuid
    * @param templateVO
@@ -4355,4 +4561,18 @@
      }
   }
   /***
    * 申请集团编码
    * @param idList
    * @param btmName
    */
   public void sendApplyGroupcode(List<String> idList,String btmName,String operationType){
      String oids=VciBaseUtil.array2String(idList.toArray(new String[]{}));
      if(operationType.equals(sysIntegrationPushTypeEnum.ACCPET_APPCODE.getValue())) {
         mdmInterJtClient.applyGroupCode(oids,btmName);
      }else if(operationType.equals(sysIntegrationPushTypeEnum.ACCPET_EDITCODE)){
         mdmInterJtClient.receiveEditApply(oids,btmName);
      }
   }
}