/* * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the dreamlu.net developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ package com.vci.ubcs.code.service.impl; import com.alibaba.cloud.commons.lang.StringUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.vci.ubcs.code.constant.MdmBtmTypeConstant; import com.vci.ubcs.code.dto.CodeBasicSecDTO; import com.vci.ubcs.code.dto.CodeRuleDTO; import com.vci.ubcs.code.entity.*; import com.vci.ubcs.code.lifecycle.CodeRuleLC; import com.vci.ubcs.code.mapper.CodeRuleMapper; import com.vci.ubcs.code.mapper.CodeSerialValueMapper; import com.vci.ubcs.code.mapper.CommonsMapper; import com.vci.ubcs.code.service.ICodeAllCodeService; import com.vci.ubcs.code.service.ICodeBasicSecService; import com.vci.ubcs.code.service.ICodeClassifyService; import com.vci.ubcs.code.service.ICodeRuleService; import com.vci.ubcs.code.vo.pagemodel.CodeClassifyVO; import com.vci.ubcs.code.vo.pagemodel.CodeRuleVO; import com.vci.ubcs.code.wrapper.CodeClassifyWrapper; import com.vci.ubcs.code.wrapper.CodeRuleWrapper; import com.vci.ubcs.starter.exception.VciBaseException; import com.vci.ubcs.starter.revision.service.RevisionModelUtil; import com.vci.ubcs.starter.util.DefaultAttrAssimtUtil; import com.vci.ubcs.starter.util.UBCSCondition; import com.vci.ubcs.starter.web.pagemodel.BladeQueryObject; import com.vci.ubcs.starter.web.pagemodel.KeyValue; import com.vci.ubcs.starter.web.util.BeanUtilForVCI; import com.vci.ubcs.starter.web.util.VciBaseUtil; import com.vci.ubcs.starter.web.util.WebUtil; import org.springblade.core.log.exception.ServiceException; 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.api.R; import org.springblade.core.tool.utils.BeanUtil; 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 java.util.*; import java.util.stream.Collectors; import static com.vci.ubcs.code.constant.FrameWorkDefaultValueConstant.FRAMEWORK_RELEASE_EDITING; import static com.vci.ubcs.code.constant.FrameWorkLangCodeConstant.DATA_OID_NOT_EXIST; import static com.vci.ubcs.code.constant.MdmLifeCycleConstant.CODE_RULE_LC; /** * 编码规则 服务实现类 * * @author ludc * @since 2023-04-03 */ @Service public class CodeRuleServiceImpl extends ServiceImpl implements ICodeRuleService { /** * 数据操作层 */ @Resource private CodeRuleMapper codeRuleMapper; @Resource private CommonsMapper commonsMapper; @Resource private CodeSerialValueMapper codeSerialValueMapper; /** * 其他服务层 */ @Resource @Lazy private ICodeClassifyService codeClassifyServcie; @Resource private ICodeAllCodeService codeAllcodeService; @Resource private ICodeBasicSecService codeBasicSecService; /** * 对象的操作 */ @Resource private RevisionModelUtil revisionModelUtil; /** * 分页查询 * @param query * @param conidtionMap * @return */ @Override public IPage gridCodeRule(Query query, Map conidtionMap) { IPage codeRuleIPage = this.codeRuleMapper.selectPage(Condition.getPage(query), UBCSCondition.getQueryWrapper(conidtionMap, CodeRule.class)); //do转vo同时setLcStatusText生命周期值,并包装成分页对象返回 return CodeRuleWrapper.build().pageVO(codeRuleIPage); } /** * 增加主数据编码规则 * * @param codeRuleDTO 主数据编码规则数据传输对象 * @return 执行结果 * @throws VciBaseException 参数为空,唯一项,必输项不通过时会抛出异常 */ @Override public boolean addSave(CodeRuleDTO codeRuleDTO) throws VciBaseException { VciBaseUtil.alertNotNull(codeRuleDTO, "需要添加的数据对象"); //将DTO转换为DO CodeRule codeRule = Objects.requireNonNull(BeanUtil.copy(codeRuleDTO, CodeRule.class)); String userId = AuthUtil.getUserId().toString(); DefaultAttrAssimtUtil.addDefaultAttrAssimt(codeRule, MdmBtmTypeConstant.CODE_RULE); codeRule.setLctid(CODE_RULE_LC); codeRule.setLcStatus(FRAMEWORK_RELEASE_EDITING); return codeRuleMapper.insert(codeRule)>0; } /** * 校验编码规则的状态是否可以编辑或删除 * * @param lcStatus 编码规则 * @return true表示可以编辑或删除,false表示不可以 */ @Override public boolean checkEditDelStatus(String lcStatus) { if (CodeRuleLC.RELEASED.getValue().equals(lcStatus) || CodeRuleLC.DISABLED.getValue().equals(lcStatus)) { return false; } return true; } /** * 修改主数据编码规则 * * @param codeRuleDTO 主数据编码规则数据传输对象 * @return 执行结果 * @throws VciBaseException 参数为空,唯一项,必输项不通过时会抛出异常 */ @Override public boolean editSave(CodeRuleDTO codeRuleDTO) throws VciBaseException{ VciBaseUtil.alertNotNull(codeRuleDTO, "数据对象", codeRuleDTO.getOid(), "主数据编码规则主键"); if (!checkEditDelStatus(codeRuleDTO.getLcStatus())) { throw new VciBaseException("编码规则已发布,不允许编辑或删除"); } //将DTO转换为DO CodeRule codeRule = selectByOid(codeRuleDTO.getOid()); revisionModelUtil.copyFromDTOIgnore(codeRuleDTO, codeRule); DefaultAttrAssimtUtil.updateDefaultAttrAssimt(codeRule); return codeRuleMapper.updateById(codeRule)>0; } /** * 删除主数据编码规则 * * @param codeRuleDTO 主数据编码规则数据传输对象,oid和ts需要传输 * @return 删除结果反馈::success:成功,fail:失败 * @throws VciBaseException 参数为空,被引用时抛出异常 */ @Override @Transactional(rollbackFor = Exception.class) public R deleteCodeRule(CodeRuleDTO codeRuleDTO) throws VciBaseException { VciBaseUtil.alertNotNull(codeRuleDTO, "主数据编码规则数据对象", codeRuleDTO.getOid(), "主数据编码规则的主键"); CodeRule codeRule = selectByOid(codeRuleDTO.getOid()); if (!checkEditDelStatus(codeRule.getLcStatus())) { return R.fail("编码规则已发布,不允许编辑或删除"); } else { if (isAlreadyInUse(codeRule.getOid())) { return R.fail("编码规则已被引用,不允许编辑或删除!"); } } List codeDOList = codeAllcodeService.selectByWrapper(Wrappers.query().lambda().eq(CodeAllCode::getCodeRuleOid, codeRuleDTO.getOid())); if (!CollectionUtils.isEmpty(codeDOList)) { return R.fail("编码规则已生成编码,不允许删除"); } //执行删除操作 //WebUtil.setPersistence(false); boolean resBoolean = codeBasicSecService.batchDeleteSecByCodeRuleOid(codeRule.getOid()); boolean resBoolean1 = codeRuleMapper.deleteById(codeRule.getOid()) > 0; //WebUtil.setPersistence(true); return R.status(resBoolean&&resBoolean1); } /** * 编码规则清空所有已生成的编码 * * @param oid 编码规则主键 * @return 执行结果 */ @Override public R clearAllCode(String oid) { WebUtil.alertNotNull(oid, "编码规则主键"); List codeDOList = codeAllcodeService.selectByWrapper(Wrappers.query().lambda().eq(CodeAllCode::getCodeRuleOid, oid)); if (CollectionUtils.isEmpty(codeDOList)) { return R.fail("当前编码规则没有生成编码,无需清空"); } //是否需要进行btm不统一的判断? String btmType = codeDOList.get(0).getCreateCodeBtm(); //多种类型下的查询 Set btmTypeSet = codeDOList.stream().filter(s -> { return !btmType.equalsIgnoreCase(s.getCreateCodeBtm()); }).map(s -> s.getCreateCodeBtm()).collect(Collectors.toSet()); List> businessDataList = new ArrayList<>(); if (btmTypeSet.size() > 1) { for (String btm : btmTypeSet) { Map businessData = commonsMapper.selectByCount("PL_CODE_"+btm,oid,btm); businessDataList.add(businessData); } }else { Map businessData = commonsMapper.selectByCount("PL_CODE_"+btmType,oid,btmType); businessDataList.add(businessData); } if (CollectionUtils.isEmpty(businessDataList) || StringUtils.isBlank(businessDataList.get(0).get("count"))) { //无效查询 return R.fail("查询失败"); } else if (!"0".equalsIgnoreCase(businessDataList.get(0).get("count"))) { return R.fail("编码规则生成的编码已在业务数据中应用,不允许清空"); } //没有数据,可以安全删除 WebUtil.setPersistence(false); //删除码值表中的数据,但不够,如果有流水的码段,需要重新计算流水 List serialValueList = codeSerialValueMapper.selectByCodeRoleId(oid); /*BatchCBO batchCBO = boService.batchDelete(codeDOList); batchCBO.getDeleteCbos().addAll(serialValueList); WebUtil.setPersistence(true); boService.persistenceBatch(batchCBO);*/ return R.success("清空码值成功!"); } /** * 主键查询数据对象 * * @param oid 主键 * @return 数据对象 * @throws VciBaseException 参数为空,并且数据不存在的时候会抛出异常 */ private CodeRule selectByOid(String oid) throws VciBaseException { VciBaseUtil.alertNotNull(oid, "主键"); CodeRule codeRuleDO = codeRuleMapper.selectById(oid.trim()); if (codeRuleDO == null || StringUtils.isBlank(codeRuleDO.getOid())) { throw new VciBaseException(DATA_OID_NOT_EXIST); } return codeRuleDO; } /** * 检验编码规则是否已经被使用 * * @param oid 编码规则主键 * @return true表示已经使用,false表示未被使用 */ @Override public boolean isAlreadyInUse(String oid) { Collection codeClassifyVOS = listUseRangeInCodeClassify(oid); if (codeClassifyVOS.size() > 0) { return true; } else { return false; } } /** * 查看主数据编码规则的使用范围 * * @param oid 编码规则主键 * @return 主题库分类使用到该编码规则的所有集合 */ @Override public Collection listUseRangeInCodeClassify(String oid) { List codeClassifies = codeClassifyServcie.selectByWrapper(Wrappers.query().lambda().eq(CodeClassify::getCodeRuleOid, oid)); return CodeClassifyWrapper.build().listVO(codeClassifies); } /** * 主键获取主数据编码规则 * * @param oid 主键 * @return 主数据编码规则显示对象 * @throws VciBaseException 参数为空,数据不存在时会抛出异常 */ @Override public CodeRuleVO getObjectByOid(String oid) throws VciBaseException { CodeRule codeRule = selectByOid(oid); return CodeRuleWrapper.build().entityVO(codeRule); } /** * 主键批量获取主数据编码规则 * * @param oidCollections 主键集合,但是受性能影响,建议一次查询不超过10000个 * @return 主数据编码规则显示对象 * @throws VciBaseException 查询出现异常时会抛出 */ @Override public Collection listCodeRuleByOids(Collection oidCollections) throws VciBaseException { VciBaseUtil.alertNotNull(oidCollections, "数据对象主键集合"); List codeRuleDOList = listCodeRuleDOByOidCollections(oidCollections); return CodeRuleWrapper.build().listVO(codeRuleDOList); } /** * 主键批量获取主数据编码规则 * * @param oidCollections 主键集合,但是受性能影响,建议一次查询不超过10000个 * @param hasSec 是否包含码段 * @return 主数据编码规则显示对象 * @throws VciBaseException 查询出现异常时会抛出 */ @Override public Collection listCodeRuleByIds(Collection oidCollections, boolean hasSec) throws VciBaseException { VciBaseUtil.alertNotNull(oidCollections, "数据对象主键集合"); List codeRuleDOList = listCodeRuleDOByOidCollections(oidCollections); return codeRuleDO2VOs(codeRuleDOList, true); } /** * 使用主键集合查询数据对象 * * @param oidCollections 主键的集合 * @return 数据对象列表 */ private List listCodeRuleDOByOidCollections(Collection oidCollections) { List codeRuleDOList = new ArrayList(); if (!CollectionUtils.isEmpty(oidCollections)) { Collection> oidCollectionsList = VciBaseUtil.switchCollectionForOracleIn(oidCollections); for (Collection oids : oidCollectionsList) { List tempDOList = codeRuleMapper.selectBatchIds(oids); if (!CollectionUtils.isEmpty(tempDOList)) { codeRuleDOList.addAll(tempDOList); } } } return codeRuleDOList; } /** * 参照主数据编码规则列表 * * @param bladeQueryObject 查询条件 * @return 主数据编码规则显示对象列表,生效的内容 * @throws VciBaseException 查询条件和分页出错的时候会抛出异常 */ @Override public IPage refDataGridCodeRule(BladeQueryObject bladeQueryObject) throws VciBaseException { return gridCodeRule(bladeQueryObject.getQuery(), bladeQueryObject.getConditionMap()); } /** * 停用与启用编码规则 * * @param oid 编码规则主键 * @param update enable:启用 disable:停用 release:发布 * @return 执行结果 */ @Override public R updateStatus(String oid, String update) { int count = 0; //先查询对象 CodeRule codeRuleDO = selectByOid(oid); //创建修改对象的的wrapper条件 LambdaUpdateWrapper wrapper = Wrappers.update() .lambda() .eq(CodeRule::getOid, oid); if ("enable".equalsIgnoreCase(update)) { if (!CodeRuleLC.DISABLED.getValue().equals(codeRuleDO.getLcStatus())) { return R.fail("非停用状态的编码规则无需点击启用"); } count = codeRuleMapper.update(null,wrapper.set(CodeRule::getLcStatus, CodeRuleLC.RELEASED.getValue())); } else if ("disable".equalsIgnoreCase(update)) { if (!CodeRuleLC.RELEASED.getValue().equals(codeRuleDO.getLcStatus())) { return R.fail("非发布状态的编码规则无法停用"); } count = codeRuleMapper.update(null,wrapper.set(CodeRule::getLcStatus, CodeRuleLC.DISABLED.getValue())); } else if ("release".equalsIgnoreCase(update)) { if (!CodeRuleLC.EDITING.getValue().equals(codeRuleDO.getLcStatus())) { return R.fail("非编辑状态的编码规则无法发布"); } count = codeRuleMapper.update(null,wrapper.set(CodeRule::getLcStatus, CodeRuleLC.RELEASED.getValue())); } else { return R.fail("暂不支持的操作类型"); } if (count > 0) { return R.success("更新状态成功"); } else { return R.fail("更新状态失败"); } } /** * 克隆编码规则 * * @param codeRuleDTO 主数据编码规则数据传输对象,oid和ts需要传输 * @return 主数据编码规则显示对象 */ @Override @Transactional(rollbackFor = Exception.class) public R cloneCodeRule(CodeRuleDTO codeRuleDTO) { VciBaseUtil.alertNotNull(codeRuleDTO, "需要添加的数据对象"); CodeRule codeRuleDO = new CodeRule(); BeanUtilForVCI.copyPropertiesIgnoreCase(codeRuleDTO, codeRuleDO); boolean exFlag = codeRuleMapper.insert(codeRuleDO)>0; List secList = codeRuleDTO.getElements(); List codeBasicSecs = new ArrayList<>(); secList.forEach(codeBasicSecDTO -> { codeBasicSecDTO.setPkCodeRule(codeRuleDO.getOid()); KeyValue attrKv = codeBasicSecService.checkAttrNullableBySecType(codeBasicSecDTO); if (!"success".equals(attrKv.getKey())) { throw new VciBaseException(attrKv.getValue() + "不能为空"); } CodeBasicSec codeBasicSecDO = new CodeBasicSec(); BeanUtilForVCI.copyPropertiesIgnoreCase(codeBasicSecDTO, codeBasicSecDO); codeBasicSecDO.setOid(""); codeBasicSecDO.setRevisionOid(""); codeBasicSecDO.setNameOid(""); codeBasicSecs.add(codeBasicSecDO); }); boolean exFlag1 = this.codeBasicSecService.saveBatch(codeBasicSecs); return R.data(exFlag&&exFlag1); } /** * 使用主键获取编码规则的内容 * * @param oid 主键 * @return 规则的显示对象 */ @Override public CodeRuleVO getObjectHasSecByOid(String oid) { CodeRule ruleDO = selectByOid(oid); return codeRuleDO2VO(ruleDO, true); } /** * 批量数据对象转换为显示对象 * * @param codeRules 数据对象列表 * @param hasSec 是否包含码段 * @return 显示对象 * @throws VciBaseException 参数为空或者不存在的时候会抛出异常 */ public List codeRuleDO2VOs(Collection codeRules, boolean hasSec) throws VciBaseException { List voList = new ArrayList(); if (!CollectionUtils.isEmpty(codeRules)) { for (CodeRule s : codeRules) { CodeRuleVO vo = codeRuleDO2VO(s,true); if (vo != null) { voList.add(vo); } } } return voList; } /** * 数据对象转换为显示对象 * * @param codeRuleDO 规则的数据对象 * @param hasSec 是否查询码段 * @return 显示对象 * @throws VciBaseException 拷贝属性出错的时候会抛出异常 */ public CodeRuleVO codeRuleDO2VO(CodeRule codeRuleDO, boolean hasSec) throws VciBaseException { CodeRuleVO vo = new CodeRuleVO(); if (codeRuleDO != null) { BeanUtilForVCI.copyPropertiesIgnoreCase(codeRuleDO, vo); //如果有lcstatus的类的话 vo.setLcStatusText(CodeRuleLC.getTextByValue(vo.getLcStatus())); if (hasSec) { //查询码段 vo.setSecVOList(codeBasicSecService.listCodeBasicSecByRuleOid(vo.getOid())); } } return vo; } }