田源
2023-12-01 504dcb79430e0010e6b443e1ae2ef7f35b86e1a7
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
@@ -1,5 +1,6 @@
package com.vci.ubcs.code.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -9,8 +10,10 @@
import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO;
import com.vci.ubcs.code.bo.CodeTemplateAttrSqlBO;
import com.vci.ubcs.code.constant.FrameWorkDefaultValueConstant;
import com.vci.ubcs.code.dto.CodeBZApplyDTO;
import com.vci.ubcs.code.dto.CodeDeleteBatchDTO;
import com.vci.ubcs.code.dto.CodeOrderDTO;
import com.vci.ubcs.code.dto.CodeOrderSecDTO;
import com.vci.ubcs.code.dto.datapush.BaseModelDTO;
import com.vci.ubcs.code.entity.*;
import com.vci.ubcs.code.enumpack.*;
@@ -22,6 +25,7 @@
import com.vci.ubcs.code.vo.pagemodel.UITablePageVO;
import com.vci.ubcs.code.vo.pagemodel.*;
import com.vci.ubcs.code.wrapper.BaseMdodelWrapper;
import com.vci.ubcs.code.wrapper.CodeAllcodeWrapper;
import com.vci.ubcs.flow.core.dto.FlowStatusDTO;
import com.vci.ubcs.flow.core.feign.IMDMIFlowAttrClient;
import com.vci.ubcs.flow.core.vo.ProcessStageAttrVO;
@@ -39,6 +43,8 @@
import com.vci.ubcs.starter.revision.model.TreeWrapperOptions;
import com.vci.ubcs.starter.revision.service.RevisionModelUtil;
import com.vci.ubcs.starter.util.MdmBtmTypeConstant;
import com.vci.ubcs.starter.util.SaveLogUtil;
import com.vci.ubcs.starter.util.SpecialCharacterConverter;
import com.vci.ubcs.starter.util.UBCSSqlKeyword;
import com.vci.ubcs.starter.web.constant.QueryOptionConstant;
import com.vci.ubcs.starter.web.constant.RegExpConstant;
@@ -59,12 +65,14 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.log.annotation.OperateLog;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
@@ -99,10 +107,65 @@
public class MdmEngineServiceImpl implements MdmEngineService {
   /**
    * 多线程方式批量执行开启线程池的总数
    */
   @Value("${batchadd.thread_num:10}")
   private Integer THREAD_NUM;
   /**
    * 单次sql的最多导入数量
    */
   @Value("${import.maxNum}")
   @Value("${batchadd.single_maxnum:200}")
   private Integer MAX_IMPORT_NUM;
   /**
    * 是否开启多线程方式导入历史数据
    */
   @Value("${batchadd.is_thread_import:false}")
   private boolean IS_THREAD_IMPORT;
   /***
    * 操作类型
    */
   @Value("${bzApply.operationType:operationType}")
   private String operationType;
   /***
    * 是否系列
    */
   @Value("${bzApply.isSeries:isSeries}")
   private String isSeries;
   /***
    *发布时间
    */
   @Value("${bzApply.releaseTime:releaseTime}")
   private String releaseTime;
   /***
    * 源标准号
    */
   @Value("${bzApply.oldCode:oldCode}")
   private String oldCode;
   /***
    * 系列流水
    */
   @Value("${bzApply.seriesFlow:seriesFlow}")
   private String seriesFlow;
   /***
    * 是否变更系列
    */
   @Value("${bzApply.isEditSeries:isEditSeries}")
   private String isEditSeries;
   /***
    * 控制是否写入值的码段名称
    */
   @Value("${bzApply.secName:系列号}")
   private String secName;
   /***
    * 控制是否写入值的码段名称
    */
   @Value("${bzApply.yearSecName:年代号}")
   private String yearSecName;
    /**
     * 模板的服务
@@ -153,13 +216,11 @@
    @Autowired
    private FormulaServiceImpl formulaService;
    /**
     * 对omd中提供的feign接口进行调用,以及处理相关逻辑
     */
    @Autowired
    ICodeReferBtmTypeService codeReferBtmTypeService;
    /**
     * 相似项查询规则
@@ -290,8 +351,15 @@
    */
   @Autowired
   private IMDMIFlowAttrClient imdmiFlowAttrClient;
//   @Autowired
//   private CodeOsbtmtypeMapper codeOsbtmtypeMapper;----
   //   @Autowired
   //   private CodeOsbtmtypeMapper codeOsbtmtypeMapper;
   /**
    * 日志保存工具类
    */
   @Autowired
   private SaveLogUtil saveLogUtil;
    /**
@@ -354,39 +422,52 @@
    @Transactional
    @Override
    public void changeStatus(BaseModelDTO baseModelDTO) {
        VciBaseUtil.alertNotNull(baseModelDTO, "数据信息", baseModelDTO.getOid(), "主键", baseModelDTO.getBtmname(), "业务类型", baseModelDTO.getLcStatus(), "目标状态");
        List<String> oids = VciBaseUtil.str2List(baseModelDTO.getOid());
        List<BaseModel> baseModels = new ArrayList<>();
        baseModels = selectByTypeAndOid(baseModelDTO.getBtmname(), baseModelDTO.getOid());
        if (baseModels.size() == 0) {
            throw new VciBaseException("未查询到相关数据。");
        }
        //还需要修改allCode的生命周期
        QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
        allCodeWrapper.eq("createcodebtm", baseModelDTO.getBtmname());
        allCodeWrapper.in("createcodeoid", oids);
        List<CodeAllCode> codeCbos = codeAllCodeService.selectByWrapper(allCodeWrapper);// 回收需要业务数据删除
        if (CodeDefaultLC.TASK_BACK.getValue().equals(baseModelDTO.getLcStatus())) {
            R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(baseModelDTO.getBtmname()));
            if (!listR.isSuccess() || listR.getData().size() == 0) {
                throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
            }
         // 直接删除,不给状态
         commonsMapper.deleteByTaleAndOid(listR.getData().get(0).getTableName(), VciBaseUtil.toInSql(baseModelDTO.getOid()));
         // commonsMapper.updateByTaleAndOid(listR.getData().get(0).getTableName(), VciBaseUtil.toInSql(baseModelDTO.getOid()),CodeDefaultLC.TASK_BACK.getValue());
        } else {
            for (BaseModel baseModel : baseModels) {
                baseModel.setLcStatus(baseModelDTO.getLcStatus());
            }
         R r = updateBatchByBaseModel(baseModelDTO.getBtmname(), baseModels);
         if(!r.isSuccess()){
            throw new VciBaseException("更新数据出错,重试!"+r.getMsg());
      try {
         VciBaseUtil.alertNotNull(baseModelDTO, "数据信息", baseModelDTO.getOid(), "主键", baseModelDTO.getBtmname(), "业务类型", baseModelDTO.getLcStatus(), "目标状态");
         List<String> oids = VciBaseUtil.str2List(baseModelDTO.getOid());
         List<BaseModel> baseModels = new ArrayList<>();
         baseModels = selectByTypeAndOid(baseModelDTO.getBtmname(), baseModelDTO.getOid());
         if (baseModels.size() == 0) {
            throw new VciBaseException("未查询到相关数据。");
         }
         //还需要修改allCode的生命周期
         QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
         allCodeWrapper.eq("createcodebtm", baseModelDTO.getBtmname());
         allCodeWrapper.in("createcodeoid", oids);
         List<CodeAllCode> codeCbos = codeAllCodeService.selectByWrapper(allCodeWrapper);// 回收需要业务数据删除
         if (CodeDefaultLC.TASK_BACK.getValue().equals(baseModelDTO.getLcStatus())) {
            R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(baseModelDTO.getBtmname()));
            if (!listR.isSuccess() || listR.getData().size() == 0) {
               throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
            }
            // 直接删除,不给状态
            commonsMapper.deleteByTaleAndOid(listR.getData().get(0).getTableName(), VciBaseUtil.toInSql(baseModelDTO.getOid()));
            // commonsMapper.updateByTaleAndOid(listR.getData().get(0).getTableName(), VciBaseUtil.toInSql(baseModelDTO.getOid()),CodeDefaultLC.TASK_BACK.getValue());
         } else {
            for (BaseModel baseModel : baseModels) {
               baseModel.setLcStatus(baseModelDTO.getLcStatus());
            }
            R r = updateBatchByBaseModel(baseModelDTO.getBtmname(), baseModels);
            if(!r.isSuccess()){
               throw new VciBaseException("更新数据出错,重试!"+r.getMsg());
            }
         }
         for (CodeAllCode codeCbo : codeCbos) {
            codeCbo.setLcStatus(baseModelDTO.getLcStatus());
         }
         codeAllCodeService.updateBatchById(codeCbos);
         //记录日志信息
         saveLogUtil.operateLog(
            CodeDefaultLC.getTextByValue(baseModelDTO.getLcStatus()),
            false,
            JSON.toJSONString(baseModels)
         );
      }catch (Exception e){
         // 插入更改日志记录
         saveLogUtil.operateLog(CodeDefaultLC.getTextByValue(baseModelDTO.getLcStatus()),true,e.getMessage());
         throw e;
      }
        for (CodeAllCode codeCbo : codeCbos) {
            codeCbo.setLcStatus(baseModelDTO.getLcStatus());
        }
        codeAllCodeService.updateBatchById(codeCbos);
    }
   /**
@@ -417,7 +498,7 @@
     * @param orderDTO 申请的信息,需要包含属性的内容和码段相关的内容
     * @return 返回编码的内容
     */
    private String addSaveCode(CodeOrderDTO orderDTO,boolean authUser) throws Exception {
   private String addSaveCode(CodeOrderDTO orderDTO, boolean authUser) throws Exception {
        VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键",
                orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键");
        CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
@@ -687,14 +768,16 @@
        //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可
        if (!CollectionUtils.isEmpty(conditionMap)) {
         conditionMap.put("CODETEMPLATEOID","'" + orderDTO.getTemplateOid() + "'");
         // TODO: 同一个库判重不需要区分分类oid
         // conditionMap.put("CODETEMPLATEOID","'" + orderDTO.getTemplateOid() + "'");
//         final String[] sql = {"select count(*) from " + VciBaseUtil.getTableName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()) + " t where 1 = 1 "};
            R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(classifyFullInfo.getTopClassifyVO().getBtmTypeId()));
//            String referTable = VciBaseUtil.getTableName(referVO.getReferType());
            if (!listR.isSuccess() || listR.getData().size() == 0) {
                throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
            }
            final String[] sql = {"select count(*) from " + listR.getData().get(0).getTableName() + " t where 1 = 1 "};
            //final String[] sql = {"select count(*) from " + listR.getData().get(0).getTableName() + " t where 1 = 1 "};
         final String[] sql = {"select id from " + listR.getData().get(0).getTableName() + " t where 1 = 1 "};
            conditionMap.forEach((key, value) -> {
            if(StringUtils.isBlank(value)||value.equals(QueryOptionConstant.ISNULL)) {
               sql[0] += " and " + key + " is null";
@@ -709,11 +792,17 @@
                sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'";
            }
            sql[0] += " and lastR = '1' and lastV = '1' ";
         // 获取不参与校验的分类oid
         String isParticipateCheckOids = classifyService.selectLeafByParentClassifyOid(classifyFullInfo.getTopClassifyVO().getOid(), classifyFullInfo.getCurrentClassifyVO().getOid());
         if(Func.isNotEmpty(isParticipateCheckOids)){
            sql[0] += " and codeclsfid not in(" + isParticipateCheckOids + ")";
         }
//         if (boService.queryCountBySql(sql[0], new HashMap<>()) > 0) {
            if (Integer.parseInt(commonsMapper.selectById(sql[0]).get(0)) > 0) {
         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 ? "是" : "否"};
                throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。" + ruleInfoMsg, objs);
                throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现该数据已经与系统中编号为"+repeatData.stream().collect(Collectors.joining(","))+"的数据重复。请修正!。" + ruleInfoMsg, objs);
            }
        }
    }
@@ -805,6 +894,255 @@
      return R.data("false");
   }
   /***
    *
    * @param codeBZApplyDTO 编码申请相关的信息,需要有属性和码段相关的信息
    * @return
    * @throws Exception
    */
   @Override
   public String addSaveBZ(CodeBZApplyDTO codeBZApplyDTO) throws Exception {
      return addSaveBZCode(codeBZApplyDTO,true);
   }
   /**
    * 标准申请和修订用
    *
    * @param codeBZApplyDTO 编码申请相关的信息,需要有属性和码段相关的信息
    * @param authUser
    * @return
    */
   public String addSaveBZCode(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
      String code="";
      VciBaseUtil.alertNotNull(codeBZApplyDTO.getCodeClassifyOid(), "主题库分类的主键",
         codeBZApplyDTO.getTemplateOid(), "模板的主键", codeBZApplyDTO.getCodeRuleOid(), "编码规则的主键");
      //操作类型
      if(StringUtils.isBlank(codeBZApplyDTO.getOperationType())){
         String operationTypeValue=codeBZApplyDTO.getData().get(operationType);
         codeBZApplyDTO.setOperationType(operationTypeValue);
      }
      //是否系列
      if(!codeBZApplyDTO.isSeries()){
         boolean isSeriesValue=codeBZApplyDTO.getData().get(isSeries).equals("true")?true:false;
         codeBZApplyDTO.setSeries(isSeriesValue);
      }
      //原标准号
      if(StringUtils.isBlank(codeBZApplyDTO.getOldCode())){
         String oldCodeValue=codeBZApplyDTO.getData().get(oldCode);
         codeBZApplyDTO.setOldCode(oldCodeValue);
      }
      //系列流水
      if(StringUtils.isBlank(codeBZApplyDTO.getSeriesFlow())){
         String seriesFlowValue=codeBZApplyDTO.getData().get(seriesFlow);
         codeBZApplyDTO.setSeriesFlow(seriesFlowValue);
      }
      //发布时间
      if(StringUtils.isBlank(codeBZApplyDTO.getReleaseTime())){
         String releaseTimeValue=codeBZApplyDTO.getData().get(releaseTime);
         codeBZApplyDTO.setReleaseTime(releaseTimeValue);
      }
      //是否变更系列
      if(!codeBZApplyDTO.isEditSeries()){
         boolean isEditSeriesValue=codeBZApplyDTO.getData().get(isEditSeries).equals("true")?true:false;
         codeBZApplyDTO.setEditSeries(isEditSeriesValue);
      }
      VciBaseUtil.alertNotNull(codeBZApplyDTO.getOperationType(), "操作类型",
         codeBZApplyDTO.isSeries(), "是否系列", codeBZApplyDTO.getReleaseTime(), "发布时间");
      if(codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_FORMULATE.getValue())){//制定
         code=   addsaveDataBZ(codeBZApplyDTO,authUser);
      }else if(codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_AMENDMENT.getValue())){//修订
         VciBaseUtil.alertNotNull(codeBZApplyDTO.getOldCode(), "源标准号");
         code=   amendmentDataBZ(codeBZApplyDTO,authUser);
         createChangeOder(code,codeBZApplyDTO,authUser);
      }else if(codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_EDIT.getValue())){//更改
         code=   amendmentDataBZ(codeBZApplyDTO,authUser);
         createChangeOder(code,codeBZApplyDTO,authUser);
      }else if(codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_DISABLE.getValue())) {//作废
         code=   amendmentDataBZ(codeBZApplyDTO,authUser);
         createChangeOder(code,codeBZApplyDTO,authUser);
      }else if(codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_AMENDMENT.getValue())) {//备查
         code=   amendmentDataBZ(codeBZApplyDTO,authUser);
         createChangeOder(code,codeBZApplyDTO,authUser);
      }
      return code;
   }
   /***
    * 修订
    * @param codeBZApplyDTO
    * @param authUser
    * @return
    */
   private String amendmentDataBZ(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
      CodeOrderDTO orderDTO=new CodeOrderDTO();
      BeanUtil.convert(codeBZApplyDTO,orderDTO);
      CodeRuleVO ruleVO = ruleService.getObjectHasSecByOid(codeBZApplyDTO.getCodeRuleOid());
      Map<String, CodeBasicSecVO> codeCodeBasicSecMap = ruleVO.getSecVOList().stream().filter(s -> StringUtils.isNotBlank(s.getOid())).collect(Collectors.toMap(s -> s.getOid().toLowerCase(Locale.ROOT), t -> t));
      VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键",
         orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键");
      String oldCode=codeBZApplyDTO.getOldCode();//源标准编码
      String releaseTime=codeBZApplyDTO.getReleaseTime();
      List<CodeOrderSecDTO> secDTOS=   orderDTO.getSecDTOList();
      LinkedList<CodeOrderSecDTO> newSecDTOList=new LinkedList<>();
      changeCodeOrderSecDTO(ruleVO,secDTOS,oldCode,newSecDTOList);//根据要求重新算码段码值
      if(!codeBZApplyDTO.isEditSeries()){//变更为标准
         //if(!codeBZApplyDTO.isSeries()){//如果是表准,则需要将系列好流水置为null
            //因为是标准则控制码段中的系列流水码段值为空
            newSecDTOList.stream().forEach(codeOrderSecDTO -> {
               if(codeCodeBasicSecMap.containsKey(codeOrderSecDTO.getSecOid())&&codeCodeBasicSecMap.get(codeOrderSecDTO.getSecOid()).getName().equals(secName)){
                  codeOrderSecDTO.setSecValue("");
               }
            });
         //}
         orderDTO.setSecDTOList(newSecDTOList);
         return createDataBZ(orderDTO,ruleVO,authUser);
      }else{//变更为系列.则按照逻辑去处理
         orderDTO.setSecDTOList(newSecDTOList);
         return createDataBZ(orderDTO,ruleVO,authUser);
      }
   }
   private String createDataBZ(CodeOrderDTO orderDTO,   CodeRuleVO ruleVO,boolean authUser) throws Exception {
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
      //1.判断规则中除了流水码段,是否有其他码段
      checkSecValueOnOrder(ruleVO, orderDTO);
      //2.判断必输项
      checkRequiredAttrOnOrder(templateVO, orderDTO);
      //3.先注入,再组合,最后校验
      switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO);
      //4.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的
      switchComponentAttrOnOrder(templateVO, orderDTO);
      //5.校验规则
      checkVerifyOnOrder(templateVO, orderDTO);
      //6.关键属性
      checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO);
      //7.枚举转换
      checkEnumOnOrder(templateVO, orderDTO);
      //8.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
      switchDateAttrOnOrder(templateVO, orderDTO);
      //9.生成编码的信息 ,初始化业务类型:缓存先取消,因为版本规则会出现变动的情况所以无法使用缓存
      // BaseModel cbo = createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmTypeId());
      BaseModel cbo = createBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId().trim().toLowerCase());
      //默认的属性都不用从前端拷贝
      //设置编码需要的默认属性的内容
      copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, false);
      cbo.setOid(VciBaseUtil.getPk());
      cbo.setRevisionOid(VciBaseUtil.getPk());
      cbo.setNameOid(VciBaseUtil.getPk());
      cbo.setCreateTime(new Date());
      cbo.setLastModifyTime(new Date());
      //cbo.setCreator(String.valueOf(AuthUtil.getUser().getUserId()));、
      if(authUser) {
         // 要求显示账号,所以做了更改
         cbo.setCreator(String.valueOf(AuthUtil.getUser().getAccount()));
         cbo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      }else{
         cbo.setCreator(orderDTO.getCreator());
         cbo.setLastModifier(orderDTO.getLastModifier());
      }
      cbo.setTenantId(AuthUtil.getTenantId());
      if(StringUtils.isNotBlank(orderDTO.getLcStatus())||StringUtils.isNotBlank(orderDTO.getData().get("lcStatus"))){
         cbo.setLcStatus(StringUtils.isNotBlank(orderDTO.getLcStatus())?orderDTO.getLcStatus():orderDTO.getData().get("lcStatus"));
      }
      //TODO:因为默认的属性都不拷贝,目前集团码叫name,并没有从DTO拷贝到cbo里。增加一个单独处理,以后再看要不要调整
      cbo.setName(orderDTO.getName() == null ? "" : orderDTO.getName());
      //end -- modify by lihang @20220407
      List<BaseModel> cboList = new ArrayList<>();
      //备注
      cbo.setDescription(orderDTO.getDescription());
      cboList.add(cbo);
      List<String> codeList = productCodeService.productCodeAndSaveDataBZ(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(), cboList);
      batchSaveSelectChar(templateVO, cboList);
      return codeList.size() > 0 ? codeList.get(0) : "";
   }
   /***
    * 根据编号获取码段码值
    * @param secDTOList
    */
   private void changeCodeOrderSecDTO(CodeRuleVO ruleVO,List<CodeOrderSecDTO> secDTOList,String oldCode,LinkedList<CodeOrderSecDTO> newSecDTOList) throws Exception {
      //还需要修改allCode的生命周期
      QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
      allCodeWrapper.in("id", VciBaseUtil.str2List(oldCode));
      Map<String,String> secDTOMap=secDTOList.stream().collect(Collectors.toMap(s -> s.getSecOid(), t -> t.getSecValue(),(o1, o2)->o2));
      List<CodeAllCode>codeAllcodeList=codeAllCodeService.selectByWrapper(allCodeWrapper);
      if(!CollectionUtils.isEmpty(codeAllcodeList)){
         String codeDelimit=codeAllcodeList.get(0).getCodeDelimit();
         String[] secValues=StringUtils.splitByWholeSeparatorPreserveAllTokens(codeDelimit,SERIAL_VALUE_SPACE);
         //VciBaseUtil.str2List()
         for (int i=0; i<ruleVO.getSecVOList().size();i++){
            CodeBasicSecVO codeBasicSecVO=ruleVO.getSecVOList().get(i);
            CodeOrderSecDTO codeOrderSecDTO=new CodeOrderSecDTO();
            String secValue=secValues[i];
            boolean isRoman=VciBaseUtil.isRoman(secValue);
            if(isRoman){
               continue;
            }
            if(secDTOMap.containsKey(codeBasicSecVO.getOid())){
               secValue=   secDTOMap.get(codeBasicSecVO.getOid())   ;
            }
            if(StringUtils.isNotBlank(secValue)) {
               codeOrderSecDTO.setSecOid(codeBasicSecVO.getOid());
               codeOrderSecDTO.setSecValue(secValue);
               newSecDTOList.add(codeOrderSecDTO);
            }
         }
      }else{
         throw new Exception("根据原标准编号,在系统中未查询到相应的信息");
      }
   }
   /***
    * 制定,则不需要产生更改单直接生成编码
    * @param codeBZApplyDTO
    * @param authUser
    * @return
    */
   private String addsaveDataBZ(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
      String code="";
      CodeOrderDTO orderDTO=new CodeOrderDTO();
      BeanUtil.convert(codeBZApplyDTO,orderDTO);
      CodeRuleVO ruleVO = ruleService.getObjectHasSecByOid(codeBZApplyDTO.getCodeRuleOid());
      Map<String, CodeBasicSecVO> codeCodeBasicSecMap = ruleVO.getSecVOList().stream().filter(s -> StringUtils.isNotBlank(s.getOid())).collect(Collectors.toMap(s -> s.getOid(), t -> t));
      //是否是标准,不是标准的不会去管
      if(!codeBZApplyDTO.isSeries()){
         //因为是标准则控制码段中的系列流水码段值为空
         orderDTO.getSecDTOList().stream().forEach(codeOrderSecDTO -> {
            if(codeCodeBasicSecMap.containsKey(codeOrderSecDTO.getSecOid())&&codeCodeBasicSecMap.get(codeOrderSecDTO.getSecOid()).getName().equals(secName)){
               codeOrderSecDTO.setSecValue("");
            }
         });
      }
      VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键",
         orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键");
      return createDataBZ(orderDTO,ruleVO,authUser);
   }
   /***
    * 更改单的创建
    * @param code
    * @param codeBZApplyDTO
    * @param authUser
    * @return
    */
   private String createChangeOder(String code,CodeBZApplyDTO codeBZApplyDTO, boolean authUser){
      return "";
   }
   /***
    * 集成可变码段申请接口
    * @param codeBZApplyDTO 申请的信息,需要包含属性的内容和码段相关的内容
    * @param    authUser 是否用登录用户记录
    * @return
    * @throws Exception
    */
   @Override
   public String addSaveBZCodeNotauthUser(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
      return   addSaveBZCode(codeBZApplyDTO,authUser);
   }
   /**
     * 封装关键属性的查询语句
     *
@@ -856,13 +1194,13 @@
                    //不忽略大小写、不去空、不忽略全半角
                    temp = "%s";
                }
                queryKey = String.format(temp, "t." + attrId);
                queryValue = String.format(temp, "'" + (trim ? value.trim() : value) + "'");
                queryKey = String.format(temp, "nvl("+ "t." + attrId +",'/')");
                queryValue = String.format(temp, "'" + (trim ? SpecialCharacterConverter.escapeSpecialCharacters(value.trim()):SpecialCharacterConverter.escapeSpecialCharacters(value)) + "'");
                conditionMap.put(queryKey, queryValue);
            } else {
            if(StringUtils.isNotBlank(value)) {
               //为空的时候不代表不校验,只是不去除相关的信息
               conditionMap.put("t." + attrId, "'" + value + "'");
               conditionMap.put("nvl("+ "t." + attrId+",'/')", "'" + SpecialCharacterConverter.escapeSpecialCharacters(value) + "'");
            }else{
               conditionMap.put("t." + attrId, QueryOptionConstant.ISNULL);
            }
@@ -962,10 +1300,10 @@
//                  cbo.setLcStatus("Editing");
////                  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());
                }
            }
@@ -980,7 +1318,6 @@
            logger.error("设置默认的属性的值错误", e);
        }
    }
    /**
     * 初始化业务类型
@@ -1780,7 +2117,6 @@
        }
    }
    /**
     * 根据模板属性生成相应的sql信息
     *
@@ -1946,6 +2282,8 @@
        String sqlHasPage = pageHelper.getLimit() > 0 ? ("select * from (select A.*,rownum RN from (" + sql + whereSubfixForPage) : sql;
        String sqlCount = "select count(1) from " + tableName + SPACE + "t" + SPACE + joinTableList.values().stream().collect(Collectors.joining(SPACE))
                + (StringUtils.isBlank(whereSql) ? "" : " where ") + whereSql;
      String sqlId = "select t.ID from " + tableName + SPACE + "t" + SPACE + joinTableList.values().stream().collect(Collectors.joining(SPACE))
         + (StringUtils.isBlank(whereSql) ? "" : " where ") + whereSql;
        CodeTemplateAttrSqlBO sqlBO = new CodeTemplateAttrSqlBO();
        sqlBO.setTableName(tableName);
        sqlBO.setJoinTable(joinTableList);
@@ -1954,9 +2292,9 @@
        sqlBO.setSqlHasPage(sqlHasPage);
        sqlBO.setSqlCount(sqlCount);
        sqlBO.setSqlUnPage(sql);
      sqlBO.setSqlId(sqlId);
        return sqlBO;
    }
    /**
     * 组合查询条件的sql
@@ -2136,7 +2474,6 @@
            return getSqlByValue(key, value, attrVOMap,btmType);
         }
      }*/
    }
    /**
@@ -2393,6 +2730,7 @@
        cbo.setLastModifyTime(new Date());
        cbo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      R r = updateBatchByBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), Collections.singletonList(cbo));
      if(!r.isSuccess()){
         throw new ServiceException(r.getMsg());
      }
@@ -2760,17 +3098,25 @@
        cbo.setName(orderDTO.getName());
        //数据的时候,编码是不变的
        cbo.setCreateTime(cbo.getCreateTime());
      cbo.setCreator(cbo.getCreator());
        cbo.setLastModifyTime(cbo.getLastModifyTime());
      cbo.setTenantId(AuthUtil.getTenantId());
      oldCbo.setLastV("0");
      oldCbo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      oldCbo.setLastModifyTime(new Date());
        try {
         // 修改版次号
         updateBatchByBaseModel(oldCbo.getBtmname(), Collections.singletonList(oldCbo));
         // 插入新的数据
            insertBatchByType(cbo.getBtmname(), Collections.singletonList(cbo));
        } catch (Exception vciError) {
            throw new VciBaseException("数据更改保存出错了", new String[0], vciError);
        }
         // 记录数据更改日志
         saveLogUtil.operateLog("数据更改",false, StringUtil.format("{}\n修改为:\n{}",JSON.toJSONString(Collections.singletonList(oldCbo)),JSON.toJSONString(Collections.singletonList(cbo))));
      } catch (Exception vciError) {
         // 记录数据更改报错时的日志
         saveLogUtil.operateLog("数据更改",true,vciError.getMessage());
         throw new VciBaseException("数据更改保存出错了", new String[0], vciError);
      }
        batchSaveSelectChar(templateVO, Collections.singletonList(cbo));
    }
@@ -3530,7 +3876,6 @@
     * @return 处理成功数据条数
     */
    @Override
   @Transactional(rollbackFor = Exception.class)
    public Integer insertBatchByType(String btmType, List<BaseModel> baseModels) {
        //使用传入的业务类型查询表
        R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(btmType));
@@ -3555,34 +3900,44 @@
                throw new VciBaseException("类型转换错误:" + e.toString());
            }
        });
      try {
         bactchExecuteInsert(listR.getData().get(0).getTableName(),maps);
      }catch (Exception e){
         throw new ServiceException("分批执行insert语句报错:"+e.getMessage());
      // 是否开启多线程执行插入语句
      if(IS_THREAD_IMPORT){
         try {
            threadBactchExecuteInsert(listR.getData().get(0).getTableName(),maps);
         }catch (Exception e){
            throw new ServiceException("分批执行insert语句报错:"+e.getMessage());
         }
      }else {
         bacthExcecuteInsert(listR.getData().get(0).getTableName(),maps);
      }
        return maps.size();
    }
   /**
    * 分批执行insert语句
    * 多线程方式分批执行insert语句
    * @param tableName
    * @param maps
    * @throws ServiceException
    */
   @Transactional(rollbackFor = Exception.class)
   void bactchExecuteInsert(String tableName, List<Map<String, String>> maps) throws ServiceException{
      ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池
   private void threadBactchExecuteInsert(String tableName, List<Map<String, String>> maps) throws ServiceException{
      ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUM); // 创建一个固定大小的线程池
      List<Map<String, String>> threadSafeMaps = new CopyOnWriteArrayList<>(maps);
      for (int i = 0; i < threadSafeMaps.size(); i += MAX_IMPORT_NUM) {
         final int startIndex = i;
         final int endIndex = Math.min(i + MAX_IMPORT_NUM, maps.size());
         executor.execute(() -> {
            List<Map<String, String>> subList = threadSafeMaps.subList(startIndex, endIndex);
            // 调用插入数据库的方法
            commonsMapper.insertByBaseModel(tableName, threadSafeMaps.get(0), subList);
         });
         final int endIndex = Math.min(i + MAX_IMPORT_NUM, threadSafeMaps.size());
         try {
            executor.execute(() -> {
               List<Map<String, String>> subList = threadSafeMaps.subList(startIndex, endIndex);
               // 调用插入数据库的方法
               commonsMapper.insertByBaseModel(tableName, threadSafeMaps.get(0), subList);
            });
         }catch (Throwable e){
            throw new ServiceException(e.getMessage());
         }
      }
      // 关闭线程池
      executor.shutdown();
      try {
@@ -3591,6 +3946,21 @@
      } catch (InterruptedException e) {
         // 处理异常
         throw new ServiceException("多线程方式执行批量插入时产生错误:"+e.getMessage());
      }
   }
   /**
    * 单线程方式分批执行
    * @param tableName
    * @param maps
    */
   private void bacthExcecuteInsert(String tableName, List<Map<String, String>> maps){
      for (int i = 0; i < maps.size(); i += MAX_IMPORT_NUM) {
         final int startIndex = i;
         final int endIndex = Math.min(i + MAX_IMPORT_NUM, maps.size());
         List<Map<String, String>> subList = maps.subList(startIndex, endIndex);
         // 调用插入数据库的方法
         commonsMapper.insertByBaseModel(tableName, maps.get(0), subList);
      }
   }
@@ -4153,7 +4523,7 @@
        toBo.setLastV(String.valueOf(1));
      // 数据升版不需要重新设置创建人,只对最后修改人做更新就可以了
        //toBo.setCreator(String.valueOf(AuthUtil.getUser().getUserId()));
        toBo.setCreateTime(new Date());
        toBo.setCreateTime(fromBo.getCreateTime());
        // toBo.setLastModifier(String.valueOf(AuthUtil.getUser().getUserId()));
      toBo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
        toBo.setLastModifyTime(new Date());
@@ -4183,7 +4553,8 @@
        toBo.setVersionSeq(Integer.valueOf(nextRevision.get("VERSIONSEQ").toString()));
        toBo.setVersionValue(nextRevision.get("VERSIONVAL").toString());
        toBo.setLctid(fromBo.getLctid());
        toBo.setLcStatus("Editing");
        //toBo.setLcStatus("Editing");
      toBo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
        toBo.setId(fromBo.getId());
        toBo.setName(fromBo.getName());
        toBo.setDescription(fromBo.getDescription());