update 优化流程分类校验

This commit is contained in:
AprilWind 2024-12-16 14:30:39 +08:00
parent 8333435770
commit eba12bf236
11 changed files with 485 additions and 121 deletions

View File

@ -2,10 +2,11 @@ package org.dromara.workflow.controller;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.excel.utils.ExcelUtil;
@ -25,7 +26,6 @@ import java.util.List;
* 流程分类 * 流程分类
* *
* @author may * @author may
* @date 2023-06-28
*/ */
@Validated @Validated
@RequiredArgsConstructor @RequiredArgsConstructor
@ -33,16 +33,16 @@ import java.util.List;
@RequestMapping("/workflow/category") @RequestMapping("/workflow/category")
public class FlwCategoryController extends BaseController { public class FlwCategoryController extends BaseController {
private final IFlwCategoryService FlowCategoryService; private final IFlwCategoryService flwCategoryService;
/** /**
* 查询流程分类列表 * 查询流程分类列表
*/ */
@SaCheckPermission("workflow:category:list")
@GetMapping("/list") @GetMapping("/list")
public R<List<FlowCategoryVo>> list(FlowCategoryBo bo) { public R<List<FlowCategoryVo>> list(FlowCategoryBo bo) {
List<FlowCategoryVo> list = FlowCategoryService.queryList(bo); List<FlowCategoryVo> list = flwCategoryService.queryList(bo);
return R.ok(list); return R.ok(list);
} }
/** /**
@ -52,19 +52,20 @@ public class FlwCategoryController extends BaseController {
@Log(title = "流程分类", businessType = BusinessType.EXPORT) @Log(title = "流程分类", businessType = BusinessType.EXPORT)
@PostMapping("/export") @PostMapping("/export")
public void export(FlowCategoryBo bo, HttpServletResponse response) { public void export(FlowCategoryBo bo, HttpServletResponse response) {
List<FlowCategoryVo> list = FlowCategoryService.queryList(bo); List<FlowCategoryVo> list = flwCategoryService.queryList(bo);
ExcelUtil.exportExcel(list, "流程分类", FlowCategoryVo.class, response); ExcelUtil.exportExcel(list, "流程分类", FlowCategoryVo.class, response);
} }
/** /**
* 获取流程分类详细信息 * 获取流程分类详细信息
* *
* @param id 主键 * @param categoryId 主键
*/ */
@GetMapping("/{id}") @SaCheckPermission("workflow:category:query")
public R<FlowCategoryVo> getInfo(@NotNull(message = "主键不能为空") @GetMapping("/{categoryId}")
@PathVariable Long id) { public R<FlowCategoryVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long categoryId) {
return R.ok(FlowCategoryService.queryById(id)); flwCategoryService.checkCategoryDataScope(categoryId);
return R.ok(flwCategoryService.queryById(categoryId));
} }
/** /**
@ -74,8 +75,11 @@ public class FlwCategoryController extends BaseController {
@Log(title = "流程分类", businessType = BusinessType.INSERT) @Log(title = "流程分类", businessType = BusinessType.INSERT)
@RepeatSubmit() @RepeatSubmit()
@PostMapping() @PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody FlowCategoryBo bo) { public R<Void> add(@Validated(AddGroup.class) @RequestBody FlowCategoryBo category) {
return toAjax(FlowCategoryService.insertByBo(bo)); if (!flwCategoryService.checkCategoryNameUnique(category)) {
return R.fail("新增流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在");
}
return toAjax(flwCategoryService.insertByBo(category));
} }
/** /**
@ -85,20 +89,39 @@ public class FlwCategoryController extends BaseController {
@Log(title = "流程分类", businessType = BusinessType.UPDATE) @Log(title = "流程分类", businessType = BusinessType.UPDATE)
@RepeatSubmit() @RepeatSubmit()
@PutMapping() @PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody FlowCategoryBo bo) { public R<Void> edit(@Validated(EditGroup.class) @RequestBody FlowCategoryBo category) {
return toAjax(FlowCategoryService.updateByBo(bo)); Long categoryId = category.getCategoryId();
flwCategoryService.checkCategoryDataScope(categoryId);
if (!flwCategoryService.checkCategoryNameUnique(category)) {
return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在");
} else if (category.getParentId().equals(categoryId)) {
return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,上级流程分类不能是自己");
} else if (StringUtils.equals(SystemConstants.DISABLE, category.getStatus())) {
if (flwCategoryService.selectNormalChildrenCategoryById(categoryId) > 0) {
return R.fail("该流程分类包含未停用的子流程分类!");
} else if (flwCategoryService.checkCategoryExistDefinition(categoryId)) {
return R.fail("该部门下存在已分配流程定义,不能禁用!");
}
}
return toAjax(flwCategoryService.updateByBo(category));
} }
/** /**
* 删除流程分类 * 删除流程分类
* *
* @param ids 主键串 * @param categoryId 主键
*/ */
@SaCheckPermission("workflow:category:remove") @SaCheckPermission("workflow:category:remove")
@Log(title = "流程分类", businessType = BusinessType.DELETE) @Log(title = "流程分类", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}") @DeleteMapping("/{categoryId}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") public R<Void> remove(@PathVariable Long categoryId) {
@PathVariable Long[] ids) { if (flwCategoryService.hasChildByCategoryId(categoryId)) {
return toAjax(FlowCategoryService.deleteWithValidByIds(List.of(ids), true)); return R.warn("存在下级流程分类,不允许删除");
}
if (flwCategoryService.checkCategoryExistDefinition(categoryId)) {
return R.warn("流程分类存在流程定义,不允许删除");
}
return toAjax(flwCategoryService.deleteWithValidById(categoryId));
} }
} }

View File

@ -1,5 +1,6 @@
package org.dromara.workflow.controller; package org.dromara.workflow.controller;
import cn.hutool.core.lang.tree.Tree;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
@ -11,7 +12,9 @@ import org.dromara.common.web.core.BaseController;
import org.dromara.warm.flow.core.entity.Definition; import org.dromara.warm.flow.core.entity.Definition;
import org.dromara.warm.flow.core.service.DefService; import org.dromara.warm.flow.core.service.DefService;
import org.dromara.warm.flow.orm.entity.FlowDefinition; import org.dromara.warm.flow.orm.entity.FlowDefinition;
import org.dromara.workflow.domain.bo.FlowCategoryBo;
import org.dromara.workflow.domain.vo.FlowDefinitionVo; import org.dromara.workflow.domain.vo.FlowDefinitionVo;
import org.dromara.workflow.service.IFlwCategoryService;
import org.dromara.workflow.service.IFlwDefinitionService; import org.dromara.workflow.service.IFlwDefinitionService;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -32,6 +35,7 @@ import java.util.List;
@RequestMapping("/workflow/definition") @RequestMapping("/workflow/definition")
public class FlwDefinitionController extends BaseController { public class FlwDefinitionController extends BaseController {
private final IFlwCategoryService flwCategoryService;
private final IFlwDefinitionService iFlwDefinitionService; private final IFlwDefinitionService iFlwDefinitionService;
private final DefService defService; private final DefService defService;
@ -45,6 +49,14 @@ public class FlwDefinitionController extends BaseController {
return iFlwDefinitionService.page(flowDefinition, pageQuery); return iFlwDefinitionService.page(flowDefinition, pageQuery);
} }
/**
* 获取流程分类树列表
*/
@GetMapping("/categoryTree")
public R<List<Tree<Long>>> categoryTree(FlowCategoryBo dept) {
return R.ok(flwCategoryService.selectCategoryTreeList(dept));
}
/** /**
* 获取历史流程定义列表 * 获取历史流程定义列表
* *

View File

@ -99,7 +99,6 @@ public class FlwTaskController extends BaseController {
* @param flowTaskBo 参数 * @param flowTaskBo 参数
* @param pageQuery 分页 * @param pageQuery 分页
*/ */
@GetMapping("/pageByAllTaskFinish") @GetMapping("/pageByAllTaskFinish")
public TableDataInfo<FlowHisTaskVo> pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { public TableDataInfo<FlowHisTaskVo> pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
return flwTaskService.pageByAllTaskFinish(flowTaskBo, pageQuery); return flwTaskService.pageByAllTaskFinish(flowTaskBo, pageQuery);

View File

@ -1,6 +1,7 @@
package org.dromara.workflow.domain; package org.dromara.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -23,25 +24,45 @@ public class FlowCategory extends TenantEntity {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 主键 * 流程分类ID
*/ */
@TableId(value = "id") @TableId(value = "category_id")
private Long id; private Long categoryId;
/** /**
* 分类名称 * 父流程分类id
*/
private String categoryName;
/**
* 父级id
*/ */
private Long parentId; private Long parentId;
/** /**
* 排序 * 祖级列表
*/ */
private Long sortNum; private String ancestors;
/**
* 流程分类名称
*/
private String categoryName;
/**
* 流程分类编码
*/
private String categoryCode;
/**
* 显示顺序
*/
private Long orderNum;
/**
* 流程分类状态0正常 1停用
*/
private String status;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
} }

View File

@ -22,26 +22,36 @@ import org.dromara.workflow.domain.FlowCategory;
public class FlowCategoryBo extends BaseEntity { public class FlowCategoryBo extends BaseEntity {
/** /**
* 主键 * 流程分类ID
*/ */
@NotNull(message = "主键不能为空", groups = {EditGroup.class}) @NotNull(message = "流程分类ID不能为空", groups = { EditGroup.class })
private Long id; private Long categoryId;
/** /**
* 分类名称 * 父流程分类id
*/ */
@NotBlank(message = "分类名称不能为空", groups = {AddGroup.class, EditGroup.class}) @NotNull(message = "父流程分类id不能为空", groups = {AddGroup.class, EditGroup.class})
private String categoryName;
/**
* 父级id
*/
@NotNull(message = "父级id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long parentId; private Long parentId;
/** /**
* 排序 * 流程分类名称
*/ */
private Long sortNum; @NotBlank(message = "流程分类名称不能为空", groups = {AddGroup.class, EditGroup.class})
private String categoryName;
/**
* 流程分类编码
*/
private String categoryCode;
/**
* 显示顺序
*/
private Long orderNum;
/**
* 流程分类状态0正常 1停用
*/
private String status;
} }

View File

@ -4,10 +4,13 @@ import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data; import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.workflow.domain.FlowCategory; import org.dromara.workflow.domain.FlowCategory;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
/** /**
@ -25,28 +28,55 @@ public class FlowCategoryVo implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 主键 * 流程分类ID
*/ */
@ExcelProperty(value = "主键") @ExcelProperty(value = "流程分类ID")
private Long id; private Long categoryId;
/** /**
* 分类名称 * 父部门id
*/ */
@ExcelProperty(value = "分类名称")
private String categoryName;
/**
* 父级id
*/
@ExcelProperty(value = "父级id")
private Long parentId; private Long parentId;
/** /**
* 排序 * 父部门名称
*/ */
@ExcelProperty(value = "排序") private String parentName;
private Long sortNum;
/**
* 祖级列表
*/
private String ancestors;
/**
* 流程分类名称
*/
@ExcelProperty(value = "流程分类名称")
private String categoryName;
/**
* 流程分类编码
*/
@ExcelProperty(value = "流程分类编码")
private String categoryCode;
/**
* 显示顺序
*/
@ExcelProperty(value = "显示顺序")
private Long orderNum;
/**
* 流程分类状态0正常 1停用
*/
@ExcelProperty(value = "流程分类状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=正常,1=停用")
private String status;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
} }

View File

@ -1,5 +1,7 @@
package org.dromara.workflow.mapper; package org.dromara.workflow.mapper;
import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.annotation.DataPermission;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.workflow.domain.FlowCategory; import org.dromara.workflow.domain.FlowCategory;
import org.dromara.workflow.domain.vo.FlowCategoryVo; import org.dromara.workflow.domain.vo.FlowCategoryVo;
@ -12,4 +14,15 @@ import org.dromara.workflow.domain.vo.FlowCategoryVo;
*/ */
public interface FlwCategoryMapper extends BaseMapperPlus<FlowCategory, FlowCategoryVo> { public interface FlwCategoryMapper extends BaseMapperPlus<FlowCategory, FlowCategoryVo> {
/**
* 统计指定流程分类ID的分类数量
*
* @param categoryId 流程分类ID
* @return 该流程分类ID的分类数量
*/
@DataPermission({
@DataColumn(key = "deptName", value = "createDept")
})
long countCategoryById(Long categoryId);
} }

View File

@ -1,42 +1,102 @@
package org.dromara.workflow.service; package org.dromara.workflow.service;
import cn.hutool.core.lang.tree.Tree;
import org.dromara.workflow.domain.bo.FlowCategoryBo; import org.dromara.workflow.domain.bo.FlowCategoryBo;
import org.dromara.workflow.domain.vo.FlowCategoryVo; import org.dromara.workflow.domain.vo.FlowCategoryVo;
import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
* 流程分类Service接口 * 流程分类Service接口
* *
* @author may * @author may
* @date 2023-06-28
*/ */
public interface IFlwCategoryService { public interface IFlwCategoryService {
/** /**
* 查询流程分类 * 查询流程分类
*
* @param categoryId 主键
* @return 流程分类
*/ */
FlowCategoryVo queryById(Long id); FlowCategoryVo queryById(Long categoryId);
/** /**
* 查询流程分类列表 * 查询符合条件的流程分类列表
*
* @param bo 查询条件
* @return 流程分类列表
*/ */
List<FlowCategoryVo> queryList(FlowCategoryBo bo); List<FlowCategoryVo> queryList(FlowCategoryBo bo);
/** /**
* 新增流程分类 * 查询流程分类树结构信息
*
* @param category 流程分类信息
* @return 流程分类树信息集合
*/ */
Boolean insertByBo(FlowCategoryBo bo); List<Tree<Long>> selectCategoryTreeList(FlowCategoryBo category);
/**
* 校验流程分类是否有数据权限
*
* @param categoryId 流程分类ID
*/
void checkCategoryDataScope(Long categoryId);
/**
* 校验流程分类名称是否唯一
*
* @param category 流程分类信息
* @return 结果
*/
boolean checkCategoryNameUnique(FlowCategoryBo category);
/**
* 根据ID查询所有子流程分类数正常状态
*
* @param categoryId 流程分类ID
* @return 子流程分类数
*/
long selectNormalChildrenCategoryById(Long categoryId);
/**
* 查询流程分类是否存在流程定义
*
* @param categoryId 流程分类ID
* @return 结果 true 存在 false 不存在
*/
boolean checkCategoryExistDefinition(Long categoryId);
/**
* 是否存在流程分类子节点
*
* @param categoryId 流程分类ID
* @return 结果
*/
boolean hasChildByCategoryId(Long categoryId);
/**
* 新增流程分类
*
* @param bo 流程分类
* @return 是否新增成功
*/
int insertByBo(FlowCategoryBo bo);
/** /**
* 修改流程分类 * 修改流程分类
*
* @param bo 流程分类
* @return 是否修改成功
*/ */
Boolean updateByBo(FlowCategoryBo bo); int updateByBo(FlowCategoryBo bo);
/** /**
* 校验并批量删除流程分类信息 * 删除流程分类信息
*
* @param categoryId 主键
* @return 是否删除成功
*/ */
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); int deleteWithValidById(Long categoryId);
} }

View File

@ -1,44 +1,66 @@
package org.dromara.workflow.service.impl; package org.dromara.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.*;
import org.dromara.common.mybatis.helper.DataBaseHelper;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.warm.flow.core.service.DefService;
import org.dromara.warm.flow.orm.entity.FlowDefinition;
import org.dromara.workflow.domain.FlowCategory; import org.dromara.workflow.domain.FlowCategory;
import org.dromara.workflow.domain.bo.FlowCategoryBo; import org.dromara.workflow.domain.bo.FlowCategoryBo;
import org.dromara.workflow.domain.vo.FlowCategoryVo; import org.dromara.workflow.domain.vo.FlowCategoryVo;
import org.dromara.workflow.mapper.FlwCategoryMapper; import org.dromara.workflow.mapper.FlwCategoryMapper;
import org.dromara.workflow.service.IFlwCategoryService; import org.dromara.workflow.service.IFlwCategoryService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
* 流程分类Service业务层处理 * 流程分类Service业务层处理
* *
* @author may * @author may
* @date 2023-06-28
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Service @Service
public class FlwCategoryServiceImpl implements IFlwCategoryService { public class FlwCategoryServiceImpl implements IFlwCategoryService {
private final FlwCategoryMapper baseMapper; private final FlwCategoryMapper baseMapper;
private final DefService defService;
/** /**
* 查询流程分类 * 查询流程分类
*
* @param categoryId 主键
* @return 流程分类
*/ */
@Override @Override
public FlowCategoryVo queryById(Long id) { public FlowCategoryVo queryById(Long categoryId) {
return baseMapper.selectVoById(id); FlowCategoryVo category = baseMapper.selectVoById(categoryId);
if (ObjectUtil.isNull(category)) {
return null;
}
FlowCategoryVo parentCategory = baseMapper.selectVoOne(new LambdaQueryWrapper<FlowCategory>()
.select(FlowCategory::getCategoryName).eq(FlowCategory::getCategoryId, category.getParentId()));
category.setParentName(ObjectUtils.notNullGetter(parentCategory, FlowCategoryVo::getCategoryName));
return category;
} }
/** /**
* 查询流程分类列表 * 查询符合条件的流程分类列表
*
* @param bo 查询条件
* @return 流程分类列表
*/ */
@Override @Override
public List<FlowCategoryVo> queryList(FlowCategoryBo bo) { public List<FlowCategoryVo> queryList(FlowCategoryBo bo) {
@ -46,52 +68,220 @@ public class FlwCategoryServiceImpl implements IFlwCategoryService {
return baseMapper.selectVoList(lqw); return baseMapper.selectVoList(lqw);
} }
/**
* 查询流程分类树结构信息
*
* @param category 流程分类信息
* @return 流程分类树信息集合
*/
@Override
public List<Tree<Long>> selectCategoryTreeList(FlowCategoryBo category) {
LambdaQueryWrapper<FlowCategory> lqw = buildQueryWrapper(category);
List<FlowCategoryVo> categorys = baseMapper.selectVoList(lqw);
if (CollUtil.isEmpty(categorys)) {
return CollUtil.newArrayList();
}
// 获取当前列表中每一个节点的parentId然后在列表中查找是否有id与其parentId对应若无对应则表明此时节点列表中该节点在当前列表中属于顶级节点
List<Tree<Long>> treeList = CollUtil.newArrayList();
for (FlowCategoryVo d : categorys) {
Long parentId = d.getParentId();
FlowCategoryVo categoryVo = StreamUtils.findFirst(categorys, it -> it.getCategoryId().longValue() == parentId);
if (ObjectUtil.isNull(categoryVo)) {
List<Tree<Long>> trees = TreeBuildUtils.build(categorys, parentId, (dept, tree) ->
tree.setId(dept.getCategoryId())
.setParentId(dept.getParentId())
.setName(dept.getCategoryName())
.setWeight(dept.getOrderNum())
.putExtra("disabled", SystemConstants.DISABLE.equals(dept.getStatus())));
Tree<Long> tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getCategoryId());
treeList.add(tree);
}
}
return treeList;
}
/**
* 校验流程分类是否有数据权限
*
* @param categoryId 流程分类ID
*/
@Override
public void checkCategoryDataScope(Long categoryId) {
if (ObjectUtil.isNull(categoryId)) {
return;
}
if (LoginHelper.isSuperAdmin()) {
return;
}
if (baseMapper.countCategoryById(categoryId) == 0) {
throw new ServiceException("没有权限访问流程分类数据!");
}
}
/**
* 校验流程分类名称是否唯一
*
* @param category 流程分类信息
* @return 结果
*/
@Override
public boolean checkCategoryNameUnique(FlowCategoryBo category) {
boolean exist = baseMapper.exists(new LambdaQueryWrapper<FlowCategory>()
.eq(FlowCategory::getCategoryName, category.getCategoryName())
.eq(FlowCategory::getParentId, category.getParentId())
.ne(ObjectUtil.isNotNull(category.getCategoryId()), FlowCategory::getCategoryId, category.getCategoryId()));
return !exist;
}
/**
* 根据ID查询所有子流程分类数正常状态
*
* @param categoryId 流程分类ID
* @return 子流程分类数
*/
@Override
public long selectNormalChildrenCategoryById(Long categoryId) {
return baseMapper.selectCount(new LambdaQueryWrapper<FlowCategory>()
.eq(FlowCategory::getStatus, SystemConstants.NORMAL)
.apply(DataBaseHelper.findInSet(categoryId, "ancestors")));
}
/**
* 查询流程分类是否存在流程定义
*
* @param categoryId 流程分类ID
* @return 结果 true 存在 false 不存在
*/
@Override
public boolean checkCategoryExistDefinition(Long categoryId) {
FlowDefinition definition = new FlowDefinition();
definition.setCategory(categoryId.toString());
return defService.exists(definition);
}
/**
* 是否存在流程分类子节点
*
* @param categoryId 流程分类ID
* @return 结果
*/
@Override
public boolean hasChildByCategoryId(Long categoryId) {
return baseMapper.exists(new LambdaQueryWrapper<FlowCategory>()
.eq(FlowCategory::getParentId, categoryId));
}
private LambdaQueryWrapper<FlowCategory> buildQueryWrapper(FlowCategoryBo bo) { private LambdaQueryWrapper<FlowCategory> buildQueryWrapper(FlowCategoryBo bo) {
LambdaQueryWrapper<FlowCategory> lqw = Wrappers.lambdaQuery(); LambdaQueryWrapper<FlowCategory> lqw = Wrappers.lambdaQuery();
lqw.eq(FlowCategory::getDelFlag, SystemConstants.NORMAL);
lqw.eq(ObjectUtil.isNotNull(bo.getCategoryId()), FlowCategory::getCategoryId, bo.getCategoryId());
lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), FlowCategory::getParentId, bo.getParentId());
lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), FlowCategory::getCategoryName, bo.getCategoryName()); lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), FlowCategory::getCategoryName, bo.getCategoryName());
lqw.like(StringUtils.isNotBlank(bo.getCategoryCode()), FlowCategory::getCategoryCode, bo.getCategoryCode());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), FlowCategory::getStatus, bo.getStatus());
lqw.orderByAsc(FlowCategory::getAncestors);
lqw.orderByAsc(FlowCategory::getParentId);
lqw.orderByAsc(FlowCategory::getOrderNum);
lqw.orderByAsc(FlowCategory::getCategoryId);
return lqw; return lqw;
} }
/** /**
* 新增流程分类 * 新增流程分类
*
* @param bo 流程分类
* @return 是否新增成功
*/ */
@Override @Override
public Boolean insertByBo(FlowCategoryBo bo) { public int insertByBo(FlowCategoryBo bo) {
FlowCategory add = MapstructUtils.convert(bo, FlowCategory.class); FlowCategory info = baseMapper.selectById(bo.getParentId());
validEntityBeforeSave(add); // 如果父节点不为正常状态,则不允许新增子节点
boolean flag = baseMapper.insert(add) > 0; if (!SystemConstants.NORMAL.equals(info.getStatus())) {
if (flag) { throw new ServiceException("流程分类停用,不允许新增");
bo.setId(add.getId());
} }
return flag; FlowCategory category = MapstructUtils.convert(bo, FlowCategory.class);
category.setAncestors(info.getAncestors() + StringUtils.SEPARATOR + category.getParentId());
return baseMapper.insert(category);
} }
/** /**
* 修改流程分类 * 修改流程分类
*
* @param bo 流程分类
* @return 是否修改成功
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) public int updateByBo(FlowCategoryBo bo) {
public Boolean updateByBo(FlowCategoryBo bo) { FlowCategory category = MapstructUtils.convert(bo, FlowCategory.class);
FlowCategory update = MapstructUtils.convert(bo, FlowCategory.class); FlowCategory oldCategory = baseMapper.selectById(category.getCategoryId());
validEntityBeforeSave(update); if (ObjectUtil.isNull(oldCategory)) {
return baseMapper.updateById(update) > 0; throw new ServiceException("流程分类不存在,无法修改");
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(FlowCategory entity) {
// 做一些数据校验,如唯一约束
}
/**
* 批量删除流程分类
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// 做一些业务上的校验,判断是否需要校验
} }
return baseMapper.deleteByIds(ids) > 0; if (!oldCategory.getParentId().equals(category.getParentId())) {
// 如果是新父流程分类 则校验是否具有新父流程分类权限 避免越权
this.checkCategoryDataScope(category.getParentId());
FlowCategory newParentCategory = baseMapper.selectById(category.getParentId());
if (ObjectUtil.isNotNull(newParentCategory)) {
String newAncestors = newParentCategory.getAncestors() + StringUtils.SEPARATOR + newParentCategory.getCategoryId();
String oldAncestors = oldCategory.getAncestors();
category.setAncestors(newAncestors);
updateCategoryChildren(category.getCategoryId(), newAncestors, oldAncestors);
}
} else {
category.setAncestors(oldCategory.getAncestors());
}
int result = baseMapper.updateById(category);
if (SystemConstants.NORMAL.equals(category.getStatus()) && StringUtils.isNotEmpty(category.getAncestors())
&& !StringUtils.equals(SystemConstants.NORMAL, category.getAncestors())) {
// 如果该流程分类是启用状态则启用该流程分类的所有上级流程分类
updateParentCategoryStatusNormal(category);
}
return result;
}
/**
* 修改子元素关系
*
* @param categoryId 被修改的流程分类ID
* @param newAncestors 新的父ID集合
* @param oldAncestors 旧的父ID集合
*/
private void updateCategoryChildren(Long categoryId, String newAncestors, String oldAncestors) {
List<FlowCategory> children = baseMapper.selectList(new LambdaQueryWrapper<FlowCategory>()
.apply(DataBaseHelper.findInSet(categoryId, "ancestors")));
List<FlowCategory> list = new ArrayList<>();
for (FlowCategory child : children) {
FlowCategory category = new FlowCategory();
category.setCategoryId(child.getCategoryId());
category.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
list.add(category);
}
if (CollUtil.isNotEmpty(list)) {
baseMapper.updateBatchById(list);
}
}
/**
* 修改该流程分类的父级流程分类状态
*
* @param category 当前流程分类
*/
private void updateParentCategoryStatusNormal(FlowCategory category) {
String ancestors = category.getAncestors();
Long[] categoryIds = Convert.toLongArray(ancestors);
baseMapper.update(null, new LambdaUpdateWrapper<FlowCategory>()
.set(FlowCategory::getStatus, SystemConstants.NORMAL)
.in(FlowCategory::getCategoryId, Arrays.asList(categoryIds)));
}
/**
* 删除流程分类信息
*
* @param categoryId 主键
* @return 是否删除成功
*/
@Override
public int deleteWithValidById(Long categoryId) {
return baseMapper.deleteById(categoryId);
} }
} }

View File

@ -4,4 +4,8 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.FlwCategoryMapper"> <mapper namespace="org.dromara.workflow.mapper.FlwCategoryMapper">
<select id="countCategoryById" resultType="Long">
select count(*) from flow_category where del_flag = '0' and category_id = #{categoryId}
</select>
</mapper> </mapper>

View File

@ -151,22 +151,24 @@ CREATE TABLE `flow_user`
-- ---------------------------- -- ----------------------------
create table flow_category create table flow_category
( (
id bigint(20) not null comment '流程分类ID', category_id bigint(20) not null comment '流程分类ID',
tenant_id varchar(20) default '000000' comment '租户编号', tenant_id varchar(20) default '000000' comment '租户编号',
category_name varchar(255) null comment '分类名称', parent_id bigint(20) default 0 comment '父流程分类id',
category_code varchar(255) null comment '分类编码', ancestors varchar(500) default '' comment '祖级列表',
parent_id bigint null comment '父级id', category_name varchar(30) not null comment '流程分类名称',
sort_num int(19) null comment '排序', category_code varchar(100) default '' comment '流程分类编码',
create_dept bigint(20) null comment '创建部门', order_num int(4) default 0 comment '显示顺序',
create_by bigint(20) null comment '创建者', status char(1) default '0' comment '流程分类状态0正常 1停用',
create_time datetime null comment '创建时间', del_flag char(1) default '0' comment '删除标志0代表存在 2代表删除',
update_by bigint(20) null comment '更新者', create_dept bigint(20) null comment '创建部门',
update_time datetime null comment '更新时间', create_by bigint(20) null comment '创建者',
constraint uni_category_code unique (category_code), create_time datetime null comment '创建时间',
primary key (id) update_by bigint(20) null comment '更新者',
update_time datetime null comment '更新时间',
primary key (category_id)
) engine = innodb comment = '流程分类'; ) engine = innodb comment = '流程分类';
INSERT INTO flow_category values (1, '000000', 'OA', 'OA', 0, 0, 103, 1, sysdate(), null, null); INSERT INTO flow_category values (1, '000000', 0, '0', 'OA', 'OA', 0, '0', '0', 103, 1, sysdate(), null, null);
-- ---------------------------- -- ----------------------------
-- 请假单信息 -- 请假单信息