/*
|
* 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.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.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.com.vci.starter.exception.VciBaseException;
|
import com.vci.ubcs.com.vci.starter.revision.service.RevisionModelUtil;
|
import com.vci.ubcs.com.vci.starter.web.pagemodel.KeyValue;
|
import com.vci.ubcs.com.vci.starter.web.util.BeanUtilForVCI;
|
import com.vci.ubcs.com.vci.starter.web.util.VciBaseUtil;
|
import com.vci.ubcs.com.vci.starter.web.util.WebUtil;
|
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<CodeRuleMapper, CodeRule> 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;
|
|
@Override
|
public IPage<CodeRuleVO> gridCodeRule(IPage<CodeRuleVO> page, CodeRuleVO codeRule) {
|
//对生命周期的枚举进行转换
|
if(!StringUtils.isEmpty(codeRule.getLcStatusText())){
|
codeRule.setLcStatus(CodeRuleLC.getValueByText(codeRule.getLcStatusText()));
|
}
|
List<CodeRule> codeRulePage = codeRuleMapper.selectCodeRulePage(page, codeRule);
|
//do转vo同时setLcStatusText生命周期值,并包装成分页对象返回
|
return page.setRecords(CodeRuleWrapper.build().listVO(codeRulePage));
|
}
|
|
/**
|
* 增加主数据编码规则
|
*
|
* @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();
|
codeRule.setOid(VciBaseUtil.getPk());
|
codeRule.setRevisionOid(VciBaseUtil.getPk());
|
codeRule.setNameOid(VciBaseUtil.getPk());
|
codeRule.setBtmname("coderule");
|
codeRule.setLastR("1");
|
codeRule.setLastV("1");
|
codeRule.setFirstR("1");
|
codeRule.setFirstV("1");
|
codeRule.setCreator(userId);
|
codeRule.setCreateTime(new Date());
|
codeRule.setLastModifier("1");
|
codeRule.setLastModifyTime(new Date());
|
codeRule.setVersionRule("0");
|
codeRule.setVersionSeq(1);
|
codeRule.setLctid(CODE_RULE_LC);
|
codeRule.setLcStatus(FRAMEWORK_RELEASE_EDITING);
|
codeRule.setOwner("1");
|
codeRule.setCreator(userId);
|
codeRule.setLastModifier(userId);
|
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);
|
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<CodeAllCode> codeDOList = codeAllcodeService.selectByWrapper(Wrappers.<CodeAllCode>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<CodeAllCode> codeDOList = codeAllcodeService.selectByWrapper(Wrappers.<CodeAllCode>query().lambda().eq(CodeAllCode::getCodeRuleOid, oid));
|
if (CollectionUtils.isEmpty(codeDOList)) {
|
return R.fail("当前编码规则没有生成编码,无需清空");
|
}
|
//是否需要进行btm不统一的判断?
|
String btmType = codeDOList.get(0).getCreateCodeBtm();
|
//多种类型下的查询
|
Set<String> btmTypeSet = codeDOList.stream().filter(s -> {
|
return !btmType.equalsIgnoreCase(s.getCreateCodeBtm());
|
}).map(s -> s.getCreateCodeBtm()).collect(Collectors.toSet());
|
List<Map<String,String>> businessDataList = new ArrayList<>();
|
if (btmTypeSet.size() > 1) {
|
for (String btm : btmTypeSet) {
|
Map<String,String> businessData = commonsMapper.selectByCount("PL_CODE_"+btm,oid,btm);
|
businessDataList.add(businessData);
|
}
|
}else {
|
Map<String,String> 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<CodeSerialValue> 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<CodeClassifyVO> codeClassifyVOS = listUseRangeInCodeClassify(oid);
|
if (codeClassifyVOS.size() > 0) {
|
return true;
|
} else {
|
return false;
|
}
|
}
|
|
/**
|
* 查看主数据编码规则的使用范围
|
*
|
* @param oid 编码规则主键
|
* @return 主题库分类使用到该编码规则的所有集合
|
*/
|
@Override
|
public Collection<CodeClassifyVO> listUseRangeInCodeClassify(String oid) {
|
List<CodeClassify> codeClassifies = codeClassifyServcie.selectByWrapper(Wrappers.<CodeClassify>query().eq("codeRuleOid", 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<CodeRuleVO> listCodeRuleByOids(Collection<String> oidCollections) throws VciBaseException {
|
VciBaseUtil.alertNotNull(oidCollections, "数据对象主键集合");
|
List<CodeRule> codeRuleDOList = listCodeRuleDOByOidCollections(oidCollections);
|
return CodeRuleWrapper.build().listVO(codeRuleDOList);
|
}
|
|
/**
|
* 使用主键集合查询数据对象
|
*
|
* @param oidCollections 主键的集合
|
* @return 数据对象列表
|
*/
|
private List<CodeRule> listCodeRuleDOByOidCollections(Collection<String> oidCollections) {
|
List<CodeRule> codeRuleDOList = new ArrayList<CodeRule>();
|
if (!CollectionUtils.isEmpty(oidCollections)) {
|
Collection<Collection<String>> oidCollectionsList = VciBaseUtil.switchCollectionForOracleIn(oidCollections);
|
for (Collection<String> oids : oidCollectionsList) {
|
List<CodeRule> tempDOList = codeRuleMapper.selectBatchIds(oids);
|
if (!CollectionUtils.isEmpty(tempDOList)) {
|
codeRuleDOList.addAll(tempDOList);
|
}
|
}
|
}
|
return codeRuleDOList;
|
}
|
|
/**
|
* 参照主数据编码规则列表
|
*
|
* @param codeRule 查询条件
|
* @param page 分页和排序
|
* @return 主数据编码规则显示对象列表,生效的内容
|
* @throws VciBaseException 查询条件和分页出错的时候会抛出异常
|
*/
|
@Override
|
public IPage<CodeRuleVO> refDataGridCodeRule(IPage<CodeRuleVO> page, CodeRuleVO codeRule) throws VciBaseException {
|
return gridCodeRule(page, codeRule);
|
}
|
|
/**
|
* 停用与启用编码规则
|
*
|
* @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<CodeRule> wrapper = Wrappers.<CodeRule>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<CodeBasicSecDTO> secList = codeRuleDTO.getElements();
|
List<CodeBasicSec> 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);
|
}
|
|
|
}
|