From 298a6a7085823ec754762c39affe145bb47e4aaa Mon Sep 17 00:00:00 2001 From: xuhy <3313886187@qq.com> Date: 星期四, 20 二月 2025 18:08:30 +0800 Subject: [PATCH] 合同新增审批 --- ruoyi-common/src/main/java/com/ruoyi/common/enums/ProcessCategoryEnum.java | 51 +++++++ ruoyi-common/src/main/java/com/ruoyi/common/enums/SubmitStatusEnum.java | 33 ++++ ruoyi-system/src/main/java/com/ruoyi/system/service/TContractService.java | 3 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java | 2 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java | 25 +++ ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java | 245 +++++++++++++++++++++++++++++++++++ ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java | 8 + ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java | 5 ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml | 11 + ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java | 2 10 files changed, 381 insertions(+), 4 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java index 391f5dc..c0e4618 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java @@ -3,6 +3,7 @@ import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.basic.PageInfo; @@ -10,10 +11,9 @@ import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.DictUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.WebUtils; +import com.ruoyi.common.enums.ProcessCategoryEnum; +import com.ruoyi.common.utils.*; +import com.ruoyi.system.bo.ProcessStartBO; import com.ruoyi.system.dto.*; import com.ruoyi.system.export.ContractExport; import com.ruoyi.system.export.OpticalInspectionExport; @@ -71,6 +71,8 @@ private TBillService billService; @Autowired private TCheckAcceptRecordService checkAcceptRecordService; + @Autowired + private StateProcessTemplateService stateProcessTemplateService; @ApiOperation(value = "测试生成账单") @PostMapping(value = "/testBill") @@ -197,6 +199,21 @@ tContractRentType.setChangeTime(dto.getChangeTime()); tContractRentType.setCycleTime(dto.getCycleTime()); contractRentTypeService.save(tContractRentType); + + //发起合同新增审批 + ProcessStartBO processStartBO = new ProcessStartBO(); + processStartBO.setCategory(ProcessCategoryEnum.CATEGORY1.getValue().toString()); + processStartBO.setModuleName("合同新增审批"); + processStartBO.setName(dto.getContractName()); + //需要显示发起申请人所在单位 +// String cedName = SecurityUtils.getLoginUser().getUser().getDept().getDeptName(); +// String remark = String.format("【镇/街】:%s,【征收实施单位】:%s,【申请金额】:%s万元", stateProject.getStreet(), cedName, stateApplyRecord.getAmount()); + processStartBO.setRemark(""); + Map<String, Object> variable = new HashMap<>(); + variable.put("projectId", dto.getId()); + processStartBO.setVariable(variable); + //开启工作流程 + stateProcessTemplateService.start(processStartBO); } return R.ok(); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/ProcessCategoryEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/ProcessCategoryEnum.java new file mode 100644 index 0000000..0b27e26 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/ProcessCategoryEnum.java @@ -0,0 +1,51 @@ +package com.ruoyi.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 1. 入户调查 + * 2. 价格评估 + * 3. 协议签订 + * 固定对应表 state_process_module + */ +@Getter +@AllArgsConstructor +public enum ProcessCategoryEnum { + CATEGORY0(0, "错误分类"), + CATEGORY1(1, "入户调查"), + CATEGORY2(2, "价格评估"), + CATEGORY3(3, "协议签订"), + ; + + + private final Integer value; + private final String text; + + public static Integer getValue(String text) { + for (ProcessCategoryEnum v : ProcessCategoryEnum.values()) { + if (v.text.equals(text)) { + return v.value; + } + } + return 0; + } + + public static String getValueByKey(Integer key) { + for (ProcessCategoryEnum v : ProcessCategoryEnum.values()) { + if (v.getValue().equals(key)) { + return v.getText(); + } + } + return ""; + } + + public static ProcessCategoryEnum getEnumByKey(Integer key) { + for (ProcessCategoryEnum v : ProcessCategoryEnum.values()) { + if (v.getValue().equals(key)) { + return v; + } + } + return CATEGORY0; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/SubmitStatusEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/SubmitStatusEnum.java new file mode 100644 index 0000000..9e231f3 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/SubmitStatusEnum.java @@ -0,0 +1,33 @@ +package com.ruoyi.common.enums; + +import lombok.Getter; + +import java.util.Objects; + +@Getter +public enum SubmitStatusEnum { + SUBMITTED(-1, ""), + REJECT(0, "已退回"), + PENDING_REVIEW(1, "待审核"), + ACCEPT(3, "已接收"); + + private final int value; + private final String text; + + public static String getTextByValue(Integer value) { + if (Objects.isNull(value)) { + return ""; + } + for (SubmitStatusEnum v : SubmitStatusEnum.values()) { + if (v.getValue() == (value)) { + return v.getText(); + } + } + return ""; + } + + SubmitStatusEnum(int value, String text) { + this.text = text; + this.value = value; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java index 9d66e47..ada62eb 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java @@ -127,4 +127,6 @@ List<SysRole> selectPageList(@Param("query")SysRoleQuery query,@Param("pageInfo") PageInfo<SysRole> pageInfo); + List<SysRole> selectRoleByUserIds(@Param("roleIds")List<String> roleIds); + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java index 7a50061..063e8a5 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java @@ -232,4 +232,6 @@ * @return 结果 */ public int editRole(SysRoleDTO dto); + + List<SysRole> selectRoleByUserIds(List<String> roleIds); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TContractService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TContractService.java index 5139836..00b2a31 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TContractService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TContractService.java @@ -40,4 +40,7 @@ void export(TContractQuery query); List<TContract> contractExportList(TContractQuery query); + + Boolean updateContractAuditStatus(String projectId, Integer submitStatus); + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java new file mode 100644 index 0000000..6ee462d --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java @@ -0,0 +1,245 @@ +package com.ruoyi.system.service.impl; + + +import cn.hutool.core.util.ObjectUtil; +import com.aizuda.bpm.engine.FlowLongEngine; +import com.aizuda.bpm.engine.assist.ObjectUtils; +import com.aizuda.bpm.engine.core.FlowCreator; +import com.aizuda.bpm.engine.core.FlowLongContext; +import com.aizuda.bpm.engine.core.enums.EventType; +import com.aizuda.bpm.engine.core.enums.NodeApproveSelf; +import com.aizuda.bpm.engine.core.enums.NodeSetType; +import com.aizuda.bpm.engine.core.enums.TaskType; +import com.aizuda.bpm.engine.entity.FlwExtInstance; +import com.aizuda.bpm.engine.entity.FlwHisTask; +import com.aizuda.bpm.engine.entity.FlwTask; +import com.aizuda.bpm.engine.entity.FlwTaskActor; +import com.aizuda.bpm.engine.listener.TaskListener; +import com.aizuda.bpm.engine.model.NodeAssignee; +import com.aizuda.bpm.engine.model.NodeModel; +import com.aizuda.bpm.engine.model.ProcessModel; +import com.aizuda.bpm.mybatisplus.mapper.FlwExtInstanceMapper; +import com.aizuda.bpm.mybatisplus.mapper.FlwHisTaskMapper; +import com.aizuda.bpm.mybatisplus.mapper.FlwTaskActorMapper; +import com.aizuda.bpm.mybatisplus.mapper.FlwTaskMapper; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.enums.ProcessCategoryEnum; +import com.ruoyi.common.enums.SubmitStatusEnum; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.TContractService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; +import java.util.stream.Collectors; + + +/** + * 工作流程全局任务监听 同步方式 只监听流程完成、流程中断类型,修改拒绝状态 + * <p> + * 1. 入户调查 + * 2. 价格评估 + * 3. 协议签订 + * 4. 资金管理-预算资金 + * 5. 住宅临时安置补助费 + * 6. 停产停业经济损失补助费 + * 7. 安置情况(流程图中叫做录入货币补偿金额信息) + * 固定对应表 state_process_module + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class FlowListenerService implements TaskListener { + + private final FlwExtInstanceMapper flwExtInstanceMapper; + private final FlowLongEngine flowLongEngine; + private final FlwTaskActorMapper flwTaskActorMapper; + private final FlwHisTaskMapper flwHisTaskMapper; + private final ISysRoleService sysRoleService; + private final FlwTaskMapper flwTaskMapper; + private final TContractService contractService; + + + @Override + public boolean notify(EventType eventType, Supplier<FlwTask> supplier, NodeModel nodeModel, FlowCreator flowCreator) { + FlwTask flwTask = supplier.get(); + if (ObjectUtil.isNull(flwTask)) { + return true; + } + // 创建任务时候,判断是否自动审批通过 + if (EventType.create.eq(eventType)) { + Integer approveSelf = nodeModel.getApproveSelf(); + if (NodeApproveSelf.AutoSkip.eq(approveSelf)) { + // 普通成员情况 + List<NodeAssignee> nodeAssigneeList = null; + if (NodeSetType.specifyMembers.eq(nodeModel.getSetType())) { + nodeAssigneeList = nodeModel.getNodeAssigneeList(); + if (ObjectUtil.isEmpty(nodeAssigneeList)) { + return true; + } + //查询发起人 + LambdaQueryWrapper<FlwHisTask> flwHisTaskLambdaQueryWrapper = new LambdaQueryWrapper<>(); + flwHisTaskLambdaQueryWrapper.eq(FlwTask::getTaskType, TaskType.major.getValue()); + flwHisTaskLambdaQueryWrapper.eq(FlwTask::getInstanceId, flwTask.getInstanceId()); + FlwHisTask flwHisTask = flwHisTaskMapper.selectOne(flwHisTaskLambdaQueryWrapper); + if (ObjectUtil.isEmpty(flwHisTask)) { + return true; + } + //对比发起人和节点审批人 + if (nodeAssigneeList.stream().noneMatch(t -> Objects.equals(t.getId(), flwHisTask.getCreateId()))) { + return true; + } + //查询当前节点审核人是否与创建人一致 + List<FlwTaskActor> flwTaskActor = flwTaskActorMapper.selectListByTaskId(flwTask.getId()); + if (ObjectUtil.isNotEmpty(flwTaskActor)) { + for (FlwTaskActor flwTaskActor1 : flwTaskActor) { + if (flwTaskActor1.getActorId().equals(flwHisTask.getCreateId())) { + return flowLongEngine.autoJumpTask(flwTask.getId(), flowCreator); + } + } + } + } else if (NodeSetType.role.eq(nodeModel.getSetType())) { + //角色任务跳过 + nodeAssigneeList = nodeModel.getNodeAssigneeList(); + //获取角色下的用户 + List<String> roleIds = nodeAssigneeList.stream().map(NodeAssignee::getId).collect(Collectors.toList()); + List<SysRole> actorList = sysRoleService.selectRoleByUserIds(roleIds); + List<FlwTaskActor> flwTaskActors = new ArrayList<>(); + if(ObjectUtils.isNotEmpty(actorList)) { + for (SysRole sysRole : actorList) { + if(ObjectUtil.isEmpty(sysRole.getRoleName())) { + continue; + } + NodeAssignee nodeAssignee = new NodeAssignee(); + nodeAssignee.setId(String.valueOf(sysRole.getRoleId())); + nodeAssignee.setName(sysRole.getRoleName()); + flwTaskActors.add(FlwTaskActor.of(nodeAssignee, 0)); + } + } + if (ObjectUtil.isEmpty(flwTaskActors)) { + return true; + } + //查询发起人 + LambdaQueryWrapper<FlwHisTask> flwHisTaskLambdaQueryWrapper = new LambdaQueryWrapper<>(); + flwHisTaskLambdaQueryWrapper.eq(FlwTask::getTaskType, TaskType.major.getValue()); + flwHisTaskLambdaQueryWrapper.eq(FlwTask::getInstanceId, flwTask.getInstanceId()); + FlwHisTask flwHisTask = flwHisTaskMapper.selectOne(flwHisTaskLambdaQueryWrapper); + if (ObjectUtil.isEmpty(flwHisTask)) { + return true; + } + //对比发起人和节点审批人 + if (flwTaskActors.stream().noneMatch(t -> Objects.equals(t.getActorId(), flwHisTask.getCreateId()))) { + return true; + } + //查询当前节点审核人是否与创建人一致 + List<FlwTaskActor> flwTaskActor = flwTaskActorMapper.selectListByTaskId(flwTask.getId()); + if (ObjectUtil.isNotEmpty(flwTaskActor)) { + for (FlwTaskActor flwTaskActor1 : flwTaskActor) { + if (flwTaskActor1.getActorId().equals(flwHisTask.getCreateId())) { + return flowLongEngine.autoJumpTask(flwTask.getId(), flowCreator); + } + } + } + } + } + } + + if (eventType.equals(EventType.reject) || eventType.equals(EventType.autoReject)) { + System.out.println("流程失败:" + flwTask.getVariable()); + handlerBusiness(flwTask.getVariable(), 2); + } else if (eventType.equals(EventType.complete)) { + // 查询流程模型 + FlwExtInstance flwExtInstance = flwExtInstanceMapper.selectById(flwTask.getInstanceId()); + String modelContent = flwExtInstance.getModelContent(); + ProcessModel processModel = FlowLongContext.parseProcessModel(modelContent, null, false); + NodeModel node = processModel.getNode(flwTask.getTaskKey()); + if (ObjectUtil.isEmpty(node)) { + log.error("节点不存在 TaskName:{} InstanceId:{}", flwTask.getTaskName(), flwTask.getInstanceId()); + return true; + } + long count = flwTaskMapper.selectCount(new LambdaQueryWrapper<FlwTask>().eq(FlwTask::getInstanceId,flwTask.getInstanceId())); + if(count > 0){ + return true; + } + //最后一个节点 + if (ObjectUtil.isEmpty(node.getChildNode()) || ObjectUtil.isEmpty(node.getChildNode().getNodeName())) { + System.out.println("流程完成:" + flwTask.getVariable()); + handlerBusiness(flwTask.getVariable(), 1); + } + } else if (eventType.eq(EventType.cc)) { + // 查询流程模型//抄送 + FlwExtInstance flwExtInstance = flwExtInstanceMapper.selectById(flwTask.getInstanceId()); + String modelContent = flwExtInstance.getModelContent(); + ProcessModel processModel = FlowLongContext.parseProcessModel(modelContent, null, false); + NodeModel node = processModel.getNode(flwTask.getTaskKey()); + if (ObjectUtil.isEmpty(node)) { + log.error("节点不存在 TaskName:{} InstanceId:{}", flwTask.getTaskName(), flwTask.getInstanceId()); + return true; + } + //抄送是最后一个节点 + if (ObjectUtil.isEmpty(node.getChildNode()) || ObjectUtil.isEmpty(node.getChildNode().getNodeName())) { + System.out.println("流程完成:" + flwTask.getVariable()); + handlerBusiness(flwTask.getVariable(), 1); + } + } else if(eventType.eq(EventType.autoJump)){ + // 查询流程模型 自动跳转 + FlwExtInstance flwExtInstance = flwExtInstanceMapper.selectById(flwTask.getInstanceId()); + String modelContent = flwExtInstance.getModelContent(); + ProcessModel processModel = FlowLongContext.parseProcessModel(modelContent, null, false); + NodeModel node = processModel.getNode(flwTask.getTaskKey()); + if (ObjectUtil.isEmpty(node)) { + log.error("节点不存在 TaskName:{} InstanceId:{}", flwTask.getTaskName(), flwTask.getInstanceId()); + return true; + } + long count = flwTaskMapper.selectCount(new LambdaQueryWrapper<FlwTask>().eq(FlwTask::getInstanceId,flwTask.getInstanceId())); + if(count > 0){ + return true; + } + //最后一个节点 + if (ObjectUtil.isEmpty(node.getChildNode()) || ObjectUtil.isEmpty(node.getChildNode().getNodeName())) { + System.out.println("流程完成:" + flwTask.getVariable()); + handlerBusiness(flwTask.getVariable(), 1); + } + } + return true; + } + + /** + * 业务状态变更 + */ + private void handlerBusiness(String variable, Integer status) { + JSONObject processParameter = JSON.parseObject(variable); + //必须参数,肯定有不判断null + Integer category = processParameter.getInteger("category"); + //状态 暂定:0待审核 1审核通过 2审核拒绝 + ProcessCategoryEnum categoryEnum = ProcessCategoryEnum.getEnumByKey(category); + switch (categoryEnum) { + case CATEGORY1: { + // 合同新增审批 + int submitStatus = status==0?2:(status==1?3:5); + contractService.updateContractAuditStatus(processParameter.getString("projectId"), submitStatus); + break; + } + case CATEGORY2: { + // 合同签订审批 + break; + } + case CATEGORY3: { + // 合同提前终止审批 + break; + } + default: + throw new ServiceException("错误类型"); + } + + } + +} \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java index 86924f1..a310cf7 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -606,4 +606,9 @@ return roleMenuMapper.batchRoleMenu(sysRoleMenus); } + + @Override + public List<SysRole> selectRoleByUserIds(List<String> roleIds) { + return roleMapper.selectRoleByUserIds(roleIds); + } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java index cbfbde3..61c5b1f 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java @@ -1,6 +1,7 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.ruoyi.common.basic.PageInfo; import com.ruoyi.common.constant.DictConstants; import com.ruoyi.common.core.domain.R; @@ -638,4 +639,11 @@ return list; } + + @Override + public Boolean updateContractAuditStatus(String projectId, Integer status) { + LambdaUpdateWrapper<TContract> contractLambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + contractLambdaUpdateWrapper.eq(TContract::getId, projectId).set(TContract::getStatus, status); + return this.update(contractLambdaUpdateWrapper); + } } diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml index f24c54f..f3dfeeb 100644 --- a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -148,6 +148,17 @@ left join sys_role t2 on t1.role_id = t2.role_id where t1.user_id = #{userId} </select> + <select id="selectRoleByUserIds" resultType="com.ruoyi.common.core.domain.entity.SysRole"> + select + a.user_id as role_id, + b.nick_name as role_name + from sys_user_role a + left join sys_user b on a.user_id = b.user_id + where a.role_id in + <foreach item="item" index="index" collection="roleIds" open="(" separator="," close=")"> + #{item} + </foreach> + </select> <insert id="insertRole" parameterType="SysRole" useGeneratedKeys="true" keyProperty="roleId"> insert into sys_role( -- Gitblit v1.7.1