应征入伍保留学籍工作流

This commit is contained in:
2025-11-11 11:50:07 +08:00
parent 434cbc0c0e
commit 52de1dda74
5 changed files with 186 additions and 9 deletions

View File

@@ -0,0 +1,150 @@
package com.srs.flowable.listener.enlistmentReserve;
import com.srs.common.core.domain.entity.SysUser;
import com.srs.common.utils.SecurityUtils;
import com.srs.system.service.ISysUserService;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 审批流程负责人自动流转监听器
* 用于节点审批通过时,更新下一个节点的负责人变量(approval)
*/
@Component("approvalAssigneeListener") // Spring Bean名称与BPMN表达式对应
public class ApprovalAssigneeListener implements ExecutionListener {
@Autowired
private ISysUserService sysUserService; // 用户服务(查询部门/学院负责人)
// @Autowired
// private FlowBusinessService enlistmentReserveMapper; // 业务表Mapper
@Autowired
private HistoryService historyService; // Flowable历史服务
// 用于查询流程定义中的节点信息
@Autowired
private RepositoryService repositoryService;
@Override
public void notify(DelegateExecution execution) {
// 1. 获取当前节点ID和流程定义ID
String currentActivityId = execution.getCurrentActivityId(); // 当前节点ID兼容所有版本
String processDefinitionId = execution.getProcessDefinitionId(); // 流程定义ID
// 2. 根据节点ID查询节点名称核心修正通过流程定义获取名称
String currentNodeName = getNodeNameByActivityId(processDefinitionId, currentActivityId);
if (currentNodeName == null) {
throw new RuntimeException("未找到节点ID=" + currentActivityId + "的名称");
}
// 3. 获取流程实例ID
String processInstanceId = execution.getProcessInstanceId();
// 4. 后续逻辑不变:查询下一个节点负责人并更新变量
Long nextAssigneeId = getNextAssignee(currentNodeName, processInstanceId);
if (nextAssigneeId != null) {
execution.setVariable("approval", nextAssigneeId);
execution.setVariable("currentNode", currentNodeName);
}
}
/**
* 根据节点ID和流程定义ID查询节点名称兼容所有版本的核心方法
*/
private String getNodeNameByActivityId(String processDefinitionId, String activityId) {
// 获取流程模型
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
if (bpmnModel == null) {
throw new RuntimeException("未找到流程定义ID=" + processDefinitionId + "的模型");
}
// 从模型中获取节点信息FlowNode包含用户任务、网关等节点
FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(activityId);
return flowNode != null ? flowNode.getName() : null;
}
/**
* 根据当前节点查询下一个节点的负责人
*/
private Long getNextAssignee(String currentNodeName, String processInstanceId) {
// 获取当前登录用户的部门id
Long currentDeptId = SecurityUtils.getDeptId();
if (currentDeptId == null) {
throw new RuntimeException("当前登录用户未分配部门,无法匹配学务负责人");
}
// 注意节点名称需与BPMN模型中完全一致区分大小写
switch (currentNodeName) {
case "辅导员审批":
// 辅导员通过后 → 下一个节点学务筛选出角色ID=105且与当前部门一致
// 查询角色ID=105学务的所有用户
SysUser queryUser = new SysUser();
queryUser.setRoleId(105L); // 学务角色固定ID
List<SysUser> academicAffairsUsers = sysUserService.selectAllocatedList(queryUser);
if (academicAffairsUsers.isEmpty()) {
throw new RuntimeException("未查询到角色ID=105学务的用户");
}
// 3. 从学务用户中筛选出部门ID与当前辅导员部门一致的用户
SysUser targetAcademic = academicAffairsUsers.stream()
.filter(user -> currentDeptId.equals(user.getDeptId())) // 部门ID匹配
.findFirst() // 取第一个匹配的学务(若有多个,可根据排序或优先级调整)
.orElseThrow(() -> new RuntimeException("未找到部门ID=" + currentDeptId + "的学务负责人"));
// 4. 返回匹配的学务用户ID作为下一个节点负责人
return targetAcademic.getUserId();
case "学务审批":
// 学务通过后 → 下一个节点二级学院角色ID=106匹配学生所属学院
// 查询当前流程对应的业务数据获取学生所属学院ID
// RtEnlistmentReserve reserve = enlistmentReserveMapper.selectRtEnlistmentReserveByProcessInstanceId(processInstanceId);
// if (reserve == null) {
// throw new RuntimeException("未查询到流程对应的业务数据processInstanceId=" + processInstanceId);
// }
// 查询角色ID=106二级学院的所有用户
SysUser qUser = new SysUser();
qUser.setRoleId(106L); // 二级学院角色固定ID=106
List<SysUser> collegeUsers = sysUserService.selectAllocatedList(qUser);
if (collegeUsers.isEmpty()) {
throw new RuntimeException("未查询到角色ID=106二级学院的用户");
}
// 筛选出部门ID学院ID与登录用户所属学院一致的二级学院负责人
SysUser targetCollegeLeader = collegeUsers.stream()
.filter(user -> currentDeptId.equals(user.getDeptId())) // 学院ID匹配部门ID即学院ID
.findFirst()
.orElseThrow(() -> new RuntimeException("未找到学院ID=" + currentDeptId + "的二级学院负责人角色ID=106"));
// 4. 返回匹配的二级学院负责人ID
return targetCollegeLeader.getUserId();
case "二级学院审批":
// 二级学院通过后 → 下一个节点学籍管理科假设部门ID=30
return 30L;
case "学籍管理科审批":
// 学籍管理科通过后 → 下一个节点教务处假设部门ID=40
return 40L;
case "教务处主管领导审批":
// 最后一个节点通过后 → 流程结束(无需设置负责人)
return null;
default:
throw new RuntimeException("未配置节点[" + currentNodeName + "]的下一个负责人规则");
}
}
}

View File

@@ -50,6 +50,15 @@ private static final long serialVersionUID=1L;
@Excel(name = "学生ID" , readConverterExp = "关=联sys_user")
private Long studentId;
/**
* 辅导员姓名
*/
@ApiModelProperty("辅导员姓名")
@TableField("teacher_name")
@Excel(name = "辅导员姓名")
private String teacherName;
/**
* 姓名
*/

View File

@@ -22,6 +22,14 @@ public interface RtEnlistmentReserveMapper extends BaseMapper<RtEnlistmentReserv
*/
public RtEnlistmentReserve selectRtEnlistmentReserveById(Long id);
/**
* 查询应征入伍保留学籍申请
*
* @param processInstanceId Flowable流程实例ID
* @return 应征入伍保留学籍申请
*/
public RtEnlistmentReserve selectRtEnlistmentReserveByProcessInstanceId(String processInstanceId);
// <!-- 根据学号查询辅导员信息 -->
public TeacherVo getCounselorInfo(String stuNo);

View File

@@ -99,7 +99,7 @@ public class RtEnlistmentReserveServiceImpl extends ServiceImpl<RtEnlistmentRese
// 启动流程(此时 applyId 已存在,可正常传递)
ProcessResultDto processResultDto = startEnlistmentReserveProcess(rtEnlistmentReserve);
// 3.3 同步更新流程实例 ID + 申请状态为“审批中”2形成业务闭环
// 同步更新流程实例 ID + 申请状态为“审批中”2形成业务闭环
if (processResultDto != null && StringUtils.isNotBlank(processResultDto.getProcessInstanceId())) {
RtEnlistmentReserve updateEntity = new RtEnlistmentReserve();
updateEntity.setId(applyId);
@@ -196,7 +196,7 @@ public class RtEnlistmentReserveServiceImpl extends ServiceImpl<RtEnlistmentRese
variables.put("deptId", counselorInfo.getDeptId());
// 3. 启动流程
AjaxResult ajaxResult = flowDefinitionService.startProcessInstanceById("flow_r064jfpz:4:1032511", variables);
AjaxResult ajaxResult = flowDefinitionService.startProcessInstanceById("flow_r064jfpz:7:1055004", variables);
String code = ajaxResult.get("code").toString();
if (!"200".equals(code)) {
throw new ServiceException("流程启动失败,错误码:" + code, 500);

View File

@@ -3,11 +3,12 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.srs.routine.mapper.RtEnlistmentReserveMapper">
<resultMap type="RtEnlistmentReserve" id="RtEnlistmentReserveResult">
<result property="id" column="id" />
<result property="applyNo" column="apply_no" />
<result property="studentId" column="student_id" />
<result property="teacherName" column="teacher_name" />
<result property="studentName" column="student_name" />
<result property="gender" column="gender" />
<result property="nation" column="nation" />
@@ -29,14 +30,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectRtEnlistmentReserveVo">
select id, apply_no, student_id, student_name, gender, nation, grade, student_no, class_name, major, family_address, parent_phone, apply_reason, apply_status, process_instance_id, reserve_no, reserve_start_date, reserve_end_date, approval_no, create_time, update_time from rt_enlistment_reserve
select id, apply_no, student_id, teacher_name, student_name, gender, nation, grade, student_no, class_name, major, family_address, parent_phone, apply_reason, apply_status, process_instance_id, reserve_no, reserve_start_date, reserve_end_date, approval_no, create_time, update_time from rt_enlistment_reserve
</sql>
<select id="selectRtEnlistmentReserveList" parameterType="RtEnlistmentReserve" resultMap="RtEnlistmentReserveResult">
<include refid="selectRtEnlistmentReserveVo"/>
<where>
<where>
<if test="applyNo != null and applyNo != ''"> and apply_no = #{applyNo}</if>
<if test="studentId != null "> and student_id = #{studentId}</if>
<if test="teacherName != null and teacherName != ''"> and teacher_name like concat('%', #{teacherName}, '%')</if>
<if test="studentName != null and studentName != ''"> and student_name like concat('%', #{studentName}, '%')</if>
<if test="gender != null and gender != ''"> and gender = #{gender}</if>
<if test="nation != null and nation != ''"> and nation = #{nation}</if>
@@ -61,6 +63,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where id = #{id}
</select>
<select id="selectRtEnlistmentReserveByProcessInstanceId" parameterType="String" resultMap="RtEnlistmentReserveResult">
<include refid="selectRtEnlistmentReserveVo"/>
where process_instance_id = #{processInstanceId}
</select>
<!-- 根据学号查询辅导员信息 -->
<select id="getCounselorInfo" resultType="com.srs.common.doman.vo.TeacherVo">
SELECT d.user_id userId, d.dept_id deptId, d.user_name userName, d.nick_name nickName
@@ -70,12 +77,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
LEFT JOIN sys_user d ON c.employee_id = d.user_name
WHERE a.stu_no = #{stuNo}
</select>
<insert id="insertRtEnlistmentReserve" parameterType="RtEnlistmentReserve" useGeneratedKeys="true" keyProperty="id">
insert into rt_enlistment_reserve
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="applyNo != null and applyNo != ''">apply_no,</if>
<if test="studentId != null">student_id,</if>
<if test="teacherName != null and teacherName != ''">teacher_name,</if>
<if test="studentName != null and studentName != ''">student_name,</if>
<if test="gender != null and gender != ''">gender,</if>
<if test="nation != null and nation != ''">nation,</if>
@@ -94,10 +102,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="approvalNo != null">approval_no,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
</trim>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="applyNo != null and applyNo != ''">#{applyNo},</if>
<if test="studentId != null">#{studentId},</if>
<if test="teacherName != null and teacherName != ''">#{teacherName},</if>
<if test="studentName != null and studentName != ''">#{studentName},</if>
<if test="gender != null and gender != ''">#{gender},</if>
<if test="nation != null and nation != ''">#{nation},</if>
@@ -116,7 +125,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="approvalNo != null">#{approvalNo},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</trim>
</insert>
<update id="updateRtEnlistmentReserve" parameterType="RtEnlistmentReserve">
@@ -124,6 +133,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<trim prefix="SET" suffixOverrides=",">
<if test="applyNo != null and applyNo != ''">apply_no = #{applyNo},</if>
<if test="studentId != null">student_id = #{studentId},</if>
<if test="teacherName != null and teacherName != ''">teacher_name = #{teacherName},</if>
<if test="studentName != null and studentName != ''">student_name = #{studentName},</if>
<if test="gender != null and gender != ''">gender = #{gender},</if>
<if test="nation != null and nation != ''">nation = #{nation},</if>
@@ -151,7 +161,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</delete>
<delete id="deleteRtEnlistmentReserveByIds" parameterType="String">
delete from rt_enlistment_reserve where id in
delete from rt_enlistment_reserve where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>