package com.vci.ubcs.code.service.impl; import com.alibaba.fastjson.JSON; 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; import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO; import com.vci.ubcs.code.dto.CodeOrderSecDTO; import com.vci.ubcs.code.entity.CodeAllCode; import com.vci.ubcs.code.entity.CodeClassifyValue; import com.vci.ubcs.code.entity.CodeSerialValue; import com.vci.ubcs.code.enumpack.CodeCutTypeEnum; import com.vci.ubcs.code.enumpack.CodeGetValueTypeEnum; import com.vci.ubcs.code.enumpack.CodeLevelTypeEnum; import com.vci.ubcs.code.enumpack.CodeSecTypeEnum; import com.vci.ubcs.code.lifecycle.CodeAllCodeLC; import com.vci.ubcs.code.mapper.CodeClassifyValueMapper; import com.vci.ubcs.code.mapper.CodeSerialValueMapper; import com.vci.ubcs.code.service.MdmEngineService; import com.vci.ubcs.code.service.MdmProductCodeService; import com.vci.ubcs.code.vo.pagemodel.CodeBasicSecVO; import com.vci.ubcs.code.vo.pagemodel.CodeClassifyTemplateVO; import com.vci.ubcs.code.vo.pagemodel.CodeClassifyVO; import com.vci.ubcs.code.vo.pagemodel.CodeRuleVO; import com.vci.ubcs.starter.exception.VciBaseException; import com.vci.ubcs.starter.revision.model.BaseModel; import com.vci.ubcs.starter.util.DefaultAttrAssimtUtil; import com.vci.ubcs.starter.util.MdmBtmTypeConstant; 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; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.secure.BladeUser; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.WebUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; 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 { /** * 流水号的相关的信息 */ @Resource private CodeSerialValueMapper serialValueMapper; /** * 流水号的相关的信息 */ @Resource private CodeClassifyValueMapper codeClassifyValueMapper; /** * 所有的编码的内容 */ @Resource private CodeAllCodeServiceImpl codeAllCodeService; /** * 所有的编码的内容 */ @Resource @Lazy private MdmEngineService mdmEngineService; /** * 公式的服务 */ @Autowired private FormulaServiceImpl formulaService; @Override @Transactional(rollbackFor = Exception.class) public List productCodeAndSaveData(CodeClassifyFullInfoBO classifyFullInfoBO, CodeClassifyTemplateVO templateVO, CodeRuleVO ruleVO, List secDTOList, List dataCBOList,BladeUser user) throws Exception { dataCBOList = dataCBOList.stream().sorted(((o1, o2) -> o1.getCreateTime().compareTo(o2.getCreateTime()))).collect(Collectors.toList()); List codeList = new ArrayList<>(); final CodeRuleVO finalRuleVO = ruleVO; /***** * 保证并发的时候,最大流水号都对的,但是这种加锁有弊端 */ if(dataCBOList.stream().anyMatch(cbo-> StringUtils.isNotBlank(cbo.getId())) // && StringUtils.isNotBlank(cbo.getAttributeValue(CODE_SEC_LENGTH_FIELD)) ){ //是历史数据导入 //主要是为了录入最大流水号和allcode //SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo(); List allCodeDOList = new CopyOnWriteArrayList<>(); Map> maxSerialMap = new HashMap<>(); // TODO 多线程流引发的问题已修改 dataCBOList.parallelStream().forEach(cbo->{ log.info("code:----->"+cbo.getId()); //VciBaseUtil.setCurrentUserSessionInfo(sessionInfo); String code = cbo.getId(); List serialUnitList = new CopyOnWriteArrayList<>(); //String seclenghStr=cbo.getData().get(CODE_SEC_LENGTH_FIELD); String[] secLengths = cbo.getData().get(CODE_SEC_LENGTH_FIELD).split("#"); cbo.getData().remove(CODE_SEC_LENGTH_FIELD);//将此key除去 cbo.getData().remove(IMPORT_ROW_INDEX);//将此key除去 cbo.getData().remove("codeclassifyid");//将此key除去 List secVOList = finalRuleVO.getSecVOList().stream().sorted(((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()))).collect(Collectors.toList()); Map serialValueMap = new HashMap<>(); Map secVOMap = secVOList.stream().collect(Collectors.toMap(s -> s.getOid(), t -> t)); Map serialSecOidIndexMap=new HashMap<>(); LinkedList codeValueList=new LinkedList<>(); for (int i = 0; i < secLengths.length; i++) { CodeBasicSecVO secVO = secVOList.get(i); String thisSecValue = ""; /*if(i == 0){ thisSecValue = seclenghStr.contains("#")?code.substring(0,VciBaseUtil.getInt(secLengths[i])):code; } else if(i == secLengths.length-1){ //最后 thisSecValue = seclenghStr.contains("#")?code.substring(VciBaseUtil.getInt(secLengths[i-1]),code.length()):code; }else {*/ int start = 0; for (int j = 0; j < i; j++) { start += VciBaseUtil.getInt(secLengths[j]); } thisSecValue = code.substring(start,start+VciBaseUtil.getInt(secLengths[i])); // } if(VciBaseUtil.getBoolean(secVO.getSerialDependFlag())){ serialUnitList.add(thisSecValue); serialSecOidIndexMap.put(secVO.getOid(),i); } if(CODE_SERIAL_SEC.getValue().equalsIgnoreCase(secVO.getSecType())){ serialValueMap.put(secVO.getOid(),thisSecValue); } codeValueList.add(thisSecValue); } List serialUnFileStringList = new ArrayList<>(); AtomicReference newSerialUnitString = new AtomicReference<>(""); if(!CollectionUtils.isEmpty(serialValueMap)){ AtomicInteger index = new AtomicInteger(); serialValueMap.forEach((secOid,secValue)->{ //要看是不是补位的 CodeBasicSecVO secVO = secVOMap.get(secOid); ListnewSerialUnitList=new ArrayList<>(); newSerialUnitList.addAll(serialUnitList); if(index.get() ==0){ if(serialSecOidIndexMap.containsKey(secOid)) { int num = serialSecOidIndexMap.get(secOid); newSerialUnitList.set(num, ""); } } String serialUnitString = newSerialUnitList.size() == 0 ? EMPTY_SERIAL_UNIT : newSerialUnitList.stream().collect(Collectors.joining(SERIAL_UNIT_SPACE)); newSerialUnitString.set(serialUnitString); index.getAndIncrement(); String serialDb = ""; // 截取掉前后缀之后的码段 String subSecValue = killPriffixSuffix(secValue, secVO.getPrefixCode(), secVO.getSuffixCode()); if(OsCodeFillTypeEnum.NONE.getValue().equalsIgnoreCase(secVO.getCodeFillType())){ //不补码 //把所有不是数字的去掉,因为可能会是老数据,新规则 //serialDb = VciBaseUtil.getDouble(killUnNumberChar(subSecValue)); //serialDb = killUnNumberChar(subSecValue); serialDb=subSecValue; }else { //左右填充的,我们需要 serialDb = killFillChar(subSecValue,secVO.getCodeFillSeparator(), OsCodeFillTypeEnum.LEFT.getValue().equalsIgnoreCase(secVO.getCodeFillType())); } Double newSerialDb = CustomSerialEnum.getDoubleCustomSerialValue(serialDb,secVO.getCustomCodeSerialType()); //TODO: 20240822需要这块代码是同步性的,maxSerialMap这儿会因为线程受影响,修改后测试多次总数为5000条一次导入耗费时间为3分30秒左右 synchronized(this) { HashMap thisUnitMaxMap = maxSerialMap.getOrDefault(serialUnitString, new HashMap<>()); Double maxValue=newSerialDb; if(thisUnitMaxMap.containsKey(secOid)){ String newMaxValue = thisUnitMaxMap.getOrDefault(secOid,""); maxValue = StringUtils.isBlank(newMaxValue)?-1:VciBaseUtil.getDouble(newMaxValue); if(maxValue < newSerialDb){ maxValue = newSerialDb; } } String newMaxValue=CustomSerialEnum.getStringCustomSerialValue(maxValue,secVO.getCustomCodeSerialType()); serialDb=CustomSerialEnum.getStringCustomSerialValue(newSerialDb,secVO.getCustomCodeSerialType()); thisUnitMaxMap.put(secOid,newMaxValue); maxSerialMap.put(serialUnitString,thisUnitMaxMap); serialUnFileStringList.add(String.valueOf(serialDb)); } }); } CodeAllCode allCodeDO = new CodeAllCode(); DefaultAttrAssimtUtil.addDefaultAttrAssimt(allCodeDO, MdmBtmTypeConstant.CODE_ALL_CODE,user); allCodeDO.setCodeClassifyOid(classifyFullInfoBO.getCurrentClassifyVO().getOid()); allCodeDO.setCodeRuleOid(finalRuleVO.getOid()); allCodeDO.setId(cbo.getId()); allCodeDO.setCodeClassifyTemplateOid(templateVO.getOid()); allCodeDO.setCreateCodeBtm(cbo.getBtmname()); allCodeDO.setCreateCodeOid(cbo.getOid()); allCodeDO.setSerialUnit(newSerialUnitString.get()); 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.setLctid("codeAllCodeLC"); allCodeDO.setCodeDelimit(codeValueList.stream().collect(Collectors.joining(SERIAL_VALUE_SPACE)));//添加链接符 allCodeDOList.add(allCodeDO); }); //处理最大的流水号 List addSerialValueList = new ArrayList<>(); List editSerialValueList = new ArrayList<>(); log.info("maxSerialMap:----->"+maxSerialMap.size()); maxSerialMap.forEach((serialUnit,secOidMaxMap)->{ secOidMaxMap.forEach((secOid,maxSerial)->{ QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("codeRuleOid", finalRuleVO.getOid()); queryWrapper.eq("serialUnit", serialUnit); //这个字段是为了解决多个流水的问题 queryWrapper.eq("codeSecOid", secOid); List serialValueDOS = serialValueMapper.selectList(queryWrapper); log.info("serialValueDOS--->"+serialValueDOS.size()); if (!CollectionUtils.isEmpty(serialValueDOS)) { CodeSerialValue serialValueDO = serialValueDOS.get(0); log.info("oldmaxSerial--->"+serialValueDO.getMaxSerial()+"---- newmaxSerial---->"+maxSerial); if(VciBaseUtil.getDouble(serialValueDO.getMaxSerial())> ruleGroup = allCodeDOList.stream().collect(Collectors.groupingBy(s -> s.getCodeRuleOid())); Map codeDOMap = allCodeDOList.stream().collect(Collectors.toMap(s -> s.getCodeRuleOid() + "${SEP}" + s.getId(), t -> t)); List addCodeDOs = new CopyOnWriteArrayList<>(); List editCodeDOs = new CopyOnWriteArrayList<>(); ruleGroup.forEach((ruleOid,allCodeDOS)->{ VciBaseUtil.switchCollectionForOracleIn(allCodeDOS).stream().forEach(codeDOs->{ QueryWrapper allCodeWrapper = new QueryWrapper<>(); allCodeWrapper.eq("coderuleoid",ruleOid); allCodeWrapper.in("id", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(codeDOs.stream().map(s->s.getId()).collect(Collectors.toList()).toArray(new String[0])) + ")"); List existCodes = codeAllCodeService.selectByWrapper(allCodeWrapper); if(!CollectionUtils.isEmpty(existCodes)){ existCodes.stream().forEach(existCode->{ String rule_id = existCode.getCodeRuleOid() + "${SEP}" + existCode.getId(); if(codeDOMap.containsKey(rule_id)){ CodeAllCode newCodeDO = codeDOMap.get(rule_id); existCode.setCreateCodeOid(newCodeDO.getOid()); existCode.setCreateCodeBtm(newCodeDO.getCreateCodeBtm()); existCode.setCodeClassifyTemplateOid(newCodeDO.getCodeClassifyTemplateOid()); existCode.setCodeClassifyOid(newCodeDO.getCodeClassifyOid()); existCode.setLcStatus(newCodeDO.getLcStatus()); editCodeDOs.add(existCode); } }); } }); }); if(!CollectionUtils.isEmpty(editCodeDOs)){ Set exitIds = editCodeDOs.stream().map(s -> s.getCodeRuleOid() + "${SEP}" + s.getId()).collect(Collectors.toSet()); addCodeDOs = allCodeDOList.stream().filter(s -> !exitIds.contains(s.getCodeRuleOid() + "${SEP}" + s.getId())).collect(Collectors.toList()); }else{ addCodeDOs = allCodeDOList; } if(!CollectionUtils.isEmpty(editCodeDOs)){ codeAllCodeService.updateBatchById(editCodeDOs); } if(!CollectionUtils.isEmpty(addCodeDOs)){ Map statusMap = addCodeDOs.stream().collect(Collectors.toMap(s -> s.getOid(), s -> s.getLcStatus())); addCodeDOs.stream().filter(s -> StringUtils.equalsIgnoreCase("codeallcode",s.getBtmname())).forEach(s -> { s.setLcStatus(statusMap.get(s.getOid())); }); //通过ID来进行去重 List distinctCodeAllCOdes = addCodeDOs.stream().collect(Collectors .collectingAndThen( Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CodeAllCode::getId))), ArrayList::new)); if(distinctCodeAllCOdes.size() != addCodeDOs.size() ){ throw new VciBaseException("编码数据重复,无法保存,请注意!"); } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("CREATECODEBTM",addCodeDOs.get(0).getCreateCodeBtm()); wrapper.in("ID",addCodeDOs.stream().map(CodeAllCode::getId).collect(Collectors.toList())); List codeAllCodes = codeAllCodeService.selectByWrapper(wrapper); List takeBack = codeAllCodes.stream().filter(e -> e.getLcStatus().equals("TakeBack")).collect(Collectors.toList()); if(codeAllCodes.size()>takeBack.size()){ throw new ServiceException("生成编码数据ID已有历史记录,请确认如下生成的ID数据:"+ addCodeDOs.stream().map(CodeAllCode::getId).collect(Collectors.toList())); } for (CodeAllCode codeAllCode : takeBack) { codeAllCode.setTs(new Date()); codeAllCode.setLastModifyTime(new Date()); codeAllCode.setLastModifier(Func.isNotEmpty(user) ? user.getAccount():AuthUtil.getUserAccount()); for (int i = 0; i < addCodeDOs.size(); i++) { if(codeAllCode.getId().equals(addCodeDOs.get(i).getId())){ codeAllCode.setCreateCodeOid(addCodeDOs.get(i).getCreateCodeOid()); codeAllCode.setLcStatus(addCodeDOs.get(i).getLcStatus()); addCodeDOs.remove(i); } } /*Iterator iterator = addCodeDOs.iterator(); while (iterator.hasNext()){ CodeAllCode next = iterator.next(); if(codeAllCode.getId().equals(next.getId())){ codeAllCode.setCreateCodeOid(next.getCreateCodeOid()); codeAllCode.setLcStatus(next.getLcStatus()); // TODO: 这儿先暂时注释掉,没看懂这儿为什么要这样做,导致报错 iterator.remove(); } }*/ } if(takeBack.size()>0){ codeAllCodeService.updateBatchById(takeBack); } codeAllCodeService.saveBatch(addCodeDOs); } mdmEngineService.insertBatchByType(dataCBOList.get(0).getBtmname(),dataCBOList); } return codeList; }else { List secVOList = finalRuleVO.getSecVOList().stream().sorted(((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()))).collect(Collectors.toList()); List serialUnitList = new LinkedList<>(); List secValueList = new ArrayList<>(); Map secValueMap = secDTOList.stream().collect(Collectors.toMap(s -> s.getSecOid(), s -> s.getSecValue()==null?"":s.getSecValue())); List serialSecVOList = new ArrayList<>(); List attrSecVOList = new ArrayList<>(); for (int i = 0; i < secVOList.size(); i++) { CodeBasicSecVO secVO = secVOList.get(i); try{ switchSecValue(secVO, secValueMap, classifyFullInfoBO, serialSecVOList, attrSecVOList, serialUnitList, secValueList); }catch (Exception e){ throw new ServiceException("码值转换时出现错误,原因:"+e.getMessage()); } } //处理属性码段和流水码段 Map> lastMaxSerialValueMap = new HashMap<>(); List allCodeDOList = new ArrayList<>(); //已经存储的最大流水号的内容 Map> 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 thisSecValueList = new LinkedList<>(); for (int j = 0; j < secValueList.size(); j++) { thisSecValueList.add(secValueList.get(j)); } List 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); String serialUnitString = thisSerialUnitList.size() == 0 ? EMPTY_SERIAL_UNIT : thisSerialUnitList.stream().collect(Collectors.joining(SERIAL_UNIT_SPACE)); switchSerialSecValue(cbo,serialSecVOList, attrSevIsSerialDepend, finalRuleVO, serialUnitString, maxSerialValueMap, thisSecValueList, lastMaxSerialValueMap, i == 0); //组装编码的值 cbo.setId(thisSecValueList.stream().collect(Collectors.joining())); codeList.add(cbo.getId()); StringBuilder sb = new StringBuilder(); //把码段里面都找一下流水号 for (int j = 0; j < serialSecVOList.size(); j++) { CodeBasicSecVO secVO = serialSecVOList.get(j); String serialValue = lastMaxSerialValueMap.getOrDefault(secVO.getOid(), new HashMap<>()).getOrDefault(serialUnitString, ""); if (serialValue != null) { 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(),codeDelimiter); } //处理最大流水 saveSerialValue( finalRuleVO, lastMaxSerialValueMap, maxSerialValueMap); allCodeDOList.stream().forEach( allCode -> {DefaultAttrAssimtUtil.addDefaultAttrAssimt(allCode,"codeallcode",user);allCode.setLctid("codeAllCodeLC");} ); Map 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 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 wrapper = new QueryWrapper<>(); wrapper.eq("CREATECODEBTM",allCodeDOList.get(0).getCreateCodeBtm()); wrapper.in("ID",allCodeDOList.stream().map(CodeAllCode::getId).collect(Collectors.toList())); List codeAllCodes = codeAllCodeService.selectByWrapper(wrapper); List 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(Func.isNotEmpty(user) ? user.getAccount():AuthUtil.getUserAccount()); for (int i = 0; i < allCodeDOList.size(); i++) { if(codeAllCode.getId().equals(allCodeDOList.get(i).getId())){ codeAllCode.setCreateCodeOid(allCodeDOList.get(i).getCreateCodeOid()); codeAllCode.setLcStatus(allCodeDOList.get(i).getLcStatus()); allCodeDOList.remove(i); } } /*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 attrSecVOList 属性码段的显示对象 * @param cbo 业务数据,用于获取码段的值 * @param thisSecValueList 码值的列表 * @param attrSevIsSerialDepend 是否有作为流水依据 * @param serialUnitList 流水依据的内容 * 还需要后续的一个移植将会涉及到其他的服务 */ private void switchAttrSecValue(List attrSecVOList, BaseModel cbo, List thisSecValueList, boolean attrSevIsSerialDepend, List serialUnitList){ if (!CollectionUtils.isEmpty(attrSecVOList)) { attrSecVOList.stream().forEach(attrSevVO -> { String value = ""; if (StringUtils.isNotBlank(attrSevVO.getGetValueClass())) { //使用组合规则来处理的 value = getValueByFormulaForCBO(cbo, attrSevVO.getGetValueClass()); } else { value = cbo.getData().get(attrSevVO.getReferAttributeId()); } if (value == null) { value = ""; } //替换secValueList里面的内容 for (int j = 0; j < thisSecValueList.size(); j++) { String secValue = thisSecValueList.get(j); if (secValue.equalsIgnoreCase("${attr_" + attrSevVO.getOid() + "}")) { // TODO: 属性码段生成码值后,拼接前后缀 thisSecValueList.set(j, joinPreffixAndSuffix(attrSevVO,value)); } } if (attrSevIsSerialDepend) { //是流水依赖的话,需要去替换一下 for (int j = 0; j < serialUnitList.size(); j++) { String secValue = serialUnitList.get(j); if (secValue.equalsIgnoreCase("${attr_" + attrSevVO.getOid() + "}")) { serialUnitList.set(j, joinPreffixAndSuffix(attrSevVO,value)); } } } }); } } /** * 转换流水码段的值 * @param serialSecVOList 流水码段 * @param secDTOS;流水值 * @param attrSevIsSerialDepend 是否有属性码段参与流水 * @param ruleVO 规则的内容 * @param serialUnitMap 流水依据 * @param maxSerialValueMap 最大的流水号 * @param thisSecValueList 本次的码值 * @param lastMaxSerialValueMap 封装后 * @param firstData 是否为第一条数据 */ private void switchSerialSecValueBZ(BaseModel cbo,List secDTOS, List serialSecVOList,boolean attrSevIsSerialDepend, CodeRuleVO ruleVO,Map serialUnitMap, Map> maxSerialValueMap,List thisSecValueList, Map> lastMaxSerialValueMap,boolean firstData){ if (!CollectionUtils.isEmpty(serialSecVOList)) { Map attrNameIdMap = secDTOS.stream().collect(Collectors.toMap(s -> s.getSecOid(), t -> t.getSecValue().toLowerCase(Locale.ROOT),(o1, o2)->o2)); Map secIdserialValueMap=new LinkedHashMap<>(); for (int j = 0; j < serialSecVOList.size(); j++) { AtomicReference 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 codeSerialWrapper = new QueryWrapper<>(); codeSerialWrapper.eq("codeRuleOid", ruleVO.getOid()); codeSerialWrapper.eq("serialUnit", serialUnitString.get()); codeSerialWrapper.eq("codeSecOid", secVO.getOid()); List serialValueDOS = serialValueMapper.selectList(codeSerialWrapper); if (!CollectionUtils.isEmpty(serialValueDOS)) { Map 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 unitSerialMap = lastMaxSerialValueMap.getOrDefault(secVO.getOid(), new HashMap<>()); unitSerialMap.put(serialUnitString.get(), String.valueOf(thisSerialValue)); lastMaxSerialValueMap.put(secVO.getOid(), unitSerialMap); } } } } } /** * 转换流水码段的值 * @param serialSecVOList 流水码段 * @param attrSevIsSerialDepend 是否有属性码段参与流水 * @param ruleVO 规则的内容 * @param serialUnitString 流水依据 * @param maxSerialValueMap 最大的流水号 * @param thisSecValueList 本次的码值 * @param lastMaxSerialValueMap 封装后 * @param firstData 是否为第一条数据 */ private void switchSerialSecValue(BaseModel cbo, List serialSecVOList,boolean attrSevIsSerialDepend, CodeRuleVO ruleVO,String serialUnitString, Map> maxSerialValueMap,List thisSecValueList, Map> lastMaxSerialValueMap,boolean firstData){ if (!CollectionUtils.isEmpty(serialSecVOList)) { Map secIdserialValueMap=new LinkedHashMap<>(); for (int j = 0; j < serialSecVOList.size(); j++) { CodeBasicSecVO secVO = serialSecVOList.get(j); String secVOValue=""; AtomicReference newSerialUnitString= new AtomicReference<>(serialUnitString); if(j==0){ secVOValue=""; newSerialUnitString.set(serialUnitString.replace("${" + secVO.getOid() + "}", secVOValue)); }else{ CodeBasicSecVO upSecVO =serialSecVOList.get(j-1); secIdserialValueMap.forEach((key,vaule)->{ newSerialUnitString.set(serialUnitString.replace("${"+key+"}", vaule)); }); } if (attrSevIsSerialDepend || firstData) { //如果属性码段也是依赖,则每次都要查询,如果属性码段不是依赖,则只查询一次 // Map conditionMap = new HashMap<>(); // conditionMap.put("codeRuleOid", ruleVO.getOid()); // conditionMap.put("serialUnit", serialUnitString); // //这个字段是为了解决多个流水的问题 // conditionMap.put("codeSecOid", secVO.getOid()); QueryWrapper codeSerialWrapper = new QueryWrapper<>(); codeSerialWrapper.eq("codeRuleOid", ruleVO.getOid()); codeSerialWrapper.eq("serialUnit", newSerialUnitString.get()); codeSerialWrapper.eq("codeSecOid", secVO.getOid()); List serialValueDOS = serialValueMapper.selectList(codeSerialWrapper); if (!CollectionUtils.isEmpty(serialValueDOS)) { Map 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(newSerialUnitString.get())) { startValue = maxSerialValueMap.get(secVO.getOid()).get(newSerialUnitString.get()).getMaxSerial(); } if (lastMaxSerialValueMap.containsKey(secVO.getOid()) && lastMaxSerialValueMap.get(secVO.getOid()).containsKey(newSerialUnitString.get())) { //说明多个申请,之前已经加了流水号了 startValue = lastMaxSerialValueMap.get(secVO.getOid()).get(newSerialUnitString.get()); } if(StringUtils.isNotBlank(secVO.getCustomCodeSerialClass())){//自定义流水处理 String currentFlowValue=startValue; CodeCustomSerialDTO codeCustomSerialDTO=new CodeCustomSerialDTO(); codeCustomSerialDTO.setSerialUnitString(newSerialUnitString.get()); codeCustomSerialDTO.setSerialCodeCodeBasicSec(secVO); codeCustomSerialDTO.setCurrentFlowValue(startValue); 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; 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);//记录流水码段当前的值 Map unitSerialMap = lastMaxSerialValueMap.getOrDefault(secVO.getOid(), new HashMap<>()); unitSerialMap.put(newSerialUnitString.get(), String.valueOf(thisSerialValue)); lastMaxSerialValueMap.put(secVO.getOid(),unitSerialMap); } } } private String customCodeSerial(String beanName, CodeCustomSerialDTO codeCustomSerialDTO){ AtomicReference result = new AtomicReference<>(""); //BusAnnotationUtil.callForAnnotation(FlowNotifyWeb.class, FlowNotifyBefore.class,noticeInfo); //在登录之前,看看是否有插件 Map 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); Object obj =classInstance.newInstance(); Method method= classInstance.getMethod("serialGenerate",CodeCustomSerialDTO.class); method.setAccessible(Boolean.TRUE); //method.invoke(obj); Object o= method.invoke(obj,codeCustomSerialDTO); result= Func.isEmpty(o) ?"":o.toString(); } catch (ClassNotFoundException e) { throw new VciBaseException("未找到自定义流水算法类文件"); } catch (InvocationTargetException e) { throw new VciBaseException("执行自定义流水算法处理方法出现异常"); } catch (NoSuchMethodException e) { throw new VciBaseException("未找到自定义流水算法处理方法"); } catch (IllegalAccessException e) { throw new VciBaseException("执行自定义流水算法处理方法出现异常"); } catch (InstantiationException e) { e.printStackTrace(); }*/ return result.get(); } /** * 转换码值的内容 * @param secVO 码段的内容 * @param secValueMap 码值的内容,key是码段的主键,value是码值 * @param classifyFullInfoBO 分类的全部信息 * @param serialSecVOList 流水码段 * @param attrSecVOList 属性码段 * @param serialUnitList 流水依据 * @param secValueList 码值列表 */ private void switchSecValue(CodeBasicSecVO secVO,Map secValueMap, CodeClassifyFullInfoBO classifyFullInfoBO,List serialSecVOList, List attrSecVOList, List serialUnitList, List 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(Func.isBlank(codeClassifyValueDO.getId())){ codeClassifyValueDO.setId(""); } 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 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 ServiceException(String.format("【{%s}】这个码段是可变码段,但是现在输入的码值的长度({%s})超过了规定的长度{%s}", secVO.getName(), 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); secValue = "${" + secVO.getOid() + "}"; default: break; } if (VciBaseUtil.getBoolean(secVO.getSerialDependFlag())) { serialUnitList.add(secValue); } secValueList.add(secValue); } /** * 拼接前后缀 * @param secVO 码段 * @param secValue 码值 * @return */ public String joinPreffixAndSuffix(CodeBasicSecVO secVO, String secValue){ StringBuilder joinSecValue = new StringBuilder(); // 拼接前缀 if (Func.isNotEmpty(secVO.getPrefixCode()) && Func.isNotEmpty(secValue)) { joinSecValue = joinSecValue.append(secVO.getPrefixCode()); } // 在中间拼接值 joinSecValue.append(secValue); // 拼接后缀 if(Func.isNotEmpty(secVO.getSuffixCode()) && Func.isNotEmpty(secValue)){ joinSecValue = joinSecValue.append(secVO.getSuffixCode()); } return joinSecValue.toString(); } /** * 补位 * @param totalLength 总长度 * @param fillTypeEnum 补位方式 * @param text 当前的内容 * @param fillChar 补位的字符 * @return 不填充位置和长度已经达到/超过的时候不会填充 */ private String fillString(int totalLength,OsCodeFillTypeEnum fillTypeEnum,String text,String fillChar){ if(text.length() >= totalLength || OsCodeFillTypeEnum.NONE.equals(fillTypeEnum)){ //不用补位了 return text; } int balance = totalLength - text.length(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < balance; i++) { sb.append(fillChar); } if(OsCodeFillTypeEnum.LEFT.equals(fillTypeEnum)) { text = sb.toString() + text; }else { text = text + sb.toString(); } return text; } /** * 封装存储码值的对象 * @param classifyFullInfoBO 分类全部的信息 * @param ruleVO 规则的内容 * @param cbo 业务数据 * @param templateVO 模板的信息 * @param allCodeDOList 所有的码值的对象列表 * @param codeDelimiter 码值分割符 */ private void wrapperAllCode(CodeClassifyFullInfoBO classifyFullInfoBO, CodeRuleVO ruleVO, BaseModel cbo, CodeClassifyTemplateVO templateVO, List allCodeDOList, String serialUnitString, String serialValueString,String codeDelimiter){ CodeAllCode allCodeDO = new CodeAllCode(); DefaultAttrAssimtUtil.addDefaultAttrAssimt(allCodeDO, MdmBtmTypeConstant.CODE_ALL_CODE); allCodeDO.setCodeClassifyOid(classifyFullInfoBO.getCurrentClassifyVO().getOid()); allCodeDO.setCodeRuleOid(ruleVO.getOid()); allCodeDO.setId(cbo.getId()); allCodeDO.setCodeClassifyTemplateOid(templateVO.getOid()); allCodeDO.setCreateCodeBtm(cbo.getBtmname()); allCodeDO.setCreateCodeOid(cbo.getOid()); allCodeDO.setSerialUnit(serialUnitString); allCodeDO.setUnFillSerial(serialValueString); allCodeDO.setLcStatus(cbo.getLcStatus()); allCodeDO.setCodeDelimit(codeDelimiter); allCodeDOList.add(allCodeDO); } /** * 保存流水的信息 * @param ruleVO 规则的显示对象 * @param lastMaxSerialValueMap 最大的流水值映射 * @param maxSerialValueMap 依据存储的最大流水的内容 */ private void saveSerialValue(CodeRuleVO ruleVO, Map> lastMaxSerialValueMap, Map> maxSerialValueMap){ List editSerialValueDOList = new ArrayList<>(); List addSerialValueDOList = new ArrayList<>(); //存储最大流水号 lastMaxSerialValueMap.forEach((secOid,maxSerialMap)->{ maxSerialMap.forEach((unit,maxSerial)->{ CodeSerialValue serialValueDO = null; if(maxSerialValueMap.containsKey(secOid) && maxSerialValueMap.get(secOid).containsKey(unit)){ //说明有 serialValueDO = maxSerialValueMap.get(secOid).get(unit); serialValueDO.setMaxSerial(maxSerial.toString()); DefaultAttrAssimtUtil.updateDefaultAttrAssimt(serialValueDO); editSerialValueDOList.add(serialValueDO); }else{ serialValueDO = new CodeSerialValue(); DefaultAttrAssimtUtil.addDefaultAttrAssimt(serialValueDO, MdmBtmTypeConstant.CODE_SERIAL_VALUE); serialValueDO.setCodeRuleOid(ruleVO.getOid()); serialValueDO.setSerialUnit(unit); serialValueDO.setCodeSecOid(secOid); serialValueDO.setMaxSerial(maxSerial.toString()); addSerialValueDOList.add(serialValueDO); } }); }); if(!CollectionUtils.isEmpty(editSerialValueDOList)){ // batchCBO.copyFromOther(serialValueMapper.batchUpdate(editSerialValueDOList)); for (CodeSerialValue codeSerialValue : editSerialValueDOList) { serialValueMapper.updateById(codeSerialValue); } } if(!CollectionUtils.isEmpty(addSerialValueDOList)){ for (CodeSerialValue codeSerialValue : addSerialValueDOList) { serialValueMapper.insert(codeSerialValue); } // batchCBO.copyFromOther(serialValueMapper.batchInsert(addSerialValueDOList)); } } /** * 去掉不是数字的字符 * @param s 字符 * @return 替换后的值 */ private String killUnNumberChar(String s){ Integer lastUnNumberIndex = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if(!(new String(new char[]{c})).matches(RegExpConstant.NUMBER)){ lastUnNumberIndex = i; } } String value = s; if(lastUnNumberIndex >0){ value = value.substring(lastUnNumberIndex); } return value; } /** * 去掉前后缀 * @param secValue 字符 * @param priffix 前缀 * @param suffix 后缀 * @return 替换后的值 */ private String killPriffixSuffix(String secValue, String priffix,String suffix){ if (priffix != null && secValue.startsWith(priffix)) { secValue = secValue.substring(priffix.length()); } if (suffix != null && secValue.endsWith(suffix)) { secValue = secValue.substring(0, secValue.length() - suffix.length()); } return secValue; } /** * 去除补位字符 * @param s 字符 * @param fillString 补位字符 * @param left 是否左补位 * @return 替换后的值 */ private String killFillChar(String s, String fillString,boolean left){ Integer index = 0; String value = s; if(left){ for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if(!(new String(new char[]{c})).equalsIgnoreCase(fillString)){ break; } index = i; } if(index >0){ value = value.substring(index); } }else{ //从右往左找 for (int i = s.length()-1; i >=0; i++) { char c = s.charAt(i); if(!(new String(new char[]{c})).equalsIgnoreCase(fillString)){ break; } index = i; } if(index >0){ value = value.substring(0,index); } } return value; } /** * 回收码值 * * @param btmId 业务数据的业务类型 * @param businessOidCollection 业务数据的主键 * @return 是否更新成功 */ @Override public Boolean recycleCode(String btmId, Collection businessOidCollection) { // boolean oldPersistence = WebUtil.isPersistence(); // WebUtil.setPersistence(false); // BatchCBO batchCBO = new BatchCBO(); AtomicReference updateFlag = new AtomicReference<>(false); VciBaseUtil.switchCollectionForOracleIn(businessOidCollection).stream().forEach(oids-> { // Map conditionMap = new HashMap<>(); // //编码要记录为回收的状态 // conditionMap.put("createcodeoid", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(oids.toArray(new String[0])) + ")"); // conditionMap.put("createcodebtm", btmId); QueryWrapper wrapper = new QueryWrapper<>(); wrapper.in("createcodeoid",QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(oids.toArray(new String[0])) + ")"); wrapper.eq("createcodebtm", btmId); List allCodeDOS = codeAllCodeService.selectByWrapper(wrapper); // allCodeMapper.selectByCondition(conditionMap, new PageHelper(-1)); if (!CollectionUtils.isEmpty(allCodeDOS)) { allCodeDOS.stream().forEach(codeDO->{ codeDO.setLcStatus(CodeAllCodeLC.TASK_BACK.getValue()); }); updateFlag.set(codeAllCodeService.updateBatchById(allCodeDOS)); // batchCBO.copyFromOther(allCodeMapper.batchUpdate(allCodeDOS)); } }); // WebUtil.setPersistence(oldPersistence); return updateFlag.get(); } /*** * * @param classifyFullInfoBO 分类的全部信息 * @param templateVO 模板的显示对象 * @param ruleVO 编码规则的显示对象 * @param secDTOList 各个码段的值 * @param dataCBOList 业务数据 * @return * @throws Exception */ @Override public List productCodeAndSaveDataBZ(CodeClassifyFullInfoBO classifyFullInfoBO, CodeClassifyTemplateVO templateVO, CodeRuleVO ruleVO, List secDTOList, List dataCBOList) throws Exception { dataCBOList = dataCBOList.stream().sorted(((o1, o2) -> o1.getCreateTime().compareTo(o2.getCreateTime()))).collect(Collectors.toList()); List codeList = new ArrayList<>(); final CodeRuleVO finalRuleVO = ruleVO; List secVOList = finalRuleVO.getSecVOList().stream().sorted(((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()))).collect(Collectors.toList()); List serialUnitList = new LinkedList<>(); List secValueList = new ArrayList<>(); Map secValueMap = secDTOList.stream().collect(Collectors.toMap(s -> s.getSecOid(), s -> s.getSecValue()==null?"":s.getSecValue())); List serialSecVOList = new ArrayList<>(); List attrSecVOList = new ArrayList<>(); Map secOdserialUnitMap=new HashMap<>(); LinkedHashMap 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())){ int finalI = i; final int[] index = {0}; List newSerialUnitList= serialUnitList.stream().filter(secValueStr -> { return index[0]++< finalI;//除去流水的 }).collect(Collectors.toList()); String serialUnitString = newSerialUnitList.size() == 0 ? EMPTY_SERIAL_UNIT : newSerialUnitList.stream().collect(Collectors.joining(SERIAL_UNIT_SPACE)); secOdserialUnitMap.put(secVO.getOid(),serialUnitString); } } //处理属性码段和流水码段 Map> lastMaxSerialValueMap = new HashMap<>(); List allCodeDOList = new ArrayList<>(); //已经存储的最大流水号的内容 Map> 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 thisSecValueList = new LinkedList<>(); for (int j = 0; j < secValueList.size(); j++) { thisSecValueList.add(secValueList.get(j)); } List 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 serialUnitString= new AtomicReference<>(""); for (int j = 0; j < serialSecVOList.size(); j++) { CodeBasicSecVO secVO = serialSecVOList.get(j); if(lastMaxSerialValueMap.containsKey(secVO.getOid())){//此为最后需要存入流水依赖的最大流水 Map serialValueMap = lastMaxSerialValueMap.get(secVO.getOid()); serialValueMap.forEach((maxSerialUnitString,serialValue)->{ if(StringUtils.isNotBlank(serialValue)){ serialUnitString.set(maxSerialUnitString); sb.append(serialValue).append(SERIAL_VALUE_SPACE); } }); }else{ if(secValueMap.containsKey(secVO.getOid())) {//企业标准处理修订顺序号已经存在的数据则不需要动流水依赖表的数据 serialUnitString.set(secOdserialUnitMap.get(secVO.getOid())); sb.append(secValueMap.get(secVO.getOid())).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 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 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 wrapper = new QueryWrapper<>(); wrapper.eq("CREATECODEBTM",allCodeDOList.get(0).getCreateCodeBtm()); wrapper.in("ID",allCodeDOList.stream().map(CodeAllCode::getId).collect(Collectors.toList())); List codeAllCodes = codeAllCodeService.selectByWrapper(wrapper); List 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 iterator = allCodeDOList.iterator(); for (int i = 0; i < allCodeDOList.size(); i++) { if(codeAllCode.getId().equals(allCodeDOList.get(i).getId())){ codeAllCode.setCreateCodeOid(allCodeDOList.get(i).getCreateCodeOid()); codeAllCode.setLcStatus(allCodeDOList.get(i).getLcStatus()); allCodeDOList.remove(i); } } /*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 secValueMap, CodeClassifyFullInfoBO classifyFullInfoBO,List serialSecVOList, List attrSecVOList, List serialUnitList, List 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(Func.isBlank(codeClassifyValueDO.getId())){ codeClassifyValueDO.setId(""); } 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 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 数据的内容 * @param rule 规则的内容 * @return 转换后的 */ private String getValueByFormulaForCBO(BaseModel cbo,String rule) { Map dataMap = null; try{ dataMap = VciBaseUtil.convertBean2Map(cbo,null); }catch(Exception e){ throw new VciBaseException("mapToBeanError:"+e); } Map map = new HashMap(); for (String i : dataMap.keySet()) { map.put(i, String.valueOf(dataMap.get(i)).trim()); } // WebUtil.copyValueToMapFromCbos(cbo,dataMap); return formulaService.getValueByFormula(map,rule); } }