xiejun
2023-11-29 54036dc2ebc591f891f452b3b248594d60fc583e
1.标准申请功能开发
2.业务数据报错去空格
已修改11个文件
已添加7个文件
1439 ■■■■■ 文件已修改
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/dto/CodeBZApplyDTO.java 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/dto/CodeCustomSerialDTO.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/entity/CodeAllCode.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/attrmap/标准修订月份大于1的.json 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/attrmap/标准修订月份小于2的.json 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/attrmap/标准申请.json 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/attrmap/系列流水.json 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-util-api/src/main/java/com/vci/ubcs/starter/web/util/VciBaseUtil.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/algorithm/CustomRomanSerialAlgorithmExample.java 154 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/algorithm/Test.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/annotation/MdmSerialAlgorithm.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/MdmEngineController.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/enumpack/CodeBZOperationTypeEnum.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/MdmEngineService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/MdmProductCodeService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeSerialAlgorithmServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java 297 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmProductCodeServiceImpl.java 433 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/dto/CodeBZApplyDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,200 @@
package com.vci.ubcs.code.dto;
import com.vci.ubcs.code.dto.datapush.BaseModelDTO;
import lombok.Data;
import java.util.List;
/**
 * æ ‡å‡†ç”³è¯·å’Œä¿®è®¢æ•°æ®,在单条的时候使用
 * @author xiejun
 * @date 2023-11-22
 */
public class CodeBZApplyDTO extends BaseModelDTO {
    /**
     * åºåˆ—化
     */
    private static final long serialVersionUID = 1980155181507713249L;
    /***
     * æ“ä½œç±»åž‹
     */
    private String operationType;
    /***
     * æ˜¯å¦ç³»åˆ—
     */
    private boolean series;
    /***
     *发布时间
     */
    private String releaseTime;
    /***
     * æºæ ‡å‡†å·
     */
    private String oldCode;
    /***
     * ç³»åˆ—流水
     */
    private String seriesFlow;
    /***
     * æ˜¯å¦å˜æ›´ç³»åˆ—
     */
    private boolean editSeries;
    /**
     * ä¸»é¢˜åº“分类主键
     */
    private String codeClassifyOid;
    /**
     * æ¨¡æ¿çš„主键
     */
    private String templateOid;
    /**
     * ç¼–码规则的主键
     */
    private String codeRuleOid;
    /**
     * æ˜¯å¦åœ¨æµç¨‹ä¸­ä¸­ä¿®æ”¹
     */
    private boolean editInProcess;
    /**
     * ç æ®µé€‰æ‹©çš„信息
     */
    private List<CodeOrderSecDTO> secDTOList;
    /**
     * æœ€å¤§æµæ°´å·
     */
    private int maxSecNum;
    public String getOperationType() {
        return operationType;
    }
    public void setOperationType(String operationType) {
        this.operationType = operationType;
    }
//    public boolean isSeries() {
//        return isSeries;
//    }
//
//    public void setSeries(boolean series) {
//        isSeries = series;
//    }
//
    public String getReleaseTime() {
        return releaseTime;
    }
    public void setReleaseTime(String releaseTime) {
        this.releaseTime = releaseTime;
    }
    public String getOldCode() {
        return oldCode;
    }
    public void setOldCode(String oldCode) {
        this.oldCode = oldCode;
    }
    public String getSeriesFlow() {
        return seriesFlow;
    }
    public void setSeriesFlow(String seriesFlow) {
        this.seriesFlow = seriesFlow;
    }
    public String getCodeClassifyOid() {
        return codeClassifyOid;
    }
    public void setCodeClassifyOid(String codeClassifyOid) {
        this.codeClassifyOid = codeClassifyOid;
    }
    public String getTemplateOid() {
        return templateOid;
    }
    public void setTemplateOid(String templateOid) {
        this.templateOid = templateOid;
    }
    public String getCodeRuleOid() {
        return codeRuleOid;
    }
    public void setCodeRuleOid(String codeRuleOid) {
        this.codeRuleOid = codeRuleOid;
    }
    public boolean isEditInProcess() {
        return editInProcess;
    }
    public void setEditInProcess(boolean editInProcess) {
        this.editInProcess = editInProcess;
    }
    public List<CodeOrderSecDTO> getSecDTOList() {
        return secDTOList;
    }
    public void setSecDTOList(List<CodeOrderSecDTO> secDTOList) {
        this.secDTOList = secDTOList;
    }
    public int getMaxSecNum() {
        return maxSecNum;
    }
    public void setMaxSecNum(int maxSecNum) {
        this.maxSecNum = maxSecNum;
    }
    public boolean isSeries() {
        return series;
    }
    public void setSeries(boolean series) {
        this.series = series;
    }
    public boolean isEditSeries() {
        return editSeries;
    }
    public void setEditSeries(boolean editSeries) {
        this.editSeries = editSeries;
    }
    @Override
    public String toString() {
        return "CodeBZApplyDTO{" +
            "operationType='" + operationType + '\'' +
            ", series=" + series +
            ", releaseTime='" + releaseTime + '\'' +
            ", oldCode='" + oldCode + '\'' +
            ", seriesFlow='" + seriesFlow + '\'' +
            ", editSeries=" + editSeries +
            ", codeClassifyOid='" + codeClassifyOid + '\'' +
            ", templateOid='" + templateOid + '\'' +
            ", codeRuleOid='" + codeRuleOid + '\'' +
            ", editInProcess=" + editInProcess +
            ", secDTOList=" + secDTOList +
            ", maxSecNum=" + maxSecNum +
            '}';
    }
}
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/dto/CodeCustomSerialDTO.java
@@ -6,12 +6,15 @@
import com.vci.ubcs.starter.revision.model.BaseModel;
import lombok.Data;
import java.util.LinkedList;
import java.util.List;
@Data
public class CodeCustomSerialDTO extends BaseModelDTO {
    //编码规则码段
   private     List<CodeBasicSecVO> codeBasicSecVOList;
   //各个码段的码值
   private     List<String> secValueList=new LinkedList();
    /***
     * ç¼–码规则id
     */
@@ -21,7 +24,7 @@
     */
    private String currentFlowValue;
    /***
     * æµå¤±ä¾èµ–
     * æµæ°´ä¾èµ–
     */
    private String serialUnitString;
    /***
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/entity/CodeAllCode.java
@@ -87,5 +87,10 @@
     * æ²¡æœ‰å¡«å……前的流水号
     */
    private String unFillSerial;
    /***
     * ç æ®µå€¼é“¾æŽ¥
     */
    private String codeDelimit;
}
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/attrmap/±ê×¼ÐÞ¶©Ô·ݴóÓÚ1µÄ.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
{
  "operationType": "2",
  "series": false,
  "releaseTime": "2024-09-23",
  "oldCode": "Q/3B1-2023",
  "seriesFlow": "",
  "isEditSeries": false,
  "editInProcess": false,
  "codeClassifyOid": "1722159168229609472",
  "templateOid": "1722159635358650369",
  "codeRuleOid": "1717377846655193088",
  "editInProcess": "",
  "secDTOList":[{
    "secOid":"1717378065371369472",
    "secValue": "Q/3B"
  },{
    "secOid":"1722497248551636992",
    "secValue": "-"
  },
    {
      "secOid":"1722497450259910656",
      "secValue": "2023"
    }
  ],
  "data":{"name":"标准名称",
    "standardFileType":"文件类型",
    "codeStandardEditType":"2",
    "oldcode":"Q/3B1-2023",
    "isSeries":"false",
    "reviseSeries":"false",
    "ImplementationDate":"2023-11-23 19:22:33",
    "approveDate":"2023-11-23 19:22:33",
    "releaseDate": "2024-09-23 19:22:33"}
}
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/attrmap/±ê×¼ÐÞ¶©Ô·ÝСÓÚ2µÄ.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
{
  "operationType": "2",
  "series": false,
  "releaseTime": "2024-01-23",
  "oldCode": "Q/3B1-2023",
  "seriesFlow": "",
  "isEditSeries": false,
  "editInProcess": false,
  "codeClassifyOid": "1722159168229609472",
  "templateOid": "1722159635358650369",
  "codeRuleOid": "1717377846655193088",
  "editInProcess": "",
  "secDTOList":[{
    "secOid":"1717378065371369472",
    "secValue": "Q/3B"
  },{
    "secOid":"1722497248551636992",
    "secValue": "-"
  },
    {
      "secOid":"1722497450259910656",
      "secValue": "2023"
    }
  ],
  "data":{"name":"标准名称",
    "standardFileType":"文件类型",
    "codeStandardEditType":"2",
    "oldcode":"Q/3B1-2023",
    "isSeries":"false",
    "reviseSeries":"false",
    "ImplementationDate":"2023-11-23 19:22:33",
    "approveDate":"2023-11-23 19:22:33",
    "releaseDate": "2024-01-23 19:22:33"}
}
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/attrmap/±ê×¼ÉêÇë.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
{
  "operationType": "1",
  "series": false,
  "releaseTime": "2023-11-23",
  "oldCode": "",
  "seriesFlow": "",
  "isEditSeries": false,
  "editInProcess": false,
  "codeClassifyOid": "1722159168229609472",
  "templateOid": "1722159635358650369",
  "codeRuleOid": "1717377846655193088",
  "editInProcess": "",
  "secDTOList":[{
    "secOid":"1717378065371369472",
    "secValue": "Q/3B"
  },{
    "secOid":"1722497248551636992",
    "secValue": "-"
  },
    {
      "secOid":"1722497450259910656",
      "secValue": "2023"
    }
  ],
  "data":{"name":"标准名称",
    "standardFileType":"文件类型",
    "codeStandardEditType":"1",
    "oldcode":"",
    "isSeries":"false",
    "reviseSeries":"false",
    "ImplementationDate":"2023-11-23 19:22:33",
    "approveDate":"2023-11-23 19:22:33",
    "releaseDate": "2023-11-23 19:22:33"}
}
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/attrmap/ϵÁÐÁ÷Ë®.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
{
  "operationType": "1",
  "series": true,
  "releaseTime": "2023-11-23",
  "oldCode": "",
  "seriesFlow": "",
  "isEditSeries": false,
  "editInProcess": false,
  "codeClassifyOid": "1722159168229609472",
  "templateOid": "1722159635358650369",
  "codeRuleOid": "1717377846655193088",
  "editInProcess": "",
  "secDTOList":[{
    "secOid":"1717378065371369472",
    "secValue": "Q/3B"
  },{
    "secOid":"1722497248551636992",
    "secValue": "-"
  },
    {
      "secOid":"1722497079235973120",
      "secValue":"1"
    },
    {
      "secOid":"1722497450259910656",
      "secValue": "2023"
    }
  ],
  "data":{"name":"系列标准名称",
    "standardFileType":"文件类型",
    "codeStandardEditType":"1",
    "oldcode":"",
    "isSeries":"true",
    "reviseSeries":"false",
    "ImplementationDate":"2023-11-23 19:22:33",
    "approveDate":"2023-11-23 19:22:33",
    "releaseDate": "2023-11-23 19:22:33"}
}
Source/UBCS/ubcs-service-api/ubcs-util-api/src/main/java/com/vci/ubcs/starter/web/util/VciBaseUtil.java
@@ -1332,7 +1332,7 @@
                }
                String value = tableField.value();
                if(net.logstash.logback.encoder.org.apache.commons.lang3.StringUtils.isNotBlank(value)){
                    fieldMap.put(declaredField.getName(), value);
                    fieldMap.put(declaredField.getName(), value.trim());
                }
            }
        }
@@ -1345,6 +1345,9 @@
                ((!"".equals(existField) && !existField.contains(propertyName.toLowerCase()+","))||"data".equals(propertyName))) {
                Method readMethod = descriptor.getReadMethod();
                Object result = readMethod.invoke(bean, new Object[0]);
                if(result instanceof String){
                    result=((String) result).trim();
                }
                if (result != null) {
                    if ("data".equals(propertyName)){
@@ -1366,7 +1369,11 @@
                    && Func.isBlank(String.valueOf(mapData.get(o)))){
                    continue;
                }
                returnMap.put(String.valueOf(o).toLowerCase(),mapData.get(o));
                Object result=mapData.get(o);
                if(result instanceof String){
                    result=((String) result).trim();
                }
                returnMap.put(String.valueOf(o).toLowerCase(),result);
            }
        }
        return returnMap;
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/algorithm/CustomRomanSerialAlgorithmExample.java
@@ -1,45 +1,161 @@
package com.vci.ubcs.code.algorithm;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vci.ubcs.code.annotation.MdmSerialAlgorithm;
import com.vci.ubcs.code.annotation.MdmSerialAlgorithmMethod;
import com.vci.ubcs.code.dto.CodeCustomSerialDTO;
import com.vci.ubcs.code.entity.CodeAllCode;
import com.vci.ubcs.code.enumpack.CodeBZOperationTypeEnum;
import com.vci.ubcs.code.service.ICodeAllCodeService;
import com.vci.ubcs.code.vo.pagemodel.CodeBasicSecVO;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import io.reactivex.internal.util.LinkedArrayList;
import net.logstash.logback.encoder.org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.management.StringValueExp;
import java.util.*;
import java.util.stream.Collectors;
import static com.vci.ubcs.code.constant.MdmEngineConstant.*;
/****
 * è‡ªå®šä¹‰ç½—马流水算法自定义类
 */
@MdmSerialAlgorithm(text = "自定义罗马流水",serialType="custom_serial_roman",description = "自定义罗马流水算法")
@Component
public class CustomRomanSerialAlgorithmExample {
    /**
     * ç¼–码规则的服务
     */
    @Autowired
    private ICodeAllCodeService codeAllCodeService;
    /***
     * æ“ä½œç±»åž‹
     */
    @Value("${bzApply.operationType:operationType}")
    private String operationType;
    /***
     * æ˜¯å¦ç³»åˆ—
     */
    @Value("${bzApply.isSeries:isSeries}")
    private String isSeries;
    /***
     * æ˜¯å¦å˜æ›´ç³»åˆ—
     */
    @Value("${bzApply.isEditSeries:isEditSeries}")
    private String isEditSeries;
    /***
     * æºæ ‡å‡†å·
     */
    @Value("${bzApply.oldCode:oldCode}")
    private String oldCode;
    /***
     *发布时间
     */
    @Value("${bzApply.releaseTime:releaseTime}")
    private String releaseTime;
    /***
     * æŽ§åˆ¶æ˜¯å¦å†™å…¥å€¼çš„码段名称
     */
    @Value("${bzApply.yearSecName:年代号}")
    private String yearSecName;
    /**
     * ç”Ÿæˆç½—马流水号的方法
     * @return æµæ°´å·çš„信息
     */
    @MdmSerialAlgorithmMethod
    public String serialGenerate(CodeCustomSerialDTO codeCustomSerialDTO){
        //
        codeCustomSerialDTO.getSerialUnitString();
        CodeBasicSecVO secVO= codeCustomSerialDTO.getSerialCodeCodeBasicSec();
        String currentFlowValue=codeCustomSerialDTO.getCurrentFlowValue();
//        boolean isSeriesValue=false;
        boolean isCrete=false;//是否成产罗马顺序号
        String romanValue="";
        List<CodeBasicSecVO> codeBasicSecVOList= codeCustomSerialDTO.getCodeBasicSecVOList();
        int yearSecValue=0;//年代号
        List<String> secValueList=codeCustomSerialDTO.getSecValueList();
        String serialUnitString=codeCustomSerialDTO.getSerialUnitString();
        //源标准类型
        boolean isSeriesValue=codeCustomSerialDTO.getBaseModel().getData().containsKey(isSeries)&&StringUtils.isNotBlank(codeCustomSerialDTO.getBaseModel().getData().get(isSeries))&&codeCustomSerialDTO.getBaseModel().getData().get(isEditSeries).equals("true")?true:false;
        //是否变更系列
        boolean isEditSeriesValue=codeCustomSerialDTO.getBaseModel().getData().containsKey(isEditSeries)&&StringUtils.isNotBlank(codeCustomSerialDTO.getBaseModel().getData().get(isEditSeries))&&codeCustomSerialDTO.getBaseModel().getData().get(isEditSeries).equals("true")?true:false;
        //如果标修订为标准,原有表准系列号不变,则比较年代号,如果年代号跨年(次年1月后则为跨年)
        String operationTypeValue=codeCustomSerialDTO.getBaseModel().getData().containsKey(operationType)&&StringUtils.isNotBlank(codeCustomSerialDTO.getBaseModel().getData().get(operationType))?codeCustomSerialDTO.getBaseModel().getData().get(operationType):"";
        //发布时间
        String releaseTimeValue=codeCustomSerialDTO.getBaseModel().getData().containsKey(releaseTime)&&StringUtils.isNotBlank(codeCustomSerialDTO.getBaseModel().getData().get(releaseTime))?codeCustomSerialDTO.getBaseModel().getData().get(releaseTime):"";
        if(operationTypeValue.equals(CodeBZOperationTypeEnum.CODE_BZ_AMENDMENT.getValue())){//如果是修订
            //源标准号
            String oldCodeValue=codeCustomSerialDTO.getBaseModel().getData().containsKey(oldCode)&&StringUtils.isNotBlank(codeCustomSerialDTO.getBaseModel().getData().get(oldCode))?codeCustomSerialDTO.getBaseModel().getData().get(oldCode):"";
            if(StringUtils.isNotBlank(oldCodeValue)){
                //还需要修改allCode的生命周期
                QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
                allCodeWrapper.in("id", VciBaseUtil.str2List(oldCodeValue));
                List<CodeAllCode>codeAllcodeList=codeAllCodeService.selectByWrapper(allCodeWrapper);
                if(!CollectionUtils.isEmpty(codeAllcodeList)){
                    String codeDelimit=codeAllcodeList.get(0).getCodeDelimit();
                    String[] secValues= StringUtils.splitByWholeSeparatorPreserveAllTokens(codeDelimit,SERIAL_VALUE_SPACE);
                    int yearIndex=0;
                    if((!isSeriesValue&&!isEditSeriesValue)||(isSeriesValue&&isSeriesValue)){//如果是标准修订为标准,或者系列修订为系列时候,则判断年代号
                        for (int i=0;i<codeBasicSecVOList.size();i++){
                            CodeBasicSecVO codeBasicSecVO=codeBasicSecVOList.get(i);
                            if(codeBasicSecVO.getName().equals(yearSecName)){
                                yearSecValue=Integer.parseInt((secValues[i]));
                                yearIndex=i;
                            }
                        }
                        //则获取年代号比较,如果年代号跨年则需要不需要增加罗马流水,直接改年代号,如果不跨年则增加流水
                        if(StringUtils.isNotBlank(releaseTimeValue)){//发布时间
                         String[] yearMoths=    StringUtils.splitByWholeSeparatorPreserveAllTokens(releaseTimeValue,"-");
                         String[] serialUnitStrings=StringUtils.splitByWholeSeparatorPreserveAllTokens(serialUnitString,SERIAL_UNIT_SPACE);
                         List<String>serialUnitStringList=new ArrayList<>();
                         serialUnitStringList= Arrays.asList(serialUnitStrings);
                         int newYear=0;
                            int month=0;
                          if(yearMoths.length>2){
                              newYear=Integer.parseInt(yearMoths[0]);
                              month=Integer.parseInt(yearMoths[1]);
                          }
                          if(newYear>yearSecValue&&month>1){
                              secValueList.set(yearIndex,String.valueOf(newYear));
                              serialUnitStringList.set(yearIndex, String.valueOf(newYear));
                              codeCustomSerialDTO.setSecValueList(secValueList);
                              String newSerialUnitString = serialUnitStringList.size() == 0 ? EMPTY_SERIAL_UNIT : serialUnitStringList.stream().collect(Collectors.joining(SERIAL_UNIT_SPACE));
                              codeCustomSerialDTO.setSerialUnitString(newSerialUnitString);
                          }else{
                              isCrete=true;
                          }
                        }
                    }
                }
            }
        Double newThisSerialValue = 0d;
        if(StringUtils.isBlank(currentFlowValue)){
            //第一个编码
            newThisSerialValue = VciBaseUtil.getDouble(secVO.getSerialStart());
        }else {
            //流水号肯定是数字
            //将罗马流水转为数字流水
            int arabicValue=VciBaseUtil.convertRomanToArabic(currentFlowValue);
            newThisSerialValue = (double)(arabicValue + secVO.getSerialStep()) ;
        }
        //要看是否超过最大的流水值
        if (newThisSerialValue >= secVO.getCodeFillLimit()) {
            throw new VciBaseException("流水号已经超过允许的最大流水值{0}", new String[]{secVO.getCodeFillLimit().toString()});
        if(isCrete){
            CodeBasicSecVO secVO= codeCustomSerialDTO.getSerialCodeCodeBasicSec();
            String currentFlowValue=codeCustomSerialDTO.getCurrentFlowValue();
            Double newThisSerialValue = 0d;
            if(StringUtils.isBlank(currentFlowValue)){
                //第一个编码
                newThisSerialValue = VciBaseUtil.getDouble(secVO.getSerialStart());
            }else {
                //流水号肯定是数字
                //将罗马流水转为数字流水
                int arabicValue=VciBaseUtil.convertRomanToArabic(currentFlowValue);
                newThisSerialValue = (double)(arabicValue + secVO.getSerialStep()) ;
            }
            //要看是否超过最大的流水值
            if (newThisSerialValue >= secVO.getCodeFillLimit()) {
                throw new VciBaseException("流水号已经超过允许的最大流水值{0}", new String[]{secVO.getCodeFillLimit().toString()});
            }
            //将数字流水转为罗马流水
            romanValue=VciBaseUtil.convertArabicToRoman(newThisSerialValue.intValue());
        }
        //将数字流水转为罗马流水
        String romanValue=VciBaseUtil.convertArabicToRoman(newThisSerialValue.intValue());
        return romanValue;
    }
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/algorithm/Test.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
package com.vci.ubcs.code.algorithm;
import java.util.Arrays;
import java.util.List;
public class Test {
    public static void main(String[] args) {
        String []res={"5","6","7","8","3"};
        List<String> newList=Arrays.asList(res);
        System.out.println(res);
    }
}
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/annotation/MdmSerialAlgorithm.java
@@ -1,5 +1,6 @@
package com.vci.ubcs.code.annotation;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
@@ -18,9 +19,13 @@
public @interface MdmSerialAlgorithm {
    /**
     * bean的名称
     * å€¼ï¼Œå®žé™…就是这个注解所在的类的全路径
     * @return å€¼
     */
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
    /**
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/MdmEngineController.java
@@ -6,10 +6,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vci.ubcs.code.applyjtcodeservice.vo.BaseModelVO;
import com.vci.ubcs.code.dto.CodeDeleteBatchDTO;
import com.vci.ubcs.code.dto.CodeExportAttrDTO;
import com.vci.ubcs.code.dto.CodeOrderDTO;
import com.vci.ubcs.code.dto.CodeOrderSecDTO;
import com.vci.ubcs.code.dto.*;
import com.vci.ubcs.code.dto.datapush.BaseModelDTO;
import com.vci.ubcs.code.service.MdmEngineService;
import com.vci.ubcs.code.service.MdmIOService;
@@ -746,4 +743,15 @@
    public R processChangeStatus(@RequestBody FlowStatusDTO flowDTO){
        return engineService.processChangeStatus(flowDTO);
    }
    /**
     * æ ‡å‡†ç”³è¯·å’Œä¿®è®¢ç”¨
     * @param codeBZApplyDTO ç¼–码申请相关的信息,需要有属性和码段相关的信息
     * @return æ‰§è¡Œç»“æžœ
     */
    @PostMapping("/addSaveBZ")
    @VciBusinessLog(operateName = "申请单个编码")
    public R addSaveBZ (@RequestBody CodeBZApplyDTO codeBZApplyDTO) throws Exception {
        return R.success(engineService.addSaveBZ(codeBZApplyDTO));
    }
}
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/enumpack/CodeBZOperationTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,135 @@
package com.vci.ubcs.code.enumpack;
import com.vci.ubcs.starter.web.enumpck.BaseEnum;
/***
 * æ ‡å‡†æ“ä½œç±»åž‹
 */
public enum CodeBZOperationTypeEnum implements BaseEnum {
    /**
     * åˆ¶å®š
     */
    CODE_BZ_FORMULATE("1","制定"),
    /**
     * ä¿®è®¢
     */
    CODE_BZ_AMENDMENT("2","修订"),
    /***
     * æ›´æ”¹
     */
    CODE_BZ_EDIT("3","更改"),
    /***
     * ä½œåºŸ
     */
    CODE_BZ_DISABLE("4","作废"),
    /***
     * å¤‡æŸ¥
     */
    CODE_BZ_FOR_REFERENCE("5"," å¤‡æŸ¥");
    /**
     * æžšä¸¾çš„值
     */
    private String value;
    /**
     * æžšä¸¾æ˜¾ç¤ºæ–‡æœ¬
     */
    private String text;
    /**
     * èŽ·å–æžšä¸¾å€¼
     *
     * @return æžšä¸¾å€¼
     */
    @Override
    public String getValue() {
        return value;
    }
    /**
     * è®¾ç½®æžšä¸¾å€¼
     *
     * @param value æžšä¸¾å€¼
     */
    public void setValue(String value) {
        this.value = value;
    }
    /**
     * èŽ·å–æžšä¸¾æ˜¾ç¤ºæ–‡æœ¬
     *
     * @return æ˜¾ç¤ºæ–‡æœ¬
     */
    @Override
    public String getText() {
        return text;
    }
    /**
     * è®¾ç½®æ˜¾ç¤ºæ–‡æœ¬
     *
     * @param text æ˜¾ç¤ºæ–‡æœ¬
     */
    public void setText(String text) {
        this.text = text;
    }
    /**
     * æž„造函数
     *
     * @param value å€¼
     * @param text  æ˜¾ç¤ºæ–‡æœ¬
     */
    private CodeBZOperationTypeEnum(String value, String text) {
        this.value = value;
        this.text = text;
    }
    /**
     * æ ¹æ®åç§°èŽ·å–å¯¹åº”çš„æžšä¸¾å€¼
     *
     * @param text åç§°
     * @return æžšä¸¾å€¼
     */
    public static String getValueByText(String text) {
        for (CodeBZOperationTypeEnum wenum : CodeBZOperationTypeEnum.values()) {
            if (wenum.getText().equalsIgnoreCase(text)) {
                return wenum.getValue();
            }
        }
        return "";
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–åç§°
     *
     * @param value æžšä¸¾å€¼
     * @return åç§°
     */
    public static String getTextByValue(String value) {
        for (CodeBZOperationTypeEnum wenum : CodeBZOperationTypeEnum.values()) {
            if (wenum.getValue().equalsIgnoreCase(value)) {
                return wenum.getText();
            }
        }
        return "";
    }
    /**
     * æ ¹æ®æžšä¸¾å€¼èŽ·å–æžšä¸¾å¯¹è±¡
     *
     * @param value æžšä¸¾å€¼
     * @return æžšä¸¾å¯¹è±¡ï¼Œä¸å­˜åœ¨æ—¶å€™è¿”回null
     */
    public static CodeBZOperationTypeEnum forValue(String value) {
        for (CodeBZOperationTypeEnum wenum : CodeBZOperationTypeEnum.values()) {
            if (wenum.getValue().equalsIgnoreCase(value)) {
                return wenum;
            }
        }
        return null;
    }
}
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/MdmEngineService.java
@@ -5,6 +5,7 @@
import com.vci.ubcs.code.applyjtcodeservice.vo.BaseModelVO;
import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO;
import com.vci.ubcs.code.bo.CodeTemplateAttrSqlBO;
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.datapush.BaseModelDTO;
@@ -493,4 +494,11 @@
     * @param parameter ä¼ å…¥æ•°æ®,classifyGroupCode:配置的中的分类顶节点,oid:选择节点的oid
     */
    R checkGroupCode(Map<String, String> parameter);
    /**
     * æ ‡å‡†ç”³è¯·å’Œä¿®è®¢ç”¨
     * @param codeBZApplyDTO ç¼–码申请相关的信息,需要有属性和码段相关的信息
     * @return æ‰§è¡Œç»“æžœ
     */
    String addSaveBZ(CodeBZApplyDTO codeBZApplyDTO) throws Exception;
}
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/MdmProductCodeService.java
@@ -30,4 +30,14 @@
     */
    Boolean recycleCode(String btmId, Collection<String> businessOidCollection);
    /**
     * ç”Ÿæˆç¼–码--并且保存数据-方法加锁,因此不能返回batchCBO
     * @param classifyFullInfoBO åˆ†ç±»çš„全部信息
     * @param templateVO æ¨¡æ¿çš„æ˜¾ç¤ºå¯¹è±¡
     * @param ruleVO ç¼–码规则的显示对象
     * @param secDTOList å„个码段的值
     * @param dataCBOList ä¸šåŠ¡æ•°æ®
     */
    List<String> productCodeAndSaveDataBZ(CodeClassifyFullInfoBO classifyFullInfoBO, CodeClassifyTemplateVO templateVO,
                                        CodeRuleVO ruleVO, List<CodeOrderSecDTO> secDTOList, List<BaseModel> dataCBOList) throws Exception;
}
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeSerialAlgorithmServiceImpl.java
@@ -40,7 +40,8 @@
                    //Advised advised = (Advised)bean;
                    Class<?> targetClass = AopUtils.getTargetClass(bean);
                    //Class<?> targetClass = advised.getTargetSource().getTargetClass();
                    algorithmVO.setClassFullName(targetClass.getName());
                  //  algorithmVO.setClassFullName(targetClass.getName());
                    algorithmVO.setClassFullName(beanName);
                    MdmSerialAlgorithm serialAlgorithm = targetClass.getDeclaredAnnotation(MdmSerialAlgorithm.class);
                    if(serialAlgorithm==null){
                        serialAlgorithm = targetClass.getAnnotation(MdmSerialAlgorithm.class);
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
@@ -9,8 +9,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 +24,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;
@@ -115,6 +118,49 @@
     */
    @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;
    /**
     * æ¨¡æ¿çš„æœåŠ¡
@@ -822,6 +868,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
     */
    private 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{//变更为系列.则按照逻辑去处理
        }
        return "";
    }
    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
     */
    public String addSaveBZCodeNotauthUser(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
        return    addSaveBZCode(codeBZApplyDTO,authUser);
    }
    /**
     * å°è£…关键属性的查询语句
     *
@@ -873,7 +1168,7 @@
                    //不忽略大小写、不去空、不忽略全半角
                    temp = "%s";
                }
                queryKey = String.format(temp, "nvl("+ "t." + attrId +",'/')");
                queryKey = String.format(temp, "nvl("+ "t." + attrId +",'/')");
                queryValue = String.format(temp, "'" + (trim ? value.trim() : value) + "'");
                conditionMap.put(queryKey, queryValue);
            } else {
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);