package com.vci.ubcs.omd.service.impl; import com.alibaba.cloud.commons.lang.StringUtils; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.vci.ubcs.omd.constant.BtmTypeConstant; import com.vci.ubcs.omd.dto.RevisionRuleDTO; import com.vci.ubcs.omd.entity.BtmType; import com.vci.ubcs.omd.entity.RevisionRule; import com.vci.ubcs.omd.mapper.BtmTypeMapper; import com.vci.ubcs.omd.mapper.RevisionRuleMapper; import com.vci.ubcs.omd.service.IRevisionRuleService; import com.vci.ubcs.omd.vo.BtmTypeVO; import com.vci.ubcs.omd.vo.RevisionRuleVO; import com.vci.ubcs.omd.wrapper.BtmTypeWrapper; import com.vci.ubcs.omd.wrapper.RevisionRuleWrapper; import com.vci.ubcs.starter.exception.VciBaseException; import com.vci.ubcs.starter.util.MybatisParameterUtil; import com.vci.ubcs.starter.util.UBCSCondition; import com.vci.ubcs.starter.web.constant.RegExpConstant; import com.vci.ubcs.starter.web.util.BeanUtil; import com.vci.ubcs.starter.web.util.VciBaseUtil; import org.springblade.core.mp.support.Condition; import org.springblade.core.mp.support.Query; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.StringUtil; import org.springframework.cglib.beans.BeanMap; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * Description: 版本规则的服务 * * @author LiHang * @date 2023/5/17 */ @Service public class RevisionRuleServiceImpl extends ServiceImpl implements IRevisionRuleService { private final Pattern pattern = Pattern.compile("\\d+"); @Resource private BtmTypeMapper btmTypeMapper; /** * 获取版本规则列表 * * @param condition 查询条件 * @param query 分页信息和排序信息,默认使用id排序 * @return 版本规则对象列表 * @throws VciBaseException 查询出错时会抛出异常 */ @Override public IPage listRevisionRule(Map condition, Query query) throws VciBaseException { RevisionRule queryConditionObj = new RevisionRule(); BeanMap beanMap = BeanMap.create(queryConditionObj); beanMap.putAll(condition); return RevisionRuleWrapper.build().pageVO(baseMapper.selectPage(Condition.getPage(query),Condition.getQueryWrapper(queryConditionObj).lambda().orderByAsc(RevisionRule::getId))); } /** * 根据主键获取版本规则 * * @param pkRevisionRule 版本规则主键 * @return 版本规则,如果不存在会返回null * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public RevisionRuleVO getRevisionRuleByOid(String pkRevisionRule) throws VciBaseException { VciBaseUtil.alertNotNull(pkRevisionRule,"版本规则主键"); return RevisionRuleWrapper.build().entityVO(getOne(Wrappers.query().lambda().eq(RevisionRule::getOid,pkRevisionRule))); } /** * 根据主键批量获取版本规则 * * @param pkRevisionRules 版本规则主键,用逗号分隔 * @return 版本规则列表,如果有不存在的不会返回,全部不存在的则返回空列表 * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public List listRevisionRuleByOids(String pkRevisionRules) throws VciBaseException { VciBaseUtil.alertNotNull(pkRevisionRules,"版本规则主键"); List oidList = Func.toStrList(",", pkRevisionRules); return RevisionRuleWrapper.build().listVO(list(MybatisParameterUtil.cutInParameter(Wrappers.query().lambda(),RevisionRule::getOid,oidList))); } /** * 批量根据主键获取版本规则 * * @param pkRevisionRuleCollection 版本规则主键集合 * @return 版本规则列表,如果有不存在的不会返回,全部不存在的则返回空列表 * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public List listRevisionRuleByOidCollection(Collection pkRevisionRuleCollection) throws VciBaseException { VciBaseUtil.alertNotNull(pkRevisionRuleCollection,"版本规则主键集合"); return RevisionRuleWrapper.build().listVO(list(MybatisParameterUtil.cutInParameter(Wrappers.query().lambda(),RevisionRule::getOid, Arrays.asList(pkRevisionRuleCollection.toArray())))); } /** * 根据英文名称获取版本规则 * * @param id 英文名称 * @return 版本规则,如果不存在会返回null * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public RevisionRuleVO getRevisionRuleById(String id) throws VciBaseException { VciBaseUtil.alertNotNull(id,"英文名称"); return RevisionRuleWrapper.build().entityVO(getOne(Wrappers.query().lambda().eq(RevisionRule::getId,id))); } /** * 根据英文名称批量获取版本规则 * * @param ids 英文名称,使用逗号分隔 * @return 版本规则列表,如果有不存在的不会返回,全部不存在的则返回空列表 * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public List listRevisionRuleByIds(String ids) throws VciBaseException { VciBaseUtil.alertNotNull(ids,"英文名称"); List idList = Func.toStrList(",", ids); return RevisionRuleWrapper.build().listVO(baseMapper.selectList(Wrappers.query().lambda().in(RevisionRule::getId,idList))); } /** * 根据英文名称集合批量获取版本规则 * * @param revisionRuleIdCollection 英文名称集合,使用逗号分隔 * @return 版本规则列表,如果有不存在的不会返回,全部不存在的则返回空列表 * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public List listRevisionRuleByIdCollection(Collection revisionRuleIdCollection) throws VciBaseException { VciBaseUtil.alertNotNull(revisionRuleIdCollection,"英文名称集合"); List list = baseMapper.selectByIdIgnoreCase(revisionRuleIdCollection); return RevisionRuleWrapper.build().listVO(list); } /** * 根据版本规则主键获取中文名称 * * @param oid 版本规则主键,多个使用逗号分隔 * @return 中文名称,如果不存在会返回null;多个会以逗号分隔 * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public String getNameByOid(String oid) throws VciBaseException { VciBaseUtil.alertNotNull(oid,"版本规则主键"); return getRevisionRuleByOid(oid).getName(); } /** * 根据版本规则英文名称获取中文名称 * * @param id 版本规则英文名称 * @return 中文名称,如果不存在会返回null;多个会以逗号分隔 * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public String getNameById(String id) throws VciBaseException { VciBaseUtil.alertNotNull(id,"版本规则英文名称"); return getRevisionRuleById(id).getName(); } /** * 添加版本规则 * * @param revisionRuleVO 版本规则显示对象(和DTO共用) * @return 添加后的版本规则 * @throws VciBaseException 添加出错的时候会抛出异常 */ @Override public RevisionRuleVO addSave(RevisionRuleDTO revisionRuleVO) throws VciBaseException { VciBaseUtil.alertNotNull(revisionRuleVO,"要添加的版本规则",revisionRuleVO.getId(),"版本规则英文名称",revisionRuleVO.getName(),"版本规则中文名称"); List voList = batchAddSave(Collections.singletonList(revisionRuleVO)); if (!CollectionUtils.isEmpty(voList)){ return voList.get(0); } return null; } /** * 批量添加版本规则 * * @param revisionRuleDTOList 版本规则显示对象列表 * @return 批量添加后的版本规则 * @throws VciBaseException 添加出错的时候会抛出异常 */ @Override public List batchAddSave(List revisionRuleDTOList) throws VciBaseException { if(CollectionUtils.isEmpty(revisionRuleDTOList)){ throw new VciBaseException("要添加的版本规则对象不能为空"); } //1. 判断各个属性是否必输项都输入了 //2. 判断的英文名称是否重复 Set idSet = new HashSet<>(); String creator = AuthUtil.getUserAccount(); Date now = new Date(); List revisionRuleList = new ArrayList<>(); revisionRuleDTOList.forEach(s -> { //判断为空 VciBaseUtil.alertNotNull(s.getId(),"版本规则英文名称",s.getName(),"版本规则中文名称",s.getStartCode(),"起始字符",s.getSerialStep(),"步长"); //判断本次是否存在 if(idSet.contains(s.getId().toLowerCase().trim())){ throw new VciBaseException("英文名称为{0}的状态已经存在",new Object[]{s.getId()}); }else{ idSet.add(s.getId().toLowerCase().trim()); } RevisionRule ruleDO = org.springblade.core.tool.utils.BeanUtil.copy(s, RevisionRule.class); if(StringUtils.isBlank(ruleDO.getOid())){ ruleDO.setOid(VciBaseUtil.getPk()); } //判断属性是否符合要求 ruleDO.setCreator(creator); ruleDO.setCreateTime(now); ruleDO.setOwner(creator); ruleDO.setBtmName(BtmTypeConstant.REVISION_RULE); ruleDO.setTs(now); ruleDO.setLastModifier(creator); ruleDO.setLastModifyTime(now); ruleDO.setTs(now); revisionRuleList.add(ruleDO); }); //判断是否存在 List checkExistList = listRevisionRuleByIdCollection(idSet); if(!CollectionUtils.isEmpty(checkExistList)){ String existIds = checkExistList.stream().map(RevisionRuleVO::getId).collect(Collectors.joining(",")); throw new VciBaseException("英文名称为{0}的版本规则的已经在系统中存在(不区分大小写),不能添加",new Object[]{existIds}); } VciBaseUtil.switchCollectionForOracleIn(revisionRuleList,1000).forEach(this::saveOrUpdateBatch); return RevisionRuleWrapper.build().listEntityVO(revisionRuleList); } /** * 修改版本规则 * * @param revisionRuleDTO 版本规则显示对象(和DTO共用) * @return 修改后的版本规则 * @throws VciBaseException 修改出错的时候会抛出异常 */ @Override public RevisionRuleVO editSave(RevisionRuleDTO revisionRuleDTO) throws VciBaseException { VciBaseUtil.alertNotNull(revisionRuleDTO,"要修改的版本规则对象",revisionRuleDTO.getOid(),"要修改的版本规则对象的主键"); List voList = batchEditSave(Collections.singletonList(revisionRuleDTO)); if (!CollectionUtils.isEmpty(voList)){ return voList.get(0); } return null; } /** * 批量修改版本规则 * * @param revisionRuleDTOList 版本规则显示对象列表(和DTO共用) * @return 批量修改后的版本规则 * @throws VciBaseException 修改出错的时候会抛出异常 */ @Override public List batchEditSave(List revisionRuleDTOList) throws VciBaseException { if(CollectionUtils.isEmpty(revisionRuleDTOList)){ throw new VciBaseException("要修改的版本规则对象不能为空"); } //1. 判断各个属性是否必输项都输入了 //2. 判断的英文名称是否重复 Set idSet = new HashSet<>(); Map oidObjectMap = new HashMap<>(16); String creator = AuthUtil.getUserAccount(); Date now = new Date(); List revisionRuleList = new ArrayList<>(); revisionRuleDTOList.forEach(s -> { //判断为空 VciBaseUtil.alertNotNull(s.getOid(),"版本规则主键",s.getId(),"版本规则英文名称",s.getName(),"版本规则中文名称",s.getStartCode(),"起始字符",s.getSerialStep(),"步长"); //判断本次是否存在 if(idSet.contains(s.getId().toLowerCase().trim())){ throw new VciBaseException("英文名称为{0}的版本规则已经存在(不区分大小写)",new Object[]{s.getId()}); }else{ idSet.add(s.getId().toLowerCase().trim()); } oidObjectMap.put(s.getOid(),s); RevisionRule ruleDO = org.springblade.core.tool.utils.BeanUtil.copy(s, RevisionRule.class); ruleDO.setLastModifier(creator); ruleDO.setLastModifyTime(now); ruleDO.setTs(now); revisionRuleList.add(ruleDO); }); //判断是否存在 List checkExistList = listRevisionRuleByOidCollection(oidObjectMap.keySet()); if(CollectionUtils.isEmpty(checkExistList)){ throw new VciBaseException("这些版本规则在系统中均不存在",new Object[]{}); } //判断属性名称是否修改 Set oidInDbSet = new HashSet<>(); checkExistList.forEach(s -> { RevisionRuleDTO revisionRuleDTO = oidObjectMap.get(s.getOid()); if(!revisionRuleDTO.getId().equalsIgnoreCase(s.getId())){ throw new VciBaseException("版本规则[{0}]的英文名称不允许修改,原名称{1},新名称{2}",new Object[]{s.getName(),s.getId(),revisionRuleDTO.getId()}); } BeanUtil.convert(revisionRuleDTO,s); oidInDbSet.add(s.getOid()); }); //看看是否有不在系统中存在的 oidObjectMap.forEach( (k,v) ->{ if(!oidInDbSet.contains(k)){ throw new VciBaseException("版本规则{0}[{1}]在系统中不存在",new Object[]{v.getId(),v.getName()}); } }); VciBaseUtil.switchCollectionForOracleIn(revisionRuleList,1000).forEach(this::saveOrUpdateBatch); return RevisionRuleWrapper.build().listEntityVO(revisionRuleList); } /** * 删除版本规则 * * @param revisionRuleVO 版本规则显示对象 * @throws VciBaseException 如果版本规则被引用,或者删除出错时会抛出异常 */ @Override public void delete(RevisionRuleVO revisionRuleVO) throws VciBaseException { VciBaseUtil.alertNotNull(revisionRuleVO,"要删除的版本对象",revisionRuleVO.getOid(),"要删除的版本对象的主键"); batchDelete(Collections.singletonList(revisionRuleVO)); } /** * 批量删除版本规则 * * @param revisionRuleVOList 要删除的版本规则显示对象列表 * @throws VciBaseException 如果版本规则被引用,或者删除出错时会抛出异常 */ @Override @Transactional(rollbackFor = VciBaseException.class) public void batchDelete(List revisionRuleVOList) throws VciBaseException { VciBaseUtil.alertNotNull(revisionRuleVOList,"版本规则"); Set oidSet = revisionRuleVOList.stream().map(RevisionRuleVO::getOid).peek(s -> VciBaseUtil.alertNotNull(StringUtil.isBlank(s))).collect(Collectors.toSet()); List revisionRuleList = listRevisionRuleByOidCollection(oidSet); if(CollectionUtils.isEmpty(revisionRuleList)){ throw new VciBaseException("要删除的版本规则在系统中不存在,可能您需要刷新后再试"); } Set oidInDbSet = revisionRuleList.stream().map(RevisionRuleVO::getOid).collect(Collectors.toSet()); oidSet.forEach( s -> { if(!oidInDbSet.contains(s)){ throw new VciBaseException("要删除的版本规则在系统中不存在,可能您需要刷新后再试"); } }); //检查属性是否被引用 if(batchCheckRevisionRuleUsed(oidSet)){ throw new VciBaseException("要删除的版本规则在业务类型中被使用,无法删除"); } //执行批量删除 Collection> oidCollections = VciBaseUtil.switchCollectionForOracleIn(oidInDbSet); for(Collection oidCollection : oidCollections){ baseMapper.delete(Wrappers.query().lambda().in(RevisionRule::getOid,oidCollection)); } } /** * 批量校验版本规则是否被使用 * * @param oidCollection 主键集合 * @return true表示被引用 */ @Override public boolean batchCheckRevisionRuleUsed(Collection oidCollection) { VciBaseUtil.alertNotNull("校验是否引用的版本规则的主键",oidCollection); //检查业务类型 Collection> oidCollections = VciBaseUtil.switchCollectionForOracleIn(oidCollection); for(Collection oids : oidCollections) { MPJLambdaWrapper join = UBCSCondition.getMPJLambdaWrapper(new BtmType()) .join("join", RevisionRule.class, RevisionRule::getId, BtmType::getRevisionRuleId) .in(RevisionRule::getOid, oids); Long count = btmTypeMapper.selectCount(join); if(count>0){ return true; } } return false; } /** * 获取使用版本规则的业务类型 * * @param pkRevisionRule 版本规则的主键 * @return 引用的业务类型 * @throws VciBaseException 查询出错时会抛出异常 */ @Override public List listRevisionRuleUsedInfo(String pkRevisionRule) throws VciBaseException { VciBaseUtil.alertNotNull(pkRevisionRule,"版本规则对象的主键"); List result = btmTypeMapper.selectList( UBCSCondition.getMPJLambdaWrapper(new BtmType()) .join("join", RevisionRule.class, RevisionRule::getId, BtmType::getRevisionRuleId) .eq(RevisionRule::getOid, pkRevisionRule)); return BtmTypeWrapper.build().listEntityVO(result); } /** * 校验版本规则是否被引用 * * @param pkRevisionRule 版本规则的主键 * @return true表示被引用, false表示没有被引用 * @throws VciBaseException 参数为空或者查询出错时会抛出错误 */ @Override public boolean checkRevisionRuleUsed(String pkRevisionRule) throws VciBaseException { VciBaseUtil.alertNotNull(pkRevisionRule,"要校验是否引用的版本规则对象的主键"); return batchCheckRevisionRuleUsed(Func.toStrList(",",pkRevisionRule)); } /** * 判断版本规则是否存在 * * @param revisionRuleId 版本规则的英文名称 * @return true表示都存在,false表示不存在 * @throws VciBaseException 参数错误或者查询出错会抛出异常 */ @Override public boolean checkRevisionRuleExist(String revisionRuleId) throws VciBaseException { VciBaseUtil.alertNotNull(revisionRuleId,"版本规则的英文名称"); List idList = Func.toStrList(",",revisionRuleId.toLowerCase(Locale.ROOT)); List revisionRuleDOList = listRevisionRuleByIdCollection(idList); if(CollectionUtils.isEmpty(revisionRuleDOList)){ return false; }else{ Set existIdList = revisionRuleDOList.stream().map(RevisionRuleVO::getId) .collect(Collectors.toList()).stream() .map(String::toLowerCase).collect(Collectors.toSet()); //上方已经转换为了小写 return idList.stream().allMatch(s -> existIdList.contains(s.toLowerCase().trim())); } } /** * 获取下一个版本的值 * * @param ruleId 版本的规则 * @param currentRevisionValue 当前版本的值,为空的时候,说明是新增 * @return 下一个版本号 * @throws VciBaseException 版本规则不存在的时候会抛出异常 */ @Override public String getNextRevisionValue(String ruleId, String currentRevisionValue) throws VciBaseException { VciBaseUtil.alertNotNull(ruleId,"规则的英文名称"); boolean isFirstRevision = StringUtils.isBlank(currentRevisionValue); RevisionRuleVO revisionRuleVO = getRevisionRuleByOid(ruleId); String ruleValue; if(isFirstRevision){ //前缀+ 起始 + 后缀 return (StringUtils.isBlank(revisionRuleVO.getPrefixCode())?"":revisionRuleVO.getPrefixCode().trim()) + revisionRuleVO.getStartCode() + (StringUtils.isBlank(revisionRuleVO.getSuffixCode())?"":revisionRuleVO.getSuffixCode().trim()); }else{ ruleValue = replacePrefixAndSubfix(currentRevisionValue, revisionRuleVO.getPrefixCode(), revisionRuleVO.getSuffixCode()); String lastChar = ruleValue.substring(ruleValue.length()-1); String unHasLastCharRule = ruleValue.substring(0,ruleValue.length()-1); Integer step = revisionRuleVO.getSerialStep(); if(step == null){ step = 1; } if(lastChar.matches(RegExpConstant.LETTER)){ //是字母的,加过去后如果超过了Z,那就得加一位 //用ascii码来添加 int ascInt = lastChar.toCharArray()[0]; int ascForZ = "Z".toCharArray()[0]; int ascForA = "A".toCharArray()[0]; int newValueAsc; if((ascInt + step) > ascForZ){ newValueAsc = (ascInt + step) - ascForZ + ascForA; ruleValue = unHasLastCharRule + "A" + (char)newValueAsc; }else { ruleValue = unHasLastCharRule + (char)(ascInt + step); } }else{ //是数字 String lastNumberInString = getNumbers(ruleValue); String nextNumber = String.valueOf(Integer.parseInt(lastNumberInString) + step); if(ruleValue.length() > lastNumberInString.length()){ ruleValue = ruleValue.substring(0,ruleValue.length() - lastNumberInString.length()-1) + nextNumber; }else{ ruleValue = nextNumber; } } } return ruleValue; } /** * 获取字符串中的数字部分 * @param content 字符串内容 * @return 数字的部分,最后的那部分 */ private String getNumbers(String content) { Matcher matcher = pattern.matcher(content); while (matcher.find()) { return matcher.group(matcher.groupCount()-1); } return ""; } /** * 替换前缀和后缀 * @param ruleValue 当前版本的值 * @param prefix 前缀 * @param subfix 后缀 * @return 去除前缀和后缀的版本规则 */ private String replacePrefixAndSubfix(String ruleValue, String prefix, String subfix){ if(prefix==null){ prefix = ""; } if(subfix == null){ subfix = ""; } if(StringUtils.isNotBlank(prefix) && ruleValue.startsWith(prefix)){ ruleValue = ruleValue.substring(prefix.length()); } if(StringUtils.isNotBlank(subfix) && ruleValue.endsWith(subfix)){ ruleValue = ruleValue.substring(0,ruleValue.length()-subfix.length()-1); } return ruleValue; } /** * 分页查询 * * @param baseQueryObject 查询对象 * @return 查询结果 * @throws VciBaseException 查询出错时抛出异常 */ @Override public IPage pageQueryVO(Map condition, Query query) throws VciBaseException { return RevisionRuleWrapper.build().pageVO(baseMapper.selectPage(Condition.getPage(query),Condition.getQueryWrapper(condition,RevisionRule.class).lambda().orderByAsc(RevisionRule::getId))); } /** * 查看应用范围 * * @param id id * @return 执行结果 */ @Override public List getApplyRange(String id) { VciBaseUtil.alertNotNull(id,"版本规则英文名称"); return BtmTypeWrapper.build().listEntityVO(btmTypeMapper.selectList(Wrappers.query().lambda().eq(BtmType::getRevisionRuleId,id))); } }