ludc
2023-11-17 ac8e8998235f247365280d1a1632115c43b10037
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
@@ -66,9 +66,14 @@
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
@@ -81,7 +86,7 @@
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import static com.vci.ubcs.code.constant.FrameWorkLangCodeConstant.DATA_OID_NOT_EXIST;
@@ -97,12 +102,29 @@
@Service
public class MdmEngineServiceImpl implements MdmEngineService {
   /**
    * 多线程方式批量执行开启线程池的总数
    */
   @Value("${batchadd.thread_num:10}")
   private Integer THREAD_NUM;
   /**
    * 单次sql的最多导入数量
    */
   @Value("${batchadd.single_maxnum:200}")
   private Integer MAX_IMPORT_NUM;
   /**
    * 是否开启多线程方式导入历史数据
    */
   @Value("${batchadd.is_thread_import:false}")
   private boolean IS_THREAD_IMPORT;
    /**
     * 模板的服务
     */
    @Resource
    private CodeClstemplateServiceImpl templateService;
    private ICodeClstemplateService templateService;
    /**
     * 生成编码的服务
@@ -135,6 +157,11 @@
     */
    @Resource
    IEnumClient enumClient;
   /**
    * 版本规则服务
    */
   @Resource
   private IRevisionRuleClient revisionRuleClient;
    /**
     * 公式的服务
@@ -142,13 +169,11 @@
    @Autowired
    private FormulaServiceImpl formulaService;
    /**
     * 对omd中提供的feign接口进行调用,以及处理相关逻辑
     */
    @Autowired
    ICodeReferBtmTypeService codeReferBtmTypeService;
    /**
     * 相似项查询规则
@@ -172,17 +197,12 @@
     */
    @Autowired
    private IBtmTypeClient btmTypeClient;
    /**
     * 版本规则的服务
     */
    @Resource
    private IRevisionRuleClient revisionRuleClient;
//
    /**
     * 通用查询
     */
    @Resource
    CommonsMapper commonsMapper;
    private CommonsMapper commonsMapper;
    /**
     * 编码规则的服务
@@ -411,7 +431,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());
@@ -433,9 +453,9 @@
        checkEnumOnOrder(templateVO, orderDTO);
        //8.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
        switchDateAttrOnOrder(templateVO, orderDTO);
        //9.生成编码的信息
//      ClientBusinessObject cbo = boService.createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmtypeid());
        BaseModel cbo = createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmTypeId());
        //9.生成编码的信息 ,初始化业务类型:缓存先取消,因为版本规则会出现变动的情况所以无法使用缓存
        // BaseModel cbo = createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmTypeId());
      BaseModel cbo = createBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId().trim().toLowerCase());
      //默认的属性都不用从前端拷贝
      //设置编码需要的默认属性的内容
        copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, false);
@@ -681,14 +701,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";
@@ -703,11 +725,16 @@
                sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'";
            }
            sql[0] += " and lastR = '1' and lastV = '1' ";
         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);
            }
        }
    }
@@ -956,10 +983,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());
                }
            }
@@ -974,7 +1001,6 @@
            logger.error("设置默认的属性的值错误", e);
        }
    }
    /**
     * 初始化业务类型
@@ -1564,7 +1590,6 @@
        }
    }
    /**
     * 查询编码数据的列表
     *
@@ -1775,7 +1800,6 @@
        }
    }
    /**
     * 根据模板属性生成相应的sql信息
     *
@@ -1941,6 +1965,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 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);
@@ -1949,9 +1975,9 @@
        sqlBO.setSqlHasPage(sqlHasPage);
        sqlBO.setSqlCount(sqlCount);
        sqlBO.setSqlUnPage(sql);
      sqlBO.setSqlId(sqlId);
        return sqlBO;
    }
    /**
     * 组合查询条件的sql
@@ -2755,6 +2781,7 @@
        cbo.setName(orderDTO.getName());
        //数据的时候,编码是不变的
        cbo.setCreateTime(cbo.getCreateTime());
      cbo.setCreator(cbo.getCreator());
        cbo.setLastModifyTime(cbo.getLastModifyTime());
      cbo.setTenantId(AuthUtil.getTenantId());
      oldCbo.setLastV("0");
@@ -2964,7 +2991,7 @@
        wrapperData(dataList, templateVO, sqlBO.getSelectFieldList(), true);
        R<List<Map<String, String>>> result = R.data(Collections.singletonList(cbo));
        //我们要看是否不是升版的,升版的话,需要对比不相等的属性
        String copy = cbo.get("copyfromversion");
/*        String copy = cbo.get("copyfromversion");
//      if (StringUtils.isBlank(copy)) {
//         copy = cbo.getAttributeValue("copyfromversion");
//      }
@@ -2983,11 +3010,12 @@
                Map<String, String> difFieldMap = new HashMap<>();
                Map<String, String> finalOldData = oldData;
                cbo.forEach((key, value) -> {
                    String oldValue = finalOldData.getOrDefault(key, "");
                    if (value == null) {
               // 这儿oldmap中的全是大写,而cbo中的全是小写所以会拿不到只,这儿直接处理成小写拿不到就用大写拿
               String oldValue = String.valueOf(finalOldData.getOrDefault(key.toUpperCase(Locale.ROOT), finalOldData.getOrDefault(key, "")));
               if (value == null || value == "null") {
                        value = "";
                    }
                    if (oldValue == null) {
                    if (oldValue == null || oldValue == "null") {
                        oldValue = "";
                    }
                    if (!value.equalsIgnoreCase(oldValue)) {
@@ -2998,7 +3026,7 @@
                difFieldList.add(difFieldMap);
                result.setData(difFieldList);
            }
        }
        }*/
        return result;
    }
@@ -3356,7 +3384,6 @@
        return getTableDefineByTemplateVO(templateService.getObjectHasAttrByOid(templateOid));
    }
    /**
     * 使用模板显示对象转换为表格的信息(包含扩展的按钮)
     *
@@ -3453,6 +3480,7 @@
        }
        return uiInfoVO;
    }
    @Override
   public MdmUIInfoVO getFlowUIInfoByClassifyOid(String codeClassifyOid, String functionId,String templateId,String taskId,String modelKey){
//      MdmUIInfoVO uiInfoVO = getTableDefineByClassifyOid_v2(codeClassifyOid,templateId,taskId,modelKey);
@@ -3540,6 +3568,7 @@
      }).collect(Collectors.toSet());
      //将bean转为map,mybatis统一处理
        List<Map<String, String>> maps = new ArrayList<>();
        baseModels.stream().forEach(model -> {
            try {
                maps.add(VciBaseUtil.convertBean2Map(model,existFild));
@@ -3547,8 +3576,70 @@
                throw new VciBaseException("类型转换错误:" + e.toString());
            }
        });
        return commonsMapper.insertByBaseModel(listR.getData().get(0).getTableName(), maps.get(0), maps);
      // 是否开启多线程执行插入语句
      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语句
    * @param tableName
    * @param maps
    * @throws ServiceException
    */
   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, 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 {
         // 等待所有任务执行完成
         executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
      } 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);
      }
   }
   /**
    * 传入业务类型以及ID查询业务表数据是否重复
    *
@@ -4102,23 +4193,39 @@
        toBo.setNameOid(fromBo.getNameOid());
        toBo.setBtmname(fromBo.getBtmname());
        toBo.setLastR(String.valueOf(1));
      // 升版将FirstR修改为0
        toBo.setFirstR(String.valueOf(0));
        toBo.setFirstV(String.valueOf(1));
        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());
        toBo.setRevisionRule(fromBo.getRevisionRule());
        toBo.setVersionRule(fromBo.getVersionRule());R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(fromBo.getBtmname()));
        toBo.setVersionRule(fromBo.getVersionRule());
      //查询业务类型信息,可以获取到版本规则信息(revisionRuleId)
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(fromBo.getBtmname()));
        if (!listR.isSuccess() || listR.getData().size() == 0) {
            throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
        }
        Map<String, Object> nextRevision = commonsMapper.getNextRevision(listR.getData().get(0).getTableName(), fromBo.getNameOid());
        toBo.setRevisionSeq(Integer.parseInt(nextRevision.get("REVISIONSEQ").toString()));
        toBo.setRevisionValue(nextRevision.get("REVISIONVAL").toString());
        //Map<String, Object> nextRevision = commonsMapper.getNextRevision(listR.getData().get(0).getTableName(), fromBo.getNameOid());
      /*
         TODO:这是一个待后期完善的功能,目前实现方式是,先查询出当前数据的大版本规则,
            然后再查询业务表使用的规则的步长是多少然后计算出该升版为多少
      */
      Map<String, Object> nextRevision = commonsMapper.getCurrentRevision(listR.getData().get(0).getTableName(), fromBo.getNameOid());
      R<RevisionRuleVO> revisionRuleVOR = revisionRuleClient.selectById(listR.getData().get(0).getRevisionRuleId());
      String revisionval = nextRevision.get("REVISIONVAL").toString();
      // 未查询到版本规则,默认直接给大版本加一
      if(!revisionRuleVOR.isSuccess() || Func.isEmpty(revisionRuleVOR.getData())){
         revisionval = String.valueOf((Integer.parseInt(revisionval)+1));
      }else {
         revisionval = String.valueOf(Integer.parseInt(revisionval)+revisionRuleVOR.getData().getSerialStep());
      }
      toBo.setRevisionValue(revisionval);
      toBo.setRevisionSeq(Integer.parseInt(nextRevision.get("REVISIONSEQ").toString()));
        toBo.setVersionSeq(Integer.valueOf(nextRevision.get("VERSIONSEQ").toString()));
        toBo.setVersionValue(nextRevision.get("VERSIONVAL").toString());
        toBo.setLctid(fromBo.getLctid());