yuxc
2023-05-06 a6e6575bc3d668e14009ed0e931a376f1a4d86ff
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,779 @@
package com.vci.ubcs.code.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.corba.se.impl.orbutil.ObjectUtility;
import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO;
import com.vci.ubcs.code.dto.CodeOrderDTO;
import com.vci.ubcs.code.dto.datapush.BaseModelDTO;
import com.vci.ubcs.code.entity.CodeAllCode;
import com.vci.ubcs.code.entity.CodeOsbtmtypeEntity;
import com.vci.ubcs.code.entity.CodeRule;
import com.vci.ubcs.code.entity.CodeWupinEntity;
import com.vci.ubcs.code.enumpack.CodeDefaultLC;
import com.vci.ubcs.code.enumpack.CodeLevelTypeEnum;
import com.vci.ubcs.code.enumpack.CodeSecTypeEnum;
import com.vci.ubcs.code.mapper.CodeAllCodeMapper;
import com.vci.ubcs.code.mapper.CodeOsbtmtypeMapper;
import com.vci.ubcs.code.mapper.CodeRuleMapper;
import com.vci.ubcs.code.service.*;
import com.vci.ubcs.code.vo.CodeClstempattrVO;
import com.vci.ubcs.code.vo.CodeClstemplateVO;
import com.vci.ubcs.code.vo.CodeKeyattrrepeatVO;
import com.vci.ubcs.code.vo.pagemodel.CodeBasicSecVO;
import com.vci.ubcs.code.vo.pagemodel.CodeClassifyVO;
import com.vci.ubcs.code.vo.pagemodel.CodeRuleVO;
import com.vci.ubcs.omd.entity.Dict;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.revision.model.BaseModel;
import com.vci.ubcs.starter.web.enumpck.UserSecretEnum;
import com.vci.ubcs.starter.web.pagemodel.KeyValue;
import com.vci.ubcs.starter.web.toolmodel.DateConverter;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import com.vci.ubcs.starter.web.util.VciDateUtil;
import com.vci.ubcs.starter.web.util.VciQueryWrapperForDO;
import com.vci.ubcs.starter.web.util.WebUtil;
import com.vci.ubcs.system.entity.DictBiz;
import com.vci.ubcs.system.feign.IDictBizClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
/**
 * ä¸»æ•°æ®å¼•擎服务
 *
 * @author weidy
 * @date 2022-2-22
 */
@Service
public class MdmEngineServiceImpl extends ServiceImpl<CodeAllCodeMapper, CodeAllCode> implements MdmEngineService {
   /**
    * æ¨¡æ¿çš„æœåŠ¡
    */
   @Resource
   private CodeClstemplateServiceImpl templateService;
   /**
    * æ¨¡æ¿çš„æœåŠ¡
    */
   @Resource
   private CodeOsbtmtypeMapper codeOsbtmtypeMapper;
   /**
    * ç”Ÿæˆç¼–码的服务
    */
   @Resource
   private MdmProductCodeService productCodeService;
   /**
    * å­—典的服务
    */
   @Resource
   IDictBizClient iDictBizClient;
   /**
    * ç¼–码规则的服务
    */
   @Autowired
   private ICodeRuleService ruleService;
   /**
    * åˆ†ç±»çš„æœåŠ¡
    */
   @Resource
   private ICodeClassifyService classifyService;
   /**
    * å…³é”®å±žæ€§çš„配置
    */
   @Autowired
   private ICodeKeyattrrepeatService keyRuleService;
   /**
    * æ—¥å¿—
    */
   private Logger logger = LoggerFactory.getLogger(getClass());
//   @Autowired
//   private CodeOsbtmtypeMapper codeOsbtmtypeMapper;
   /**
    * ä½¿ç”¨åˆ†ç±»çš„主键获取可以使用的模板对象
    *
    * @param codeClassifyOid åˆ†ç±»çš„主键
    * @return æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡
    */
   @Override
   public CodeClstemplateVO getUsedTemplateByClassifyOid(String codeClassifyOid) {
      return getUsedTemplateByClassifyOid(codeClassifyOid, true);
   }
   /**
    * ä½¿ç”¨åˆ†ç±»çš„主键获取可以使用的模板对象
    *
    * @param codeClassifyOid åˆ†ç±»çš„主键
    * @param hasAttr         åŒ…含属性
    * @return æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡
    */
   @Override
   public CodeClstemplateVO getUsedTemplateByClassifyOid(String codeClassifyOid, boolean hasAttr) {
      List<CodeClstemplateVO> templateVOs = templateService.listReleaseTemplateByClassifyOid(codeClassifyOid, hasAttr);
      return templateVOs.get(templateVOs.size() - 1);
   }
   /**
    * èŽ·å–æžšä¸¾çš„ä¸‹æ‹‰é€‰é¡¹
    *
    * @param attrVO æ¨¡æ¿å±žæ€§çš„对象
    * @return ä¸‹æ‹‰é€‰é¡¹
    */
   @Override
   public List<KeyValue> listComboboxItems(CodeClstempattrVO attrVO) {
      List<KeyValue> comboboxKVs = null;
      if (StringUtils.isNotBlank(attrVO.getEnumstring())) {
         comboboxKVs = JSONObject.parseArray(attrVO.getEnumstring(), KeyValue.class);
      } else {
//         comboboxKVs = enumService.getEnum(attrVO.getEnumid());
//          Dict dict = new Dict();
//         dict.setParentId(Long.valueOf(attrVO.getEnumid()));
         R<List<DictBiz>> list = iDictBizClient.getList(attrVO.getEnumid());
         if(list.isSuccess()){
            for (DictBiz datum : list.getData()) {
               KeyValue keyValue = new KeyValue();
               keyValue.setKey(datum.getDictKey());
               keyValue.setValue(datum.getDictValue());
               comboboxKVs.add(keyValue);
            }
         }
      }
      return comboboxKVs;
   }
   /**
    * ä¿®æ”¹çŠ¶æ€
    *
    * @param baseModelDTO æ•°æ®ä¼ è¾“对象
    */
   @Override
   public void changeStatus(BaseModelDTO baseModelDTO) {
      VciBaseUtil.alertNotNull(baseModelDTO, "数据信息", baseModelDTO.getOid(), "主键", baseModelDTO.getBtmname(), "业务类型", baseModelDTO.getLcStatus(), "目标状态");
      List<String> oids = VciBaseUtil.str2List(baseModelDTO.getOid());
//      List<ClientBusinessObject> cboList = boService.selectCBOByOidCollection(oids, baseModelDTO.getBtmname());
      //插个点 ä¸šåŠ¡ç±»åž‹å®ŒæˆåŽéœ€è¦ä¿®æ”¹
      QueryWrapper<CodeOsbtmtypeEntity> wrapper = new QueryWrapper<>();
      wrapper.eq("BTMNAME",baseModelDTO.getBtmname());
      wrapper.in("OID",oids);
      List<CodeOsbtmtypeEntity> cboList = codeOsbtmtypeMapper.selectList(wrapper);
      //还需要修改allCode的生命周期
//      Map<String, String> conditionMap = new HashMap<>();
      QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
      allCodeWrapper.eq("createcodebtm",baseModelDTO.getBtmname());
      allCodeWrapper.in("createcodeoid",oids);
//      conditionMap.put("createcodeoid", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(oids.toArray(new String[0])) + ")");
//      conditionMap.put("createcodebtm", baseModelDTO.getBtmname());
      List<CodeAllCode> codeCbos = baseMapper.selectList(allCodeWrapper);
//      List<ClientBusinessObject> codeCbos = boService.queryCBO(MdmBtmTypeConstant.CODE_ALL_CODE, conditionMap);
      // å›žæ”¶éœ€è¦ä¸šåŠ¡æ•°æ®åˆ é™¤
//      if (CodeDefaultLC.TASK_BACK.getValue().equals(baseModelDTO.getLcStatus())) {
////         BatchCBO batchCBO = new BatchCBO();
////         batchCBO.getDeleteCbos().addAll(cboList);
//         codeOsbtmtypeMapper.deleteBatchIds(cboList);
////         boService.persistenceBatch(batchCBO);
//      } else {
//         lifeCycleService.transCboStatus(cboList, baseModelDTO.getLcStatus());
//      }
//      lifeCycleService.transCboStatus(codeCbos, baseModelDTO.getLcStatus());
   }
   /**
    * ç”³è¯·å•一编码
    *
    * @param orderDTO ç”³è¯·çš„信息,需要包含属性的内容和码段相关的内容
    * @return è¿”回编码的内容
    */
   @Override
   public String addSaveCode(CodeOrderDTO orderDTO) {
      VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键",
         orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键");
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      CodeClstemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
      CodeRuleVO ruleVO = ruleService.getObjectHasSecByOid(orderDTO.getCodeRuleOid());
      //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.生成编码的信息
//      ClientBusinessObject cbo = boService.createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmtypeid());
//      CodeWupinEntity cbo = createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmtypeid());
//      //默认的属性都不用从前端拷贝
//      //设置编码需要的默认属性的内容
//      copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, false);
//      //TODO:因为默认的属性都不拷贝,目前集团码叫name,并没有从DTO拷贝到cbo里。增加一个单独处理,以后再看要不要调整
//      cbo.setName(orderDTO.getName() == null ? "" : orderDTO.getName());
//      //end -- modify by lihang @20220407
//      List<CodeWupinEntity> cboList = new ArrayList<>();
//
//      //备注
//      cbo.setDescription(orderDTO.getDescription());
//
//      cboList.add(cbo);
//      List<String> codeList = productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(),cboList);
////      batchSaveSelectChar(templateVO, cboList);
//      return codeList.size() > 0 ? codeList.get(0) : "";
      return null;
   }
   /**
    * å¤„理分类注入的信息
    *
    * @param templateVO         æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡ï¼Œå¿…须要后模板的属性
    * @param classifyFullInfoBO åˆ†ç±»çš„全路径
    * @param orderDTO           ç¼–码申请的信息
    */
   private void switchClassifyLevelOnOrder(CodeClstemplateVO templateVO, CodeClassifyFullInfoBO classifyFullInfoBO, CodeOrderDTO orderDTO) {
      Map<String,CodeClstempattrVO> classifyAttrVOMap = templateVO.getAttributes().stream().filter(
         s -> StringUtils.isNotBlank(s.getClassifyinvokeattr()) && StringUtils.isNotBlank(s.getClassifyinvokelevel())
      ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      if (classifyFullInfoBO.getTopClassifyVO() == null) {
         //需要重新查询一下,因为这个是指定的分类进来的
      }
      if (!CollectionUtils.isEmpty(classifyAttrVOMap)) {
         classifyAttrVOMap.forEach((attrId, attrVO) -> {
            //分类注入的编号或者名称,
            //层级包含指定层和最小层
            CodeClassifyVO classifyVO = null;
            if (!CodeLevelTypeEnum.MIN.getValue().equalsIgnoreCase(attrVO.getClassifyinvokelevel()) && !"min".equalsIgnoreCase(attrVO.getClassifyinvokelevel())) {
               //指定了层级的
               //注意,因为查询上级分类出来的层级是倒序的,即顶层节点是最大的值
               List<CodeClassifyVO> classifyVOS = classifyFullInfoBO.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel()))).collect(Collectors.toList());
               int level = VciBaseUtil.getInt(attrVO.getClassifyinvokelevel());
               if (classifyVOS.size() >= level && level > 0) {
                  classifyVO = classifyVOS.get(level - 1);
               }
            } else {
               //当前的分类
               classifyVO = classifyFullInfoBO.getCurrentClassifyVO();
            }
            if (classifyVO == null) {
               //说明层级有误
               orderDTO.getData().put(attrId, "分类树上没有层级[" + attrVO.getClassifyinvokelevel() + "]");
               // classifyVO = classifyFullInfoBO.getCurrentClassifyVO();
            } else {
               Map<String, String> classifyDataMap = VciBaseUtil.objectToMapString(classifyVO);
               String value = classifyDataMap.getOrDefault(attrVO.getClassifyinvokeattr(), "");
               orderDTO.getData().put(attrId, value);
            }
         });
      }
   }
   /**
    * åˆ¤æ–­ç¼–码的码段是否输入或者选择了码值
    *
    * @param ruleVO   è§„则的显示对象
    * @param orderDTO ç¼–码申请的内容
    */
   @Override
   public void checkSecValueOnOrder(CodeRuleVO ruleVO, CodeOrderDTO orderDTO) {
      List<String> unSerialSecOidList = ruleVO.getSecVOList().stream().filter(
         s -> !(CodeSecTypeEnum.CODE_SERIAL_SEC.getValue().equalsIgnoreCase(s.getSecType())
            || CodeSecTypeEnum.CODE_ATTR_SEC.getValue().equalsIgnoreCase(s.getSecType())
            || CodeSecTypeEnum.CODE_DATE_SEC.getValue().equalsIgnoreCase(s.getSecType())
            || CodeSecTypeEnum.CODE_LEVEL_SEC.getValue().equalsIgnoreCase(s.getSecType())
            || VciBaseUtil.getBoolean(s.getNullableFlag()))
      ).map(CodeBasicSecVO::getOid).collect(Collectors.toList());
      if (!CollectionUtils.isEmpty(unSerialSecOidList)) {
         if (CollectionUtils.isEmpty(orderDTO.getSecDTOList())) {
            throw new VciBaseException("非流水码段(或者必输码段)必须要输入(或选择)码值");
         }
         if (orderDTO.getSecDTOList().stream().anyMatch(s -> !unSerialSecOidList.contains(s.getSecOid())
            && StringUtils.isBlank(s.getSecValue()))) {
            throw new VciBaseException("非流水码段(或者必输码段)必须要输入(或选择)码值");
         }
      }
   }
   /**
    * æ ¡éªŒå±žæ€§æ˜¯å¦ä¸ºå¿…输
    *
    * @param templateVO æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡ï¼Œéœ€è¦åŒ…含模板属性
    * @param orderDTO   ç¼–码申请的信息
    */
   private void checkRequiredAttrOnOrder(CodeClstemplateVO templateVO, CodeOrderDTO orderDTO) {
      Map<String, CodeClstempattrVO> requiredAttrMap = templateVO.getAttributes().stream().filter(
            s -> VciBaseUtil.getBoolean(s.getRequireflag()) && StringUtils.isBlank(s.getComponentrule())
               && StringUtils.isBlank(s.getClassifyinvokeattr()))
         .collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      if (!CollectionUtils.isEmpty(requiredAttrMap)) {
         requiredAttrMap.forEach((attrId, attrVO) -> {
            //只有企业编码,状态,备注,模板主键,分类主键这几个是固定的,其余都是自行配置的
            if (StringUtils.isBlank(getValueFromOrderDTO(orderDTO, attrId))) {
               throw new VciBaseException("属性【{0}】必须要输入(选择)内容", new String[]{attrVO.getName()});
            }
         });
      }
   }
   /**
    * ä»Žç¼–码申请信息对象上获取某个属性的值
    *
    * @param orderDTO ç¼–码申请对象
    * @param attrId   å±žæ€§çš„编号
    * @return å€¼
    */
   private String getValueFromOrderDTO(CodeOrderDTO orderDTO, String attrId) {
      attrId = attrId.toLowerCase(Locale.ROOT);
      String value = null;
      if (VciQueryWrapperForDO.BASIC_FIELD_MAP.containsKey(attrId)) {
         value = WebUtil.getStringValueFromObject(WebUtil.getValueFromField(WebUtil.getFieldForObject(attrId, orderDTO.getClass()).getName(), orderDTO));
      } else {
         //说明是自行配置的
         //前端必须要传递小写的属性
         value = orderDTO.getData().getOrDefault(attrId, "");
      }
      return value;
   }
   /**
    * è½¬æ¢ç»„合规则的值
    *
    * @param templateVO æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡ï¼Œéœ€è¦åŒ…含模板属性
    * @param orderDTO   ç¼–码申请的信息
    */
   private void switchComponentAttrOnOrder(CodeClstemplateVO templateVO, CodeOrderDTO orderDTO) {
      Map<String, CodeClstempattrVO> compAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getComponentrule())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      if (!CollectionUtils.isEmpty(compAttrVOMap)) {
         Map<String, String> dataMap = WebUtil.objectToMapString(orderDTO);
         Map<String, String> dataLowMap = new HashMap<>();
         if (!CollectionUtils.isEmpty(dataMap)) {
            dataMap.forEach((key, value) -> {
               dataLowMap.put(key.toLowerCase(Locale.ROOT), value);
            });
         }
         dataLowMap.putAll(orderDTO.getData());
         compAttrVOMap.forEach((attrId, attrVO) -> {
//            dataLowMap.put(attrId, formulaService.getValueByFormula(dataLowMap, attrVO.getComponentrule()));
         });
         dataLowMap.forEach((key, value) -> {
            setValueToOrderDTO(orderDTO, key, value);
         });
      }
   }
   /**
    * è®¾ç½®æ–°çš„值到申请对象上
    *
    * @param orderDTO ç¼–码申请对象
    * @param attrId   å±žæ€§çš„编号
    * @param value    å€¼
    */
   private void setValueToOrderDTO(CodeOrderDTO orderDTO, String attrId, String value) {
      attrId = attrId.toLowerCase(Locale.ROOT);
      if (VciQueryWrapperForDO.BASIC_FIELD_MAP.containsKey(attrId)) {
         WebUtil.setValueToField(WebUtil.getFieldForObject(attrId, orderDTO.getClass()).getName(), orderDTO, value);
      } else {
         orderDTO.getData().put(attrId, value);
      }
   }
   /**
    * æ ¡éªŒæ­£åˆ™è¡¨è¾¾å¼æ˜¯å¦æ­£ç¡®
    *
    * @param templateVO æ¨¡æ¿çš„信息,必须包含属性的内容
    * @param orderDTO   ç¼–码申请的相关的信息
    */
   private void checkVerifyOnOrder(CodeClstemplateVO templateVO, CodeOrderDTO orderDTO) {
      Map<String, CodeClstempattrVO> verifyAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getVerifyrule())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      if (!CollectionUtils.isEmpty(verifyAttrVOMap)) {
         verifyAttrVOMap.forEach((attrId, attrVO) -> {
            String value = getValueFromOrderDTO(orderDTO, attrId);
            if (StringUtils.isNotBlank(value) && !value.matches(attrVO.getVerifyrule())) {
               //校验正则表达式
               throw new VciBaseException("属性[{0}]的值不符合校验规则的要求", new String[]{attrVO.getName()});
            }
         });
      }
   }
   /**
    * æ ¡éªŒå…³é”®å±žæ€§
    *
    * @param classifyFullInfo åˆ†ç±»çš„全部信息
    * @param templateVO       æ¨¡æ¿çš„内容,必须包含模板属性
    * @param orderDTO         ç¼–码申请的相关的信息
    */
   private void checkKeyAttrOnOrder(CodeClassifyFullInfoBO classifyFullInfo, CodeClstemplateVO templateVO, CodeOrderDTO orderDTO) {
      //先获取关键属性的规则,也利用继承的方式
      CodeKeyattrrepeatVO keyRuleVO = keyRuleService.getRuleByClassifyFullInfo(classifyFullInfo);
      //注意的是keyRuleVO可能为空,表示不使用规则控制
      //获取所有的关键属性
      Map<String, CodeClstempattrVO> ketAttrMap = templateVO.getAttributes().stream().filter(s -> VciBaseUtil.getBoolean(s.getKeyattrflag())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      Map<String, String> conditionMap = new HashMap<>();
      boolean trimAll = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnoreallspaceflag());
      //全部去空的优先级大于去空
      boolean trim = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorespaceflag());
      boolean ignoreCase = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorecaseflag());
      boolean ignoreWidth = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorewidthflag());
      ketAttrMap.forEach((attrId, attrVO) -> {
         String value = getValueFromOrderDTO(orderDTO, attrId);
         if (value == null) {
            value = "";
         }
//         wrapperKeyAttrConditionMap(value, keyRuleVO, attrId, trim, ignoreCase, ignoreWidth, trimAll, conditionMap);
      });
      //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可
//      if (!CollectionUtils.isEmpty(conditionMap)) {
//         final String[] sql = {"select count(*) from " + VciBaseUtil.getTableName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()) + " t where 1 = 1 "};
//         conditionMap.forEach((key, value) -> {
//            sql[0] += " and " + key + " = " + value;
//         });
//         if (StringUtils.isNotBlank(orderDTO.getOid())) {
//            //修改的时候,需要排除自己
//            sql[0] += " and oid != '" + orderDTO.getOid() + "'";
//         } else if (StringUtils.isNotBlank(orderDTO.getCopyFromVersion())) {
//            sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'";
//         }
//         sql[0] += " and islastR = '1' and islastV = '1' ";
//         if (boService.queryCountBySql(sql[0], new HashMap<>()) > 0) {
//            String ruleInfoMsg = keyRuleVO == null ? "" : "查询规则:去除空格--{0},忽略大小写--{1},忽略全半角--{2},忽略全部空格--{3}";
//            String[] objs = new String[]{trim ? "是" : "否", ignoreCase ? "是" : "否", ignoreWidth ? "是" : "否", trimAll ? "是" : "否"};
//            throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。" + ruleInfoMsg, objs);
//         }
//      }
   }
   /**
    * å°è£…关键属性的查询语句
    *
    * @param value        å½“前的值
    * @param keyRuleVO    å…³é”®å±žæ€§çš„æŽ§åˆ¶è§„则,可以为空
    * @param attrId       å±žæ€§çš„编号
    * @param trim         æ˜¯å¦åŽ»é™¤ç©ºæ ¼
    * @param ignoreCase   æ˜¯å¦ä¸åŒºåˆ†å¤§å°å†™
    * @param ignoreWidth  æ˜¯å¦å¿½ç•¥å…¨åŠè§’
    * @param trimAll      æ˜¯å¦å¿½ç•¥å…¨éƒ¨ç©ºæ ¼
    * @param conditionMap æŸ¥è¯¢æ¡ä»¶
    */
//   @Override
//   public void wrapperKeyAttrConditionMap(String value, CodeKeyattrrepeatVO keyRuleVO, String attrId,
//                                 boolean trim, boolean ignoreCase, boolean ignoreWidth,
//                                 boolean trimAll, Map<String, String> conditionMap) {
//      boolean ignoreSpace = trim || trimAll;
//      if (StringUtils.isBlank(value)) {
//         //为空的时候,不能用QueryOperation.ISNULL,平台不知道啥时候不处理这种了
//         conditionMap.put("t."+attrId, "null");
//      } else {
//         if (keyRuleVO != null) {
//            String queryKey = "";
//            String queryValue = "";
//
//            String temp = "";
//            if (ignoreCase && ignoreSpace && ignoreWidth) {
//               //忽略大小写,且去空,忽略全半角
//               temp = (trimAll ? "REPLACE" : "TRIM") + "(UPPER(to_single_byte(%s)) " + (trimAll ? ",' ','')" : ")");
//            } else if (ignoreCase && ignoreSpace && !ignoreWidth) {
//               //忽略大小写、去空、不忽略全半角
//               temp = (trimAll ? "REPLACE" : "TRIM") + "(UPPER(%s) " + (trimAll ? ",' ','')" : ")");
//            } else if (ignoreCase && !ignoreSpace && ignoreWidth) {
//               //忽略大小写、不去空、忽略全半角
//               temp = "UPPER(to_single_byte(%s))";
//            } else if (!ignoreCase && ignoreSpace && ignoreWidth) {
//               //不忽略大小写、去空、忽略全半角
//               temp = (trimAll ? "REPLACE" : "TRIM") + "(to_single_byte(%s) " + (trimAll ? ",' ','')" : ")");
//            } else if (ignoreCase && !ignoreSpace && !ignoreWidth) {
//               //忽略大小写、不去空、不忽略全半角
//               temp = "UPPER(%s)";
//            } else if (!ignoreCase && !ignoreCase && ignoreWidth) {
//               //不忽略大小写、不去空、忽略全半角
//               temp = "to_single_byte(%s)";
//            } else if (!ignoreCase && ignoreSpace && !ignoreWidth) {
//               //不忽略大小写、去空、不忽略全半角
//               temp = (trimAll ? "REPLACE" : "TRIM") + "(%s " + (trimAll ? ",' ','')" : ")");
//            } else if (!ignoreCase && !ignoreSpace && !ignoreWidth) {
//               //不忽略大小写、不去空、不忽略全半角
//               temp = "%s";
//            }
//            queryKey = String.format(temp, "t."+attrId);
//            queryValue = String.format(temp, "'" + (trim ? value.trim() : value) + "'");
//            conditionMap.put(queryKey, queryValue);
//         } else {
//            //为空的时候不代表不校验,只是不去除相关的信息
//            conditionMap.put("t."+attrId, value);
//         }
//      }
//   }
   /**
    * æ ¡éªŒæžšä¸¾çš„内容
    *
    * @param templateVO æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡ï¼Œéœ€è¦åŒ…含属性
    * @param orderDTO   ç¼–码申请的信息
    */
   private void checkEnumOnOrder(CodeClstemplateVO templateVO, CodeOrderDTO orderDTO) {
      //如果枚举可以修改,则不需要校验是否符合枚举的选项
      Map<String, CodeClstempattrVO> enumAttrVOMap = templateVO.getAttributes().stream().filter(s -> (StringUtils.isNotBlank(s.getEnumstring()) || StringUtils.isNotBlank(s.getEnumid())) && !VciBaseUtil.getBoolean(s.getEnumeditflag())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      if (!CollectionUtils.isEmpty(enumAttrVOMap)) {
         enumAttrVOMap.forEach((attrId, attrVO) -> {
            String value = getValueFromOrderDTO(orderDTO, attrId);
            if (StringUtils.isNotBlank(value)) {
               //有值才能校验
               List<KeyValue> comboboxKVs = listComboboxItems(attrVO);
               if (!comboboxKVs.stream().anyMatch(s -> value.equalsIgnoreCase(s.getKey()))) {
                  throw new VciBaseException("属性【{0}】的值不符合枚举的要求", new String[]{attrVO.getName()});
               }
            }
         });
      }
   }
   /**
    * è½¬æ¢æ—¶é—´çš„æ ¼å¼
    *
    * @param templateVO æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡ï¼Œéœ€è¦åŒ…含属性
    * @param orderDTO   ç¼–码申请的信息
    */
   private void switchDateAttrOnOrder(CodeClstemplateVO templateVO, CodeOrderDTO orderDTO) {
      Map<String, CodeClstempattrVO> dateAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getCodedateformat())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      if (!CollectionUtils.isEmpty(dateAttrVOMap)) {
         dateAttrVOMap.forEach((attrId, attrVO) -> {
            String value = getValueFromOrderDTO(orderDTO, attrId);
            if (StringUtils.isNotBlank(value)) {
               DateConverter dateConverter = new DateConverter();
               dateConverter.setAsText(value);
               value = VciDateUtil.date2Str(dateConverter.getValue(), VciDateUtil.DateTimeMillFormat);
               setValueToOrderDTO(orderDTO, attrId, value);
            }
         });
      }
   }
   /**
    * æ‹·è´æ•°æ®åˆ°cbo对象上
    *
    * @param classifyFullInfo åˆ†ç±»çš„全部信息
    * @param cbo              ä¸šåŠ¡æ•°æ®
    * @param orderDTO         ç¼–码申请的信息
    * @param templateVO       æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡
    * @param edit             æ˜¯å¦ä¸ºä¿®æ”¹
    */
   private void copyValueToCBO(CodeClassifyFullInfoBO classifyFullInfo, CodeWupinEntity cbo,
                        CodeOrderDTO orderDTO, CodeClstemplateVO templateVO,
                        boolean edit) {
      String fullPath = "";
      if (!CollectionUtils.isEmpty(classifyFullInfo.getParentClassifyVOs())) {
         fullPath = classifyFullInfo.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel())))
            .map(CodeClassifyVO::getOid).collect(Collectors.joining("##"));
      } else {
         fullPath = classifyFullInfo.getCurrentClassifyVO().getOid();
      }
//      BeanUtils.
      BeanUtils.copyProperties(orderDTO.getData(),cbo);
      cbo.setMaterialtype(Short.valueOf("1001"));
//      orderDTO.getData().forEach((key, value) -> {
//         if (!edit || (!checkUnAttrUnEdit(key) &&
//            !VciQueryWrapperForDO.LC_STATUS_FIELD.equalsIgnoreCase(key))) {
//            try {
//               cbo.setAttributeValue(key, value);
//            } catch (Exception e) {
//               logger.error("设置属性的值错误", e);
//            }
//         }
//      });
      try {
         cbo.setCodeclsfid(classifyFullInfo.getCurrentClassifyVO().getOid());
         cbo.setCodetemplateoid(templateVO.getOid());
         cbo.setCodeclsfpath(fullPath);
//         cbo.setMaterialclassify("model_type");
//         cbo.setMaterialname(orderDTO.getData().get("materialname"));
//         cbo.setShifoupihaoguanli("true");
//         cbo.setKucunwl("true");
//         cbo.setXiaoshouwl("false");
         if (!edit && StringUtils.isBlank(orderDTO.getLcStatus())) {
            //找生命周期的起始状态,插个点,看生命周期是否需要创建
            if (StringUtils.isNotBlank(cbo.getLctid())) {
//               OsLifeCycleVO lifeCycleVO = lifeCycleService.getLifeCycleById(cbo.getLctid());
//               if (lifeCycleVO != null) {
//                  cbo.setLcStatus("Editing");
////                  cbo.setLcStatus(lifeCycleVO.getStartStatus());
//               } else {
                  cbo.setLcStatus(CodeDefaultLC.EDITING.getValue());
//               }
            } else {
               cbo.setLcStatus(CodeDefaultLC.EDITING.getValue());
            }
         }
         int secret = VciBaseUtil.getInt(cbo.getSecretGrade().toString());
         //插个点,后续看密级服务是否可用
//         if (secret == 0 || !secretService.checkDataSecret(secret)) {
         if (secret == 0 ) {
            Integer userSecret = VciBaseUtil.getCurrentUserSecret();
//            cbo.setAttributeValue(SECRET_FIELD, String.valueOf((userSecret == null || userSecret == 0) ? UserSecretEnum.NONE.getValue() : userSecret));
            cbo.setSecretGrade(userSecret == null || userSecret == 0 ? UserSecretEnum.NONE.getValue() : userSecret);
         }
      } catch (Throwable e) {
         logger.error("设置默认的属性的值错误", e);
      }
   }
   /**
    * åˆå§‹åŒ–业务类型
    * --创建人默认为当前用户,如果需要修改,可以在获取后自行处理
    * @param btmName ä¸šåŠ¡ç±»åž‹çš„åç§°ï¼Œä¼šè‡ªåŠ¨å˜æˆå°å†™
    * @return CodeWupinEntity
    * @throws VciBaseException åˆå§‹åŒ–出错的是会抛出异常
    */
//   @Override
//   public CodeWupinEntity createCBOByBtmName(String btmName)
//      throws VciBaseException {
//      if(btmName!=null){
//         btmName = btmName.trim().toLowerCase();
//      }
//      String userid = AuthUtil.getUser().getUserName();
////      if(!hasCreatedCbos.containsKey(btmName)){
////         if(StringUtils.isEmpty(userid)){
////            throw new VciBaseException(msgCodePrefix +"noHasUserid");
////         }
////         try {
////            hasCreatedCbos.put(btmName, createBusinessObject(btmName));
////         } catch (Exception e) {
////            logger.error("创建业务类型对象",e);
////            throw new VciBaseException(msgCodePrefix + "initBoError",new String[]{btmName});
////         }
////      }
////      ClientBusinessObject cbo = cloneClientBusinessObject(hasCreatedCbos.get(btmName));
//
//      QueryWrapper<CodeOsbtmtypeEntity> btmWrapper = new QueryWrapper<>();
//      btmWrapper.eq("ID",btmName);
//      CodeOsbtmtypeEntity btmTypeVO = codeOsbtmtypeMapper.selectOne(btmWrapper);
////      OsBtmTypeVO btmTypeVO = btmService.getBtmById(boName);
//      String userName = AuthUtil.getUser().getUserName();
//      CodeWupinEntity wupinEntity = new CodeWupinEntity();
//      wupinEntity.setOid(null);
////      bo.setRevisionid((new ObjectUtility()).getNewObjectID36());
////      bo.setNameoid((new ObjectUtility()).getNewObjectID36());
//      wupinEntity.setBtmname(btmName);
//      wupinEntity.setLastR(String.valueOf(1));
//      wupinEntity.setFirstR(String.valueOf(1));
//      wupinEntity.setFirstV(String.valueOf(1));
//      wupinEntity.setLastV(String.valueOf(1));
//      wupinEntity.setCreator(userName);
//      wupinEntity.setCreateTime(new Date());
//      wupinEntity.setLastModifier(userName);
//      wupinEntity.setLastModifyTime(new Date());
//      wupinEntity.setRevisionRule(btmTypeVO.getRevisionruleid());
//      wupinEntity.setVersionRule(String.valueOf(btmTypeVO.getVersionRule()));
//      if(StringUtils.isNotBlank(btmTypeVO.getRevisionruleid())){
//         //插个点,需要问勇哥版本问题,展示默认为1
////         OsRevisionRuleVO revisionRuleVO = revisionRuleService.getRevisionRuleById(btmTypeVO.getRevisionruleid());
//         wupinEntity.setRevisionValue("1");
//      }
//
//      wupinEntity.setRevisionSeq(1);
//      wupinEntity.setVersionSeq(1);
//      //插个点,需要问勇哥版本问题,展示默认为1
//      wupinEntity.setVersionValue("1");
//      wupinEntity.setLctid("wupinLC");
//      wupinEntity.setLcStatus("Editing");
//      wupinEntity.setId("");
//      wupinEntity.setName("");
//      wupinEntity.setDescription("");
//      wupinEntity.setOwner(userName);
//      wupinEntity.setCheckinby(userName);
//      wupinEntity.setCopyFromVersion("");
//      wupinEntity.setMaterialtype((short) 1001);
//      wupinEntity.setCaigouwl("true");
//      wupinEntity.setShifoupihaoguanli("true");
//      wupinEntity.setKucunwl("true");
//      wupinEntity.setXiaoshouwl("false");
//      wupinEntity.setPassing("true");
//
////      this.initTypeAttributeValue(wupinEntity,btmTypeVO);
//      return wupinEntity;
//
//
////      return cbo;
//   }
   /**
    * æ˜¯å¦ä¸ºä¿®æ”¹å¿½ç•¥çš„属性
    * @param attrName å±žæ€§çš„名字
    * @return true è¡¨ç¤ºåº”该忽略
    */
   boolean checkUnAttrUnEdit(String attrName){
      return  (VciQueryWrapperForDO.OID_FIELD.equalsIgnoreCase(attrName)
         ||"ts".equalsIgnoreCase(attrName)
         || "lastmodifier".equalsIgnoreCase(attrName)
         || "lastmodifytime".equalsIgnoreCase(attrName)
         || "createtime".equalsIgnoreCase(attrName)
         || "checkintime".equalsIgnoreCase(attrName)
         ||"checkouttime".equalsIgnoreCase(attrName));
   }
   /**
    * ä¿å­˜å¯è¾“可选的信息
    *
    * @param templateVO æ¨¡æ¿çš„对象
    * @param cboList    æ•°æ®çš„内容
    */
//   @Override
//   public void batchSaveSelectChar(CodeClstemplateVO templateVO, List<ClientBusinessObject> cboList) {
//      if (templateVO != null && !CollectionUtils.isEmpty(cboList)) {
//         //是异步的,所以直接循环
//         List<CodeClstempattrVO> selectAttrVOs = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getLibraryidentification())).collect(Collectors.toList());
//
//         if (!CollectionUtils.isEmpty(selectAttrVOs)) {
////            SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo();
//            selectAttrVOs.parallelStream().forEach(attrVO -> {
//               List<String> valuesList = new CopyOnWriteArrayList<>();
//               cboList.parallelStream().forEach(cbo -> {
//                  String value = cbo.getAttributeValue(attrVO.getId());
//                  if (StringUtils.isNotBlank(value)) {
//                     valuesList.add(value);
//                  }
//               });
//               if (!CollectionUtils.isEmpty(valuesList)) {
//                  charService.saveBySameNamespaceAndFlag(templateVO.getBtmTypeId(), attrVO.getLibraryIdentification(), valuesList, sessionInfo);
//               }
//            });
//         }
//      }
//   }
}