外宿申请-工作流监听器
This commit is contained in:
@@ -3,6 +3,7 @@ package com.srs.routine.service;
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.srs.dormitory.domain.DmsOutsideAccommodationApply;
|
||||
import com.srs.routine.domain.RtEnlistmentReserve;
|
||||
|
||||
/**
|
||||
@@ -67,4 +68,21 @@ public interface IRtEnlistmentReserveService extends IService<RtEnlistmentReserv
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteRtEnlistmentReserveById(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* 新增外宿申请
|
||||
*
|
||||
* @param dmsOutsideAccommodationApply 外宿申请
|
||||
* @return 结果
|
||||
*/
|
||||
DmsOutsideAccommodationApply insertDmsOutsideAccommodationApply(DmsOutsideAccommodationApply dmsOutsideAccommodationApply);
|
||||
|
||||
/**
|
||||
* 修改外宿申请
|
||||
*
|
||||
* @param dmsOutsideAccommodationApply 外宿申请
|
||||
* @return 结果
|
||||
*/
|
||||
int updateDmsOutsideAccommodationApply(DmsOutsideAccommodationApply dmsOutsideAccommodationApply);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import com.srs.common.doman.vo.TeacherVo;
|
||||
import com.srs.common.exception.ServiceException;
|
||||
import com.srs.common.utils.DateUtils;
|
||||
import com.srs.common.utils.SecurityUtils;
|
||||
import com.srs.dormitory.domain.DmsOutsideAccommodationApply;
|
||||
import com.srs.dormitory.mapper.DmsOutsideAccommodationApplyMapper;
|
||||
import com.srs.flowable.service.IFlowDefinitionService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.srs.routine.mapper.RtStuLeaveApplicationMapper;
|
||||
@@ -36,8 +38,8 @@ public class RtEnlistmentReserveServiceImpl extends ServiceImpl<RtEnlistmentRese
|
||||
@Autowired
|
||||
private RtEnlistmentReserveMapper rtEnlistmentReserveMapper;
|
||||
|
||||
// @Autowired
|
||||
// private RtStuLeaveApplicationMapper rtStuLeaveApplicationMapper;
|
||||
@Autowired
|
||||
private DmsOutsideAccommodationApplyMapper dmsOutsideAccommodationApplyMapper; // 外宿申请
|
||||
|
||||
@Autowired
|
||||
IFlowDefinitionService flowDefinitionService;
|
||||
@@ -49,7 +51,7 @@ public class RtEnlistmentReserveServiceImpl extends ServiceImpl<RtEnlistmentRese
|
||||
IdentityService identityService;
|
||||
|
||||
|
||||
// 新增:注入RuntimeService(之前缺失)
|
||||
// 注入RuntimeService
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
|
||||
@@ -177,6 +179,7 @@ public class RtEnlistmentReserveServiceImpl extends ServiceImpl<RtEnlistmentRese
|
||||
.processInstanceId(processInstanceId)
|
||||
.taskAssignee(studentUserId) // 学生作为任务负责人
|
||||
.active() // 仅查询活跃任务
|
||||
.taskName("学生申请")
|
||||
.list();
|
||||
|
||||
if (!studentTaskList.isEmpty()) {
|
||||
@@ -381,4 +384,232 @@ public class RtEnlistmentReserveServiceImpl extends ServiceImpl<RtEnlistmentRese
|
||||
public int deleteRtEnlistmentReserveById(Long id) {
|
||||
return rtEnlistmentReserveMapper.deleteRtEnlistmentReserveById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增外宿申请
|
||||
*
|
||||
* @param dmsOutsideAccommodationApply 外宿申请
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public DmsOutsideAccommodationApply insertDmsOutsideAccommodationApply(DmsOutsideAccommodationApply dmsOutsideAccommodationApply) {
|
||||
// 新增之前先查询申请记录是否存在,如果存在就不能新增重复的数据
|
||||
DmsOutsideAccommodationApply outsideAccommodationApply = dmsOutsideAccommodationApplyMapper.getAccommodationByStuNameAndStuNo(dmsOutsideAccommodationApply.getStudentName(), dmsOutsideAccommodationApply.getStudentNo());
|
||||
if (outsideAccommodationApply != null) {
|
||||
throw new ServiceException("您已经申请过了,请勿重新申请!", 400);
|
||||
}
|
||||
dmsOutsideAccommodationApply.setCreateTime(DateUtils.getNowDate());
|
||||
dmsOutsideAccommodationApply.setCreateBy(SecurityUtils.getUsername());
|
||||
dmsOutsideAccommodationApply.setStartDate(DateUtils.getNowDate());
|
||||
|
||||
// 先插入申请表数据,获取自增 ID(数据库自动为 applyStatus 赋值 0 若未传值)
|
||||
int insertCount = dmsOutsideAccommodationApplyMapper.insertDmsOutsideAccommodationApply(dmsOutsideAccommodationApply);
|
||||
if (insertCount <= 0) {
|
||||
throw new ServiceException("申请表插入失败", 500);
|
||||
}
|
||||
|
||||
Long applyId = dmsOutsideAccommodationApply.getId();
|
||||
if (applyId == null) {
|
||||
throw new ServiceException("申请表 ID 生成失败,无法继续操作", 500);
|
||||
}
|
||||
// 仅当 applyStatus = 1 时,启动流程(1=提交申请,进入审批)
|
||||
// 注意:若前端未传 applyStatus,数据库默认 0,不会触发流程
|
||||
if (1 == dmsOutsideAccommodationApply.getStatus()) {
|
||||
// 绑定当前学生 ID(提交人即学生本人,确保流程变量准确)
|
||||
dmsOutsideAccommodationApply.setStudentId(SecurityUtils.getUserId());
|
||||
|
||||
// 启动流程(此时 applyId 已存在,可正常传递)
|
||||
ProcessResultDto processResultDto = startOutsideAccommodationProcess(dmsOutsideAccommodationApply);
|
||||
|
||||
// 同步更新流程实例 ID + 申请状态为“审批中”(2),形成业务闭环
|
||||
if (processResultDto != null && StringUtils.isNotBlank(processResultDto.getProcessInstanceId())) {
|
||||
DmsOutsideAccommodationApply updateEntity = new DmsOutsideAccommodationApply();
|
||||
updateEntity.setId(applyId);
|
||||
updateEntity.setProcessInstanceId(processResultDto.getProcessInstanceId());
|
||||
updateEntity.setDeployId(processResultDto.getDeploymentId());
|
||||
/*updateEntity.setApplyStatus(1L); // 审批中状态(根据实际枚举调整)*/
|
||||
dmsOutsideAccommodationApplyMapper.updateDmsOutsideAccommodationApply(updateEntity);
|
||||
System.out.println("申请表[" + applyId + "]已启动流程,实例ID:" + processResultDto.getProcessInstanceId() + ",状态更新为审批中");
|
||||
} else {
|
||||
throw new ServiceException("流程启动失败,请重试", 500);
|
||||
}
|
||||
} else {
|
||||
// 若 applyStatus 为 0(数据库默认)或其他值,仅保存表单,不启动流程
|
||||
String statusDesc = dmsOutsideAccommodationApply.getStatus() == 0 ? "草稿" : "待辅导员审批";
|
||||
System.out.println("申请表[" + applyId + "]状态为" + dmsOutsideAccommodationApply.getStatus() + "(" + statusDesc + "),暂不启动流程");
|
||||
}
|
||||
|
||||
return dmsOutsideAccommodationApply;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改外宿申请
|
||||
*
|
||||
* @param dmsOutsideAccommodationApply 外宿申请
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateDmsOutsideAccommodationApply(DmsOutsideAccommodationApply dmsOutsideAccommodationApply) {
|
||||
if (dmsOutsideAccommodationApply.getId() == null) {
|
||||
throw new ServiceException("申请表ID不能为空,无法更新", 500);
|
||||
}
|
||||
dmsOutsideAccommodationApply.setUpdateTime(DateUtils.getNowDate());
|
||||
dmsOutsideAccommodationApply.setUpdateBy(SecurityUtils.getUsername());
|
||||
|
||||
// 查询当前申请表的已有状态(判断流程是否已启动)
|
||||
DmsOutsideAccommodationApply existing = dmsOutsideAccommodationApplyMapper.selectDmsOutsideAccommodationApplyById(dmsOutsideAccommodationApply.getId());
|
||||
if (existing == null) {
|
||||
throw new ServiceException("未查询到申请表数据,无法更新", 500);
|
||||
}
|
||||
// 判断流程是否已启动(存在 processInstanceId 即为已启动)
|
||||
boolean isProcessStarted = StringUtils.isNotBlank(existing.getProcessInstanceId());
|
||||
|
||||
if (isProcessStarted) {
|
||||
// 流程已启动:如果节点回到学生申请,则学生申请自动完成
|
||||
System.out.println("申请表[" + dmsOutsideAccommodationApply.getId() + "]流程已启动(实例ID:" + existing.getProcessInstanceId() + "),仅更新数据");
|
||||
// ========== 核心新增逻辑:仅当任务是「学生申请」节点时,学生自动完成待办任务 ==========
|
||||
String processInstanceId = existing.getProcessInstanceId();
|
||||
Long studentId = SecurityUtils.getUserId(); // 获取当前操作的学生ID
|
||||
String studentUserId = studentId.toString(); // 转换为Flowable的Assignee字符串类型
|
||||
|
||||
// 1. 查询学生当前的待办任务(流程实例ID+学生ID作为负责人)(增加:任务名称/任务定义Key过滤,仅匹配「学生申请」节点)
|
||||
List<Task> studentTaskList = taskService.createTaskQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.taskAssignee(studentUserId) // 学生作为任务负责人
|
||||
.active() // 仅查询活跃任务
|
||||
.taskName("学生申请")
|
||||
.list();
|
||||
|
||||
if (!studentTaskList.isEmpty()) {
|
||||
for (Task studentTask : studentTaskList) {
|
||||
// 补充完成任务的流程变量(如审批意见、结果,根据你的流程需求设置)
|
||||
Map<String, Object> completeVariables = new HashMap<>();
|
||||
completeVariables.put("approvalResult", "AGREE"); // 学生提交(默认同意)
|
||||
completeVariables.put("approvalOpinion", "学生自动提交申请,等待辅导员审批");
|
||||
completeVariables.put("operator", "student"); // 操作人类型
|
||||
// 添加任务分配的备注(便于流程追溯)
|
||||
taskService.addComment(
|
||||
studentTask.getId(),
|
||||
processInstanceId,
|
||||
"自动分配负责人",
|
||||
"学生已经重新修改提交申请"
|
||||
);
|
||||
// 2. 学生自动完成待办任务
|
||||
taskService.complete(studentTask.getId(), completeVariables);
|
||||
System.out.println("学生[" + studentUserId + "]已自动完成待办任务,任务ID:" + studentTask.getId());
|
||||
}
|
||||
|
||||
// 3. 分配下一节点(辅导员)的待办任务负责人【不再复用监听器,独立实现】
|
||||
assignCounselorTask(processInstanceId, existing.getId(), existing.getStudentNo());
|
||||
} else {
|
||||
System.out.println("流程实例[" + processInstanceId + "]中未查询到学生[" + studentUserId + "]的待办任务,无需自动完成");
|
||||
}
|
||||
|
||||
// 同步更新流程变量(将业务表状态同步到流程中)
|
||||
runtimeService.setVariable(processInstanceId, "applyStatus", dmsOutsideAccommodationApply.getStatus());
|
||||
// 注意:若需更新流程相关变量,需调用 Flowable 的 runtimeService.setVariables(),此处仅更新业务表
|
||||
return dmsOutsideAccommodationApplyMapper.updateDmsOutsideAccommodationApply(dmsOutsideAccommodationApply);
|
||||
} else {
|
||||
// 流程未启动:仅当 applyStatus=1 时启动流程,否则仅更新数据
|
||||
Long applyStatus = dmsOutsideAccommodationApply.getStatus();
|
||||
if (1L == applyStatus) {
|
||||
// 绑定当前学生ID,启动流程
|
||||
dmsOutsideAccommodationApply.setStudentId(SecurityUtils.getUserId());
|
||||
ProcessResultDto processResultDto = startOutsideAccommodationProcess(dmsOutsideAccommodationApply);
|
||||
if (processResultDto == null || StringUtils.isBlank(processResultDto.getProcessInstanceId())) {
|
||||
throw new ServiceException("流程启动失败,请重试", 500);
|
||||
}
|
||||
|
||||
// 关联流程实例ID,更新为“审批中”状态
|
||||
dmsOutsideAccommodationApply.setProcessInstanceId(processResultDto.getProcessInstanceId());
|
||||
dmsOutsideAccommodationApply.setDeployId(processResultDto.getDeploymentId());
|
||||
dmsOutsideAccommodationApply.setStatus(1L); // 审批中
|
||||
System.out.println("申请表[" + dmsOutsideAccommodationApply.getId() + "]启动流程成功,实例ID:" + processResultDto.getProcessInstanceId());
|
||||
} else {
|
||||
// 非提交状态:仅更新基础数据(如草稿修改)
|
||||
String statusDesc = applyStatus == null ? "未指定状态" : (applyStatus == 0 ? "草稿" : "其他状态");
|
||||
System.out.println("申请表[" + dmsOutsideAccommodationApply.getId() + "]状态为" + statusDesc + ",流程未启动,仅更新数据");
|
||||
}
|
||||
|
||||
// 执行数据库更新(含流程实例ID绑定或基础数据更新)
|
||||
return dmsOutsideAccommodationApplyMapper.updateDmsOutsideAccommodationApply(dmsOutsideAccommodationApply);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开启外宿申请工作流
|
||||
*
|
||||
* @param dmsOutsideAccommodationApply
|
||||
*/
|
||||
private ProcessResultDto startOutsideAccommodationProcess(DmsOutsideAccommodationApply
|
||||
dmsOutsideAccommodationApply) {
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
// 1. 传递关键变量(申请编号+主键ID,用于任务匹配)
|
||||
String applyNo = dmsOutsideAccommodationApply.getApplyNo(); // 申请编号(如RY2024001)
|
||||
Long enlistmentId = dmsOutsideAccommodationApply.getId(); // 申请表主键ID
|
||||
variables.put("applyNo", applyNo);
|
||||
variables.put("accommodationId", enlistmentId); // 新增:用于任务匹配的主键变量
|
||||
variables.put("stuId", dmsOutsideAccommodationApply.getStudentId());
|
||||
|
||||
// 2. 查询辅导员信息
|
||||
TeacherVo counselorInfo = dmsOutsideAccommodationApplyMapper.getCounselorInfo(dmsOutsideAccommodationApply.getStudentNo());
|
||||
if (counselorInfo == null) {
|
||||
throw new ServiceException("该学生暂无辅导员", 500);
|
||||
}
|
||||
variables.put("approval", counselorInfo.getUserId()); // 下一节点:辅导员
|
||||
variables.put("deptId", counselorInfo.getDeptId());
|
||||
|
||||
// 3. 启动流程
|
||||
AjaxResult ajaxResult = flowDefinitionService.startProcessInstanceById("flow_dre1txpk:11:1375008", variables);
|
||||
String code = ajaxResult.get("code").toString();
|
||||
if (!"200".equals(code)) {
|
||||
throw new ServiceException("流程启动失败,错误码:" + code, 500);
|
||||
}
|
||||
|
||||
ProcessResultDto dto = (ProcessResultDto) ajaxResult.get("data");
|
||||
System.out.println("流程启动成功,实例ID:" + dto.getProcessInstanceId());
|
||||
|
||||
// 4. 学生自动完成自己的待办任务
|
||||
identityService.setAuthenticatedUserId(SecurityUtils.getUserId().toString());
|
||||
// 精准查询当前流程中属于学生的待办任务
|
||||
List<Task> tasks = taskService.createTaskQuery()
|
||||
.processInstanceId(dto.getProcessInstanceId())
|
||||
.taskAssignee(SecurityUtils.getUserId().toString())
|
||||
.active()
|
||||
.list();
|
||||
|
||||
if (tasks.isEmpty()) {
|
||||
throw new ServiceException("未查询到学生的待办任务,请检查流程设计", 500);
|
||||
}
|
||||
|
||||
// 5. 完成任务(匹配主键ID,避免错误)
|
||||
variables.put("approved", true); // 学生提交确认
|
||||
for (Task task : tasks) {
|
||||
// 安全获取变量:先判断是否为null,再转换类型
|
||||
Object varValue = taskService.getVariable(task.getId(), "accommodationId");
|
||||
if (varValue == null) {
|
||||
continue;
|
||||
}
|
||||
// 转换为Long类型(与主键ID匹配)
|
||||
Long taskEnlistmentId;
|
||||
try {
|
||||
taskEnlistmentId = Long.parseLong(varValue.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
continue; // 类型不匹配,跳过
|
||||
}
|
||||
// 匹配当前申请表的主键ID
|
||||
if (taskEnlistmentId.equals(enlistmentId)) {
|
||||
taskService.complete(task.getId(), variables);
|
||||
System.out.println("学生已完成待办任务,任务ID:" + task.getId());
|
||||
break; // 完成后退出循环,避免重复处理
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 推送消息给辅导员(待办提醒)
|
||||
// todo: 企业微信推送逻辑
|
||||
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user