xiejun
2023-11-29 54036dc2ebc591f891f452b3b248594d60fc583e
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmProductCodeServiceImpl.java
@@ -1,6 +1,8 @@
package com.vci.ubcs.code.service.impl;
import com.vci.ubcs.code.algorithm.CustomSerialEnum;
import com.vci.ubcs.code.annotation.MdmSerialAlgorithm;
import com.vci.ubcs.code.annotation.MdmSerialAlgorithmMethod;
import com.vci.ubcs.code.dto.CodeCustomSerialDTO;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -29,6 +31,7 @@
import com.vci.ubcs.starter.web.constant.QueryOptionConstant;
import com.vci.ubcs.starter.web.constant.RegExpConstant;
import com.vci.ubcs.starter.web.enumpck.OsCodeFillTypeEnum;
import com.vci.ubcs.starter.web.util.ApplicationContextProvider;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import com.vci.ubcs.starter.web.util.VciDateUtil;
import lombok.extern.slf4j.Slf4j;
@@ -42,16 +45,16 @@
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import static com.vci.ubcs.code.constant.MdmEngineConstant.*;
import static com.vci.ubcs.code.enumpack.CodeSecTypeEnum.CODE_SERIAL_SEC;
@Service
@Slf4j
public class MdmProductCodeServiceImpl  implements MdmProductCodeService {
@@ -123,6 +126,7 @@
            Map<String/**码段的主键**/,String/**码段的值**/> serialValueMap = new HashMap<>();
            Map<String, CodeBasicSecVO> secVOMap = secVOList.stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
            Map<String,Integer> serialSecOidIndexMap=new HashMap<>();
            LinkedList<String> codeValueList=new LinkedList<>();
            for (int i = 0; i < secLengths.length; i++) {
               CodeBasicSecVO secVO = secVOList.get(i);
               String thisSecValue  = "";
@@ -142,9 +146,10 @@
                  serialUnitList.add(thisSecValue);
                  serialSecOidIndexMap.put(secVO.getOid(),i);
               }
               if(CodeSecTypeEnum.CODE_SERIAL_SEC.getValue().equalsIgnoreCase(secVO.getSecType())){
               if(CODE_SERIAL_SEC.getValue().equalsIgnoreCase(secVO.getSecType())){
                  serialValueMap.put(secVO.getOid(),thisSecValue);
               }
               codeValueList.add(thisSecValue);
            }
            List<String> serialUnFileStringList = new ArrayList<>();
            AtomicReference<String> newSerialUnitString = new AtomicReference<>("");
@@ -207,6 +212,7 @@
            String unFillSerial =serialUnFileStringList.size()==1?serialUnFileStringList.get(0)+ SERIAL_VALUE_SPACE:serialUnFileStringList.stream().collect(Collectors.joining(SERIAL_VALUE_SPACE));
            allCodeDO.setUnFillSerial(unFillSerial);
            allCodeDO.setLcStatus(cbo.getLcStatus());
            allCodeDO.setCodeDelimit(codeValueList.stream().collect(Collectors.joining(SERIAL_VALUE_SPACE)));//添加链接符
            allCodeDOList.add(allCodeDO);
         });
         //处理最大的流水号
@@ -403,8 +409,9 @@
                  sb.append(serialValue).append(SERIAL_VALUE_SPACE);
               }
            }
            String codeDelimiter=thisSecValueList.stream().collect(Collectors.joining(SERIAL_VALUE_SPACE));
            //要存储最后的全部allcode
            wrapperAllCode(classifyFullInfoBO, finalRuleVO, cbo, templateVO, allCodeDOList, serialUnitString, sb.toString());
            wrapperAllCode(classifyFullInfoBO, finalRuleVO, cbo, templateVO, allCodeDOList, serialUnitString, sb.toString(),codeDelimiter);
         }
         //处理最大流水
         saveSerialValue( finalRuleVO, lastMaxSerialValueMap, maxSerialValueMap);
@@ -515,6 +522,122 @@
      }
   }
   /**
    * 转换流水码段的值
    * @param serialSecVOList 流水码段
    * @param secDTOS;流水值
    * @param attrSevIsSerialDepend 是否有属性码段参与流水
    * @param ruleVO 规则的内容
    * @param serialUnitMap 流水依据
    * @param maxSerialValueMap 最大的流水号
    * @param thisSecValueList 本次的码值
    * @param lastMaxSerialValueMap 封装后
    * @param firstData 是否为第一条数据
    */
   private void switchSerialSecValueBZ(BaseModel cbo,List<CodeOrderSecDTO> secDTOS, List<CodeBasicSecVO> serialSecVOList,boolean attrSevIsSerialDepend,
                             CodeRuleVO ruleVO,Map<String,String> serialUnitMap,
                             Map<String/**码段的主键**/,Map<String/**流水依据**/,CodeSerialValue>> maxSerialValueMap,List<String> thisSecValueList,
                             Map<String/**码段的主键**/,Map<String/**流水依据**/, String>> lastMaxSerialValueMap,boolean firstData){
      if (!CollectionUtils.isEmpty(serialSecVOList)) {
         Map<String/**码段oid**/, String/**码段码值**/> attrNameIdMap = secDTOS.stream().collect(Collectors.toMap(s -> s.getSecOid(), t -> t.getSecValue().toLowerCase(Locale.ROOT),(o1, o2)->o2));
         Map<String,String> secIdserialValueMap=new LinkedHashMap<>();
         for (int j = 0; j < serialSecVOList.size(); j++) {
            AtomicReference<String> serialUnitString= new AtomicReference<>("");
            CodeBasicSecVO secVO = serialSecVOList.get(j);
            String secVOValue="";
            if(attrNameIdMap.containsKey(secVO.getOid())){
               secVOValue=attrNameIdMap.get(secVO.getOid());
               if(StringUtils.isNotBlank(secVOValue)){
                  continue;
               }
            }
            if(serialUnitMap.containsKey(secVO.getOid())){
               serialUnitString.set(serialUnitMap.get(secVO.getOid()));
               secIdserialValueMap.forEach((key,vaule)->{
                  serialUnitString.set(serialUnitString.get().replace("${"+key+"}", vaule));
               });
               if (attrSevIsSerialDepend || firstData) {
                  QueryWrapper<CodeSerialValue> codeSerialWrapper = new QueryWrapper<>();
                  codeSerialWrapper.eq("codeRuleOid", ruleVO.getOid());
                  codeSerialWrapper.eq("serialUnit", serialUnitString.get());
                  codeSerialWrapper.eq("codeSecOid", secVO.getOid());
                  List<CodeSerialValue> serialValueDOS = serialValueMapper.selectList(codeSerialWrapper);
                  if (!CollectionUtils.isEmpty(serialValueDOS)) {
                     Map<String, CodeSerialValue> unitSerialMap = maxSerialValueMap.getOrDefault(secVO.getOid(), new HashMap<>());
                     CodeSerialValue serialValueDO = serialValueDOS.get(0);
                     unitSerialMap.put(serialValueDO.getSerialUnit(),serialValueDO);
                     maxSerialValueMap.put(secVO.getOid(), unitSerialMap);
                  }
               }
               String serialString="";
               String thisSerialValue = "";
               String startValue = null;
               if (maxSerialValueMap.containsKey(secVO.getOid()) && maxSerialValueMap.get(secVO.getOid()).containsKey(serialUnitString.get())) {
                  startValue = maxSerialValueMap.get(secVO.getOid()).get(serialUnitString.get()).getMaxSerial();
               }
               if (lastMaxSerialValueMap.containsKey(secVO.getOid()) && lastMaxSerialValueMap.get(secVO.getOid()).containsKey(serialUnitString.get())) {
                  //说明多个申请,之前已经加了流水号了
                  startValue = lastMaxSerialValueMap.get(secVO.getOid()).get(serialUnitString.get());
               }
               if(StringUtils.isNotBlank(secVO.getCustomCodeSerialClass())){//自定义流水处理
                  String currentFlowValue=startValue;
                  CodeCustomSerialDTO codeCustomSerialDTO=new CodeCustomSerialDTO();
                  codeCustomSerialDTO.setSerialUnitString(serialUnitString.get());
                  codeCustomSerialDTO.setSerialCodeCodeBasicSec(secVO);
                  codeCustomSerialDTO.setCurrentFlowValue(startValue);
                  codeCustomSerialDTO.setCodeBasicSecVOList(ruleVO.getSecVOList());
                  codeCustomSerialDTO.setCodeRuleOid(ruleVO.getOid());
                  codeCustomSerialDTO.setBaseModel(cbo);
                  codeCustomSerialDTO.setSerialUnitString(serialUnitString.get());
                  codeCustomSerialDTO.setSecValueList(thisSecValueList);
                  thisSerialValue=customCodeSerial(secVO.getCustomCodeSerialClass(),codeCustomSerialDTO);
                  serialUnitString.set(codeCustomSerialDTO.getSerialUnitString());
                  log.info(secVO.getCustomCodeSerialClassText()+"---->"+thisSerialValue);
               }else {
                  Double newThisSerialValue = 0d;
                  if (startValue == null) {
                     //第一个编码
                     newThisSerialValue = VciBaseUtil.getDouble(secVO.getSerialStart());
                  } else {
                     //流水号肯定是数字
                     newThisSerialValue = Double.parseDouble(startValue) + (j + 1) * secVO.getSerialStep();
                  }
                  //要看是否超过最大的流水值
                  if (newThisSerialValue >= secVO.getCodeFillLimit()) {
                     throw new VciBaseException("流水号已经超过允许的最大流水值{0}", new String[]{secVO.getCodeFillLimit().toString()});
                  }
                  thisSerialValue=String.valueOf(newThisSerialValue.intValue());
               }
               //要看补位的内容
               Integer fillLength = VciBaseUtil.getInt(secVO.getCodeFillLength());
               if (fillLength == 0 || fillLength > VciBaseUtil.getInt(secVO.getCodeSecLength())) {
                  //防止在添加的地方没有控制正确
                  fillLength = VciBaseUtil.getInt(secVO.getCodeSecLength());
               }
               serialString = thisSerialValue;
               serialString = fillString(fillLength, OsCodeFillTypeEnum.forValue(secVO.getCodeFillType()), serialString, secVO.getCodeFillSeparator());
               for (int z = 0; z < thisSecValueList.size(); z++) {
                  String secValue = thisSecValueList.get(z);
                  if (secValue.equalsIgnoreCase("${" + secVO.getOid() + "}")) {
                     // TODO: 流水生成码值后拼接前后缀
                     thisSecValueList.set(z, joinPreffixAndSuffix(secVO, serialString));
                  }
               }
               secIdserialValueMap.put(secVO.getOid(),thisSerialValue);//记录流水码段当前的值
               if(StringUtils.isNotBlank(thisSerialValue)) {
                  Map<String, String> unitSerialMap = lastMaxSerialValueMap.getOrDefault(secVO.getOid(), new HashMap<>());
                  unitSerialMap.put(serialUnitString.get(), String.valueOf(thisSerialValue));
                  lastMaxSerialValueMap.put(secVO.getOid(), unitSerialMap);
               }
            }
         }
      }
   }
   /**
    * 转换流水码段的值
    * @param serialSecVOList 流水码段
@@ -585,7 +708,10 @@
               codeCustomSerialDTO.setCodeBasicSecVOList(ruleVO.getSecVOList());
               codeCustomSerialDTO.setCodeRuleOid(ruleVO.getOid());
               codeCustomSerialDTO.setBaseModel(cbo);
               codeCustomSerialDTO.setSerialUnitString(newSerialUnitString.get());
               codeCustomSerialDTO.setSecValueList(thisSecValueList);
               thisSerialValue=customCodeSerial(secVO.getCustomCodeSerialClass(),codeCustomSerialDTO);
               newSerialUnitString.set(codeCustomSerialDTO.getSerialUnitString());
               log.info(secVO.getCustomCodeSerialClassText()+"---->"+thisSerialValue);
            }else {
               Double newThisSerialValue = 0d;
@@ -626,7 +752,33 @@
      }
   }
   private String customCodeSerial(String className, CodeCustomSerialDTO codeCustomSerialDTO){
   private String customCodeSerial(String beanName, CodeCustomSerialDTO codeCustomSerialDTO){
      AtomicReference<String> result = new AtomicReference<>("");
      //BusAnnotationUtil.callForAnnotation(FlowNotifyWeb.class, FlowNotifyBefore.class,noticeInfo);
      //在登录之前,看看是否有插件
      Map<String, Object> beanMap = ApplicationContextProvider.getApplicationContext().getBeansWithAnnotation(MdmSerialAlgorithm.class);
      if (!CollectionUtils.isEmpty(beanMap)) {
         if(beanMap.containsKey(beanName)){
            Object v=beanMap.get(beanName);
            Method[] methods = v.getClass().getDeclaredMethods();
            if (methods != null && methods.length > 0) {
               for (Method method : methods) {
                  if (method.isAnnotationPresent(MdmSerialAlgorithmMethod.class)) {
                     try {
                        Object  o=   method.invoke(v, codeCustomSerialDTO);
                        result.set(Func.isEmpty(o) ?"":o.toString());
                     } catch (Throwable e) {
                        if (log.isErrorEnabled()) {
                           log.error("调用插件出错", e);
                        }
                        throw new VciBaseException("调用插件出错,{0},{1}", new String[]{v.getClass().getName(), method.getName()}, e);
                     }
                  }
               }
            }
         }
      }
      /*
      String result = "";
      try {
         Class classInstance=Class.forName(className);
@@ -646,8 +798,8 @@
         throw new VciBaseException("执行自定义流水算法处理方法出现异常");
      } catch (InstantiationException e) {
         e.printStackTrace();
      }
      return result;
      }*/
      return result.get();
   }
   /**
@@ -822,10 +974,11 @@
    * @param cbo 业务数据
    * @param templateVO 模板的信息
    * @param allCodeDOList 所有的码值的对象列表
    * @param codeDelimiter 码值分割符
    */
   private void wrapperAllCode(CodeClassifyFullInfoBO classifyFullInfoBO, CodeRuleVO ruleVO,
                                BaseModel cbo, CodeClassifyTemplateVO templateVO,
                                List<CodeAllCode> allCodeDOList, String serialUnitString, String serialValueString){
                                List<CodeAllCode> allCodeDOList, String serialUnitString, String serialValueString,String codeDelimiter){
      CodeAllCode allCodeDO = new CodeAllCode();
      DefaultAttrAssimtUtil.addDefaultAttrAssimt(allCodeDO, MdmBtmTypeConstant.CODE_ALL_CODE);
      allCodeDO.setCodeClassifyOid(classifyFullInfoBO.getCurrentClassifyVO().getOid());
@@ -837,6 +990,7 @@
      allCodeDO.setSerialUnit(serialUnitString);
      allCodeDO.setUnFillSerial(serialValueString);
      allCodeDO.setLcStatus(cbo.getLcStatus());
      allCodeDO.setCodeDelimit(codeDelimiter);
      allCodeDOList.add(allCodeDO);
   }
@@ -1000,6 +1154,267 @@
      return updateFlag.get();
   }
   /***
    *
    * @param classifyFullInfoBO 分类的全部信息
    * @param templateVO 模板的显示对象
    * @param ruleVO 编码规则的显示对象
    * @param secDTOList 各个码段的值
    * @param dataCBOList 业务数据
    * @return
    * @throws Exception
    */
   @Override
   public List<String> productCodeAndSaveDataBZ(CodeClassifyFullInfoBO classifyFullInfoBO, CodeClassifyTemplateVO templateVO, CodeRuleVO ruleVO, List<CodeOrderSecDTO> secDTOList, List<BaseModel> dataCBOList) throws Exception {
      dataCBOList = dataCBOList.stream().sorted(((o1, o2) -> o1.getCreateTime().compareTo(o2.getCreateTime()))).collect(Collectors.toList());
      List<String> codeList = new ArrayList<>();
      final CodeRuleVO finalRuleVO = ruleVO;
      List<CodeBasicSecVO> secVOList = finalRuleVO.getSecVOList().stream().sorted(((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()))).collect(Collectors.toList());
      List<String> serialUnitList = new LinkedList<>();
      List<String> secValueList = new ArrayList<>();
      Map<String, String> secValueMap = secDTOList.stream().collect(Collectors.toMap(s -> s.getSecOid(), s -> s.getSecValue()==null?"":s.getSecValue()));
      List<CodeBasicSecVO> serialSecVOList = new ArrayList<>();
      List<CodeBasicSecVO> attrSecVOList = new ArrayList<>();
      Map<String,String> secOdserialUnitMap=new HashMap<>();
      LinkedHashMap<String,String> newSecValueMap=new LinkedHashMap<>();
      for (int i = 0; i < secVOList.size(); i++) {
         CodeBasicSecVO secVO = secVOList.get(i);
         String secValue="";
         String secOid=secVO.getOid();
         if(secValueMap.containsKey(secOid)){
            secValue=secValueMap.get(secOid);
         }
         newSecValueMap.put(secOid,secValue);
         switchSecValueBZ(secVO, secValueMap, classifyFullInfoBO, serialSecVOList, attrSecVOList, serialUnitList, secValueList);
         //分段存储流水依赖
         if(secVO.getSecType().equals(CodeSecTypeEnum.CODE_SERIAL_SEC.getValue())){
            List<String> newSerialUnitList= serialUnitList.stream().filter(secValueStr -> {
               return  !secValueStr.equals("${"+secVO.getOid()+"}");
            }).collect(Collectors.toList());
            String serialUnitString = serialUnitList.size() == 0 ? EMPTY_SERIAL_UNIT : newSerialUnitList.stream().collect(Collectors.joining(SERIAL_UNIT_SPACE));
            secOdserialUnitMap.put(secVO.getOid(),serialUnitString);
         }
      }
      //处理属性码段和流水码段
      Map<String/**流水码段的主键**/, Map<String/**流水依据**/, String>> lastMaxSerialValueMap = new HashMap<>();
      List<CodeAllCode> allCodeDOList = new ArrayList<>();
      //已经存储的最大流水号的内容
      Map<String/**码段的主键**/, Map<String, CodeSerialValue>> maxSerialValueMap = new HashMap<>();
      for (int i = 0; i < dataCBOList.size(); i++) {
         BaseModel cbo = dataCBOList.get(i);
         cbo.getData().remove(CODE_SEC_LENGTH_FIELD);//将此key除去
         cbo.getData().remove(IMPORT_ROW_INDEX);//将此key除去
         cbo.getData().remove("codeclassifyid");//将此key除去
         List<String> thisSecValueList = new LinkedList<>();
         for (int j = 0; j < secValueList.size(); j++) {
            thisSecValueList.add(secValueList.get(j));
         }
         List<String> thisSerialUnitList = new LinkedList<>();
         //因为流水依据每次可能不一样,所以每次都拷贝一份
         for (int j = 0; j < serialUnitList.size(); j++) {
            thisSerialUnitList.add(serialUnitList.get(j));
         }
         //先看看有没有属性的码段
         boolean attrSevIsSerialDepend = CollectionUtils.isEmpty(attrSecVOList) ? false : (attrSecVOList.stream().anyMatch(s -> VciBaseUtil.getBoolean(s.getSerialDependFlag())));
         switchAttrSecValue(attrSecVOList, cbo, thisSecValueList, attrSevIsSerialDepend, thisSerialUnitList);
         switchSerialSecValueBZ(cbo,secDTOList,serialSecVOList, attrSevIsSerialDepend, finalRuleVO, secOdserialUnitMap, maxSerialValueMap, thisSecValueList, lastMaxSerialValueMap, i == 0);
         //组装编码的值
         cbo.setId(thisSecValueList.stream().collect(Collectors.joining()));
         codeList.add(cbo.getId());
         StringBuilder sb = new StringBuilder();
         //把码段里面都找一下流水号
         AtomicReference<String> serialUnitString= new AtomicReference<>("");
         for (int j = 0; j < serialSecVOList.size(); j++) {
            CodeBasicSecVO secVO = serialSecVOList.get(j);
            if(lastMaxSerialValueMap.containsKey(secVO.getOid())){
               Map<String/**流水依据**/, String> serialValueMap=   lastMaxSerialValueMap.get(secVO.getOid());
               serialValueMap.forEach((maxSerialUnitString,serialValue)->{
                  if(StringUtils.isNotBlank(serialValue)){
                     serialUnitString.set(maxSerialUnitString);
                     sb.append(serialValue).append(SERIAL_VALUE_SPACE);
                  }
               });
            }
         }
         String codeDelimiter=thisSecValueList.stream().collect(Collectors.joining(SERIAL_VALUE_SPACE));
         //要存储最后的全部allcode
         wrapperAllCode(classifyFullInfoBO, finalRuleVO, cbo, templateVO, allCodeDOList, serialUnitString.get(), sb.toString(),codeDelimiter);
      }
      //处理最大流水
      saveSerialValue( finalRuleVO, lastMaxSerialValueMap, maxSerialValueMap);
      allCodeDOList.stream().forEach(
         allCode -> {DefaultAttrAssimtUtil.addDefaultAttrAssimt(allCode,"codeallcode");allCode.setLctid("codeAllCodeLC");}
      );
      Map<String, String> statusMap = allCodeDOList.stream().collect(Collectors.toMap(s -> s.getOid(), s -> s.getLcStatus()));
      allCodeDOList.stream().filter(s -> StringUtils.equalsIgnoreCase("codeallcode",s.getBtmname())).forEach(s -> {
         s.setLcStatus(statusMap.get(s.getOid()));
      });
      //通过ID来进行去重
      List<CodeAllCode> distinctCodeAllCOdes = allCodeDOList.stream().collect(Collectors
         .collectingAndThen(
            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CodeAllCode::getId))),
            ArrayList::new));
      if( distinctCodeAllCOdes.size() != allCodeDOList.size() ){
         throw new ServiceException("编码数据重复,无法保存,请注意!");
      }
      QueryWrapper<CodeAllCode> wrapper = new QueryWrapper<>();
      wrapper.eq("CREATECODEBTM",allCodeDOList.get(0).getCreateCodeBtm());
      wrapper.in("ID",allCodeDOList.stream().map(CodeAllCode::getId).collect(Collectors.toList()));
      List<CodeAllCode> codeAllCodes = codeAllCodeService.selectByWrapper(wrapper);
      List<CodeAllCode> takeBack = codeAllCodes.stream().filter(e -> e.getLcStatus().equals("TakeBack")).collect(Collectors.toList());
      if(codeAllCodes.size()>takeBack.size()){
         throw new ServiceException("生成编码数据ID已有历史记录,请确认如下生成的ID数据:"+ allCodeDOList.stream().map(CodeAllCode::getId).collect(Collectors.toList()));
      }
      for (CodeAllCode codeAllCode : takeBack) {
         codeAllCode.setTs(new Date());
         codeAllCode.setLastModifyTime(new Date());
         codeAllCode.setLastModifier(AuthUtil.getUserId().toString());
         Iterator<CodeAllCode> iterator = allCodeDOList.iterator();
         while (iterator.hasNext()){
            CodeAllCode next = iterator.next();
            if(codeAllCode.getId().equals(next.getId())){
               codeAllCode.setCreateCodeOid(next.getCreateCodeOid());
               codeAllCode.setLcStatus(next.getLcStatus());
               //iterator.remove();
            }
         }
      }
      if(takeBack.size()>0){
         codeAllCodeService.updateBatchById(takeBack);
      }
      codeAllCodeService.saveBatch(allCodeDOList);
      mdmEngineService.insertBatchByType(dataCBOList.get(0).getBtmname(),dataCBOList);
      return codeList;
   }
   /**
    * 转换码值的内容
    * @param secVO 码段的内容
    * @param secValueMap 码值的内容,key是码段的主键,value是码值
    * @param classifyFullInfoBO 分类的全部信息
    * @param serialSecVOList 流水码段
    * @param attrSecVOList 属性码段
    * @param serialUnitList 流水依据
    * @param secValueList 码值列表
    */
   private void switchSecValueBZ(CodeBasicSecVO secVO,Map<String,String> secValueMap,
                        CodeClassifyFullInfoBO classifyFullInfoBO,List<CodeBasicSecVO> serialSecVOList,
                        List<CodeBasicSecVO> attrSecVOList, List<String> serialUnitList,
                        List<String> secValueList ){
      CodeSecTypeEnum secType = CodeSecTypeEnum.forValue(secVO.getSecType());
      String secValue = secValueMap.getOrDefault(secVO.getOid(), "");
      switch (secType) {
         case CODE_FIXED_SEC:
            secValue = joinPreffixAndSuffix(secVO, secValue);
            //固定码段的,直接用码值,不论码值的长度是多少,因为可变长度和固定长度是控制在码段管理里面的码值定义的
            break;
         case CODE_DATE_SEC:
            //时间码段,需要将当前时间依据时间格式进行转换.
            //时间码段不涉及到是否补位
            secValue =joinPreffixAndSuffix(secVO, VciDateUtil.date2Str(new Date(), secVO.getCodeDateFormatStr()));
            break;
         case CODE_CLASSIFY_SEC:
            //分类码段的,也是从前端选择了码值即可,不论码值的长度是多少
            CodeClassifyValue codeClassifyValueDO= codeClassifyValueMapper.selectById(secValue);
            if(codeClassifyValueDO!=null) {
               secValue = joinPreffixAndSuffix(secVO, codeClassifyValueDO.getId());
            }
            break;
         case CODE_LEVEL_SEC:
            //层级码段,需要从分类上获取相应的信息
            if (CodeLevelTypeEnum.MIN.getValue().equalsIgnoreCase(secVO.getCodeLevelType())) {
               //最小层,因为我们只能在叶子节点上申请编码,所以这个就是当前分类的
               if (CodeGetValueTypeEnum.CURRENT.getValue().equalsIgnoreCase(secVO.getCodeGetValueType()) || CollectionUtils.isEmpty(classifyFullInfoBO.getParentClassifyVOs())) {
                  //就是当前分类的
                  secValue = classifyFullInfoBO.getCurrentClassifyVO().getId();
               } else {
                  //我们需要从顶层开始找到当前分类为止
                  secValue = classifyFullInfoBO.getParentClassifyVOs().stream().sorted(((o1, o2) -> -o1.getDataLevel().compareTo(o2.getDataLevel()))).map(CodeClassifyVO::getId).collect(Collectors.joining()) + classifyFullInfoBO.getCurrentClassifyVO().getId();
               }
            } else {
               //指定层,我们需要通过上级的来获取
               if (CollectionUtils.isEmpty(classifyFullInfoBO.getParentClassifyVOs())) {
                  //说明当前已经是最高的了
                  secValue = classifyFullInfoBO.getCurrentClassifyVO().getId();
               } else {
                  //这个我们需要看看,层级是不是大于了最大层级的数
                  List<CodeClassifyVO> parentClassifyVOList = classifyFullInfoBO.getParentClassifyVOs().stream().sorted(((o1, o2) -> -o1.getDataLevel().compareTo(o2.getDataLevel()))).collect(Collectors.toList());
                  if (secVO.getCodeLevelValue() > (parentClassifyVOList.size() + 1)) {
                     //指定的层级比当前的层级还大了,所以只能获取当前层级了
                     if (CodeGetValueTypeEnum.CURRENT.getValue().equalsIgnoreCase(secVO.getCodeGetValueType())) {
                        secValue = classifyFullInfoBO.getCurrentClassifyVO().getId();
                     } else {
                        secValue = parentClassifyVOList.stream().map(CodeClassifyVO::getId).collect(Collectors.joining()) + classifyFullInfoBO.getCurrentClassifyVO().getId();
                     }
                  } else {
                     //我们获取其中指定层的内容
                     if (CodeGetValueTypeEnum.CURRENT.getValue().equalsIgnoreCase(secVO.getCodeGetValueType())) {
                        CodeClassifyVO classifyVO = parentClassifyVOList.stream().filter(s -> s.getDataLevel().intValue() == secVO.getCodeLevelValue().intValue()).findFirst().orElseGet(() -> null);
                        if (classifyVO != null) {
                           secValue = classifyVO.getId();
                        }
                     } else {
                        //小于等于的全部拿出来
                        secValue = parentClassifyVOList.stream().filter(s -> s.getDataLevel().intValue() <= secVO.getCodeLevelValue().intValue()).sorted(((o1, o2) -> -o1.getDataLevel().compareTo(o2.getDataLevel()))).map(CodeClassifyVO::getId).collect(Collectors.joining());
                     }
                  }
               }
            }
            //看看长度是否需要截断
            if (!CodeCutTypeEnum.NONE.getValue().equalsIgnoreCase(secVO.getValueCutType()) &&
               secVO.getValueCutLength() != null && secVO.getValueCutLength() > 0 && secValue.length() > secVO.getValueCutLength()) {
               if (CodeCutTypeEnum.RIGHT.getValue().equalsIgnoreCase(secVO.getValueCutType())) {
                  //左截取是从左边剪掉,右截取是从右边剪掉--保留左边
                  secValue = secValue.substring(0, secVO.getValueCutLength());
               } else {
                  secValue = secValue.substring(secValue.length() - secVO.getValueCutLength());
               }
            }
            secValue = joinPreffixAndSuffix(secVO,secValue);
            break;
         case CODE_REFER_SEC:
            //引用的在页面上已经选择了,所以直接使用前端上传递的值
            //引用就是参照,可能是其他的分类(业务类型)下的数据,所以只在页面上选择
            secValue = joinPreffixAndSuffix(secVO,secValue);
            break;
         case CODE_ATTR_SEC:
            //属性与引用的区别是,属性是当前数据里的属性,而引用可能是引用其他的分类的(业务类型)
            //因为可能是批量的数据的操作,所以我们这里不能直接处理属性,需要后边一边处理
            secValue = "${attr_" + secVO.getOid() + "}";
            attrSecVOList.add(secVO);
            break;
         case CODE_VARIABLE_SEC:
            //可变码段,是在页面上输入内容
            if (secValue.length() > VciBaseUtil.getInt(secVO.getCodeSecLength())) {
               throw new VciBaseException("【{0}】这个码段是可变码段,但是现在输入的码值的长度({1})超过了规定的长度{2}", new String[]{secVO.getName(), String.valueOf(secValue.length()), secVO.getCodeSecLength()});
            }
            OsCodeFillTypeEnum fillTypeEnum = OsCodeFillTypeEnum.forValue(secVO.getCodeFillType());
            secValue = fillString(VciBaseUtil.getInt(secVO.getCodeSecLength()), fillTypeEnum, secValue, secVO.getCodeFillSeparator());
            secValue = joinPreffixAndSuffix(secVO,secValue);
            break;
         case CODE_SERIAL_SEC:
            //流水码段
            serialSecVOList.add(secVO);
            if(secValueMap.containsKey(secVO.getOid())){
               secValue=secValueMap.get(secVO.getOid());
            }else{
               secValue = "${" + secVO.getOid() + "}";
            }
         default:
            break;
      }
      if (VciBaseUtil.getBoolean(secVO.getSerialDependFlag())) {
         serialUnitList.add(secValue);
      }
      secValueList.add(secValue);
   }
   /**
    * 使用CBO处理组合规则的内容
    * @param cbo 数据的内容
@@ -1015,7 +1430,7 @@
      }
      Map<String, String> map = new HashMap<String, String>();
      for (String i : dataMap.keySet()) {
         map.put(i, String.valueOf(dataMap.get(i)));
         map.put(i, String.valueOf(dataMap.get(i)).trim());
      }
//      WebUtil.copyValueToMapFromCbos(cbo,dataMap);
      return formulaService.getValueByFormula(map,rule);