外宿申请-工作流监听器

This commit is contained in:
2025-12-08 17:28:03 +08:00
parent 13afaa08b4
commit c6abc87555
16 changed files with 1806 additions and 4 deletions

View File

@@ -2,8 +2,11 @@ package com.srs.dormitory.mapper;
import java.util.List;
import com.srs.common.doman.vo.TeacherVo;
import com.srs.dormitory.domain.DmsOutsideAccommodationApply;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
/**
* 外宿申请Mapper接口
@@ -20,6 +23,14 @@ public interface DmsOutsideAccommodationApplyMapper extends BaseMapper<DmsOutsid
*/
public DmsOutsideAccommodationApply selectDmsOutsideAccommodationApplyById(Long id);
/**
* 查询外宿申请
*
* @param processInstanceId 外宿申请流程id
* @return 外宿申请
*/
public DmsOutsideAccommodationApply selectDmsOutsideAccommodationApplyByProcessInstanceId(String processInstanceId);
/**
* 查询外宿申请列表
*
@@ -28,12 +39,24 @@ public interface DmsOutsideAccommodationApplyMapper extends BaseMapper<DmsOutsid
*/
List<DmsOutsideAccommodationApply> selectDmsOutsideAccommodationApplyList(DmsOutsideAccommodationApply dmsOutsideAccommodationApply);
// <!-- 根据学号查询辅导员信息 -->
public TeacherVo getCounselorInfo(String stuNo);
/**
* 查询外宿申请
*
* @param studentName 学生姓名
* @return 应征入伍保留学籍申请
*/
public DmsOutsideAccommodationApply getAccommodationByStuNameAndStuNo(@Param("studentName") String studentName, @Param("studentNo") String studentNo);
/**
* 新增外宿申请
*
* @param dmsOutsideAccommodationApply 外宿申请
* @return 结果
*/
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
int insertDmsOutsideAccommodationApply(DmsOutsideAccommodationApply dmsOutsideAccommodationApply);
/**

View File

@@ -20,6 +20,14 @@ public interface IDmsOutsideAccommodationApplyService extends IService<DmsOutsid
*/
public DmsOutsideAccommodationApply selectDmsOutsideAccommodationApplyById(Long id);
/**
* 查询外宿申请
*
* @param processInstanceId 外宿申请流程id
* @return 外宿申请
*/
public DmsOutsideAccommodationApply selectDmsOutsideAccommodationApplyByProcessInstanceId(String processInstanceId);
/**
* 查询外宿申请列表
*

View File

@@ -33,6 +33,11 @@ public class DmsOutsideAccommodationApplyServiceImpl extends ServiceImpl<DmsOuts
return dmsOutsideAccommodationApplyMapper.selectDmsOutsideAccommodationApplyById(id);
}
@Override
public DmsOutsideAccommodationApply selectDmsOutsideAccommodationApplyByProcessInstanceId(String processInstanceId) {
return dmsOutsideAccommodationApplyMapper.selectDmsOutsideAccommodationApplyByProcessInstanceId(processInstanceId);
}
/**
* 查询外宿申请列表
*

View File

@@ -171,6 +171,38 @@
where id = #{id}
</select>
<!--根据流程ID查询信息-->
<select id="selectDmsOutsideAccommodationApplyByProcessInstanceId" parameterType="String"
resultMap="DmsOutsideAccommodationApplyResult">
<include refid="selectDmsOutsideAccommodationApplyVo"/>
where processInstanceId = #{process_instance_id}
</select>
<!--根据学生姓名和学号查询申请表-->
<select id="getAccommodationByStuNameAndStuNo" resultMap="DmsOutsideAccommodationApplyResult">
select *
from dms_outside_accommodation_apply
<where>
<if test="studentName != null and studentName != ''">
and student_name = #{studentName}
</if>
<if test="studentNo != null and studentNo != ''">
and student_no = #{studentNo}
</if>
</where>
</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
FROM srs_student a
LEFT JOIN srs_class b ON a.class_id = b.class_id
LEFT JOIN cph_teacher c ON b.teacher_id = c.teacher_id
LEFT JOIN sys_user d ON c.employee_id = d.user_name
WHERE a.stu_no = #{stuNo}
</select>
<insert id="insertDmsOutsideAccommodationApply" parameterType="DmsOutsideAccommodationApply" useGeneratedKeys="true"
keyProperty="id">
insert into dms_outside_accommodation_apply

View File

@@ -72,6 +72,16 @@ public class DmsOutsideAccommodationApplyController extends BaseController {
return success(dmsOutsideAccommodationApplyService.selectDmsOutsideAccommodationApplyById(id));
}
/**
* 获取外宿申请详细信息
*/
@PreAuthorize("@ss.hasPermi('dormitory:enlistmentReserve:query')")
@GetMapping(value = "/process/{processInstanceId}")
@ApiOperation("获取应征入伍保留学籍申请详细信息")
public AjaxResult getInfoByProcessInstanceId(@PathVariable("processInstanceId") String processInstanceId) {
return success(dmsOutsideAccommodationApplyService.selectDmsOutsideAccommodationApplyByProcessInstanceId(processInstanceId));
}
/**
* 新增外宿申请
*/
@@ -81,7 +91,7 @@ public class DmsOutsideAccommodationApplyController extends BaseController {
@ApiOperation("新增外宿申请")
public AjaxResult add(@RequestBody DmsOutsideAccommodationApply dmsOutsideAccommodationApply)
{
return toAjax(dmsOutsideAccommodationApplyService.insertDmsOutsideAccommodationApply(dmsOutsideAccommodationApply));
return success(dmsOutsideAccommodationApplyService.insertDmsOutsideAccommodationApply(dmsOutsideAccommodationApply));
}
/**

View File

@@ -3,6 +3,7 @@ package com.srs.web.controller.routine;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.srs.dormitory.domain.DmsOutsideAccommodationApply;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@@ -112,4 +113,29 @@ public class RtEnlistmentReserveController extends BaseController {
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(rtEnlistmentReserveService.deleteRtEnlistmentReserveByIds(ids));
}
/**
* 新增外宿申请
*/
@PreAuthorize("@ss.hasPermi('dormitory:outsideAccommodationApply:add')")
@Log(title = "外宿申请", businessType = BusinessType.INSERT)
@PostMapping("/outsideAccommodationApply/add")
@ApiOperation("新增外宿申请")
public AjaxResult add(@RequestBody DmsOutsideAccommodationApply dmsOutsideAccommodationApply)
{
return success(rtEnlistmentReserveService.insertDmsOutsideAccommodationApply(dmsOutsideAccommodationApply));
}
/**
* 修改外宿申请
*/
@PreAuthorize("@ss.hasPermi('dormitory:outsideAccommodationApply:edit')")
@Log(title = "外宿申请", businessType = BusinessType.UPDATE)
@PostMapping("/outsideAccommodationApply/update")
@ApiOperation("修改外宿申请")
public AjaxResult edit(@RequestBody DmsOutsideAccommodationApply dmsOutsideAccommodationApply)
{
return toAjax(rtEnlistmentReserveService.updateDmsOutsideAccommodationApply(dmsOutsideAccommodationApply));
}
}

View File

@@ -0,0 +1,356 @@
package com.srs.flowable.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.srs.common.annotation.Excel;
import com.srs.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import java.util.Date;
/**
* 外宿申请对象 dms_outside_accommodation_apply
*
* @author srs
* @date 2025-12-06
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(value = "DmsOutsideAccommodationApply对象", description = "外宿申请表")
@TableName("dms_outside_accommodation_apply")
public class OutsideAccommodationApply extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ApiModelProperty("主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 申请编号唯一如WS20240001
*/
@ApiModelProperty("申请编号唯一如WS20240001")
@TableField("apply_no")
@Excel(name = "申请编号", readConverterExp = "唯=一如WS20240001")
private String applyNo;
/**
* 学生ID关联学生表
*/
@ApiModelProperty("学生ID关联学生表")
@TableField("student_id")
@Excel(name = "学生ID", readConverterExp = "关=联学生表")
private Long studentId;
/**
* 学号
*/
@ApiModelProperty("学号")
@TableField("student_no")
@Excel(name = "学号")
private String studentNo;
/**
* 学生姓名
*/
@ApiModelProperty("学生姓名")
@TableField("student_name")
@Excel(name = "学生姓名")
private String studentName;
/**
* 性别(男/女)
*/
@ApiModelProperty("性别(男/女)")
@TableField("gender")
@Excel(name = "性别", readConverterExp = "男=/女")
private String gender;
/**
* 出生年月
*/
@ApiModelProperty("出生年月")
@TableField("birth_date")
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "出生年月", width = 30, dateFormat = "yyyy-MM-dd")
private Date birthDate;
/**
* 学院ID
*/
@ApiModelProperty("学院ID")
@TableField("dept_id")
@Excel(name = "学院ID")
private Long deptId;
/**
* 学院名称
*/
@ApiModelProperty("学院名称")
@TableField("dept_name")
@Excel(name = "学院名称")
private String deptName;
/**
* 专业ID
*/
@ApiModelProperty("专业ID")
@TableField("major_id")
@Excel(name = "专业ID")
private Long majorId;
/**
* 专业名称
*/
@ApiModelProperty("专业名称")
@TableField("major_name")
@Excel(name = "专业名称")
private String majorName;
/**
* 班级ID
*/
@ApiModelProperty("班级ID")
@TableField("class_id")
@Excel(name = "班级ID")
private Long classId;
/**
* 班级名称
*/
@ApiModelProperty("班级名称")
@TableField("class_name")
@Excel(name = "班级名称")
private String className;
/**
* 原宿舍号1栋302
*/
@ApiModelProperty("原宿舍号1栋302")
@TableField("original_dormitory")
@Excel(name = "原宿舍号", readConverterExp = "如=1栋302")
private String originalDormitory;
/**
* 住宿费缴纳
*/
@ApiModelProperty("住宿费缴纳")
@TableField("accommodation_fee")
@Excel(name = "住宿费缴纳")
private String accommodationFee;
/**
* 住宿费缴纳状态1=已交0=未交)
*/
@ApiModelProperty("住宿费缴纳状态1=已交0=未交)")
@TableField("accommodation_fee_status")
@Excel(name = "住宿费缴纳状态", readConverterExp = "1==已交0=未交")
private Long accommodationFeeStatus;
/**
* 外宿原因
*/
@ApiModelProperty("外宿原因")
@TableField("apply_reason")
@Excel(name = "外宿原因")
private String applyReason;
/**
* 外宿详细地址(精确至门牌号)
*/
@ApiModelProperty("外宿详细地址(精确至门牌号)")
@TableField("outside_address")
@Excel(name = "外宿详细地址", readConverterExp = "精=确至门牌号")
private String outsideAddress;
/**
* 外宿地址-省市区/县
*/
@ApiModelProperty("外宿地址-省市区/县")
@TableField("address")
@Excel(name = "外宿地址-省市区/县")
private String address;
/**
* 紧急联系人电话
*/
@ApiModelProperty("紧急联系人电话")
@TableField("emergency_phone")
@Excel(name = "紧急联系人电话")
private String emergencyPhone;
/**
* 外宿紧急联系人
*/
@ApiModelProperty("外宿紧急联系人")
@TableField("emergency_contact")
@Excel(name = "外宿紧急联系人")
private String emergencyContact;
/**
* 家长意见1=同意0=不同意)
*/
@ApiModelProperty("家长意见1=同意0=不同意)")
@TableField("parent_opinion")
@Excel(name = "家长意见", readConverterExp = "1==同意0=不同意")
private Long parentOpinion;
/**
* 家长签字附件URL
*/
@ApiModelProperty("家长签字附件URL")
@TableField("parent_sign_attachment")
@Excel(name = "家长签字附件URL")
private String parentSignAttachment;
/**
* 家长联系电话
*/
@ApiModelProperty("家长联系电话")
@TableField("parent_phone")
@Excel(name = "家长联系电话")
private String parentPhone;
/**
* 家长通讯地址-省市区/县
*/
@ApiModelProperty("家长通讯地址-省市区/县")
@TableField("parent_address")
@Excel(name = "家长通讯地址-省市区/县")
private String parentAddress;
/**
* 家长通讯地址-详细地址
*/
@ApiModelProperty("家长通讯地址-详细地址")
@TableField("parent_detail_address")
@Excel(name = "家长通讯地址-详细地址")
private String parentDetailAddress;
/**
* 学生承诺电子签URL
*/
@ApiModelProperty("学生承诺电子签URL")
@TableField("student_promise_sign")
@Excel(name = "学生承诺电子签URL")
private String studentPromiseSign;
/**
* 承诺签署日期
*/
@ApiModelProperty("承诺签署日期")
@TableField("promise_date")
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "承诺签署日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date promiseDate;
/**
* 外宿开始时间
*/
@ApiModelProperty("外宿开始时间")
@TableField("start_date")
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "外宿开始时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date startDate;
/**
* 外宿结束时间默认次年8月31日
*/
@ApiModelProperty("外宿结束时间默认次年8月31日")
@TableField("end_date")
@Excel(name = "外宿结束时间", readConverterExp = "默=认次年8月31日")
private Date endDate;
/**
* 申请状态0=草稿1=待辅导员审批2=待学院书记审批3=待学工处审批4=待学校领导审批5=审批通过6=审批驳回)
*/
@ApiModelProperty("申请状态0=草稿1=待辅导员审批2=待学院书记审批3=待学工处审批4=待学校领导审批5=审批通过6=审批驳回)")
@TableField("status")
@Excel(name = "申请状态", readConverterExp = "0==草稿1=待辅导员审批2=待学院书记审批3=待学工处审批4=待学校领导审批5=审批通过6=审批驳回")
private Long status;
/**
* 驳回原因
*/
@ApiModelProperty("驳回原因")
@TableField("reject_reason")
@Excel(name = "驳回原因")
private String rejectReason;
/**
* 是否有效1=有效0=失效/到期)
*/
@ApiModelProperty("是否有效1=有效0=失效/到期)")
@TableField("is_valid")
@Excel(name = "是否有效", readConverterExp = "1==有效0=失效/到期")
private Long isValid;
/**
* 辅导员姓名
*/
@ApiModelProperty("辅导员姓名")
@TableField("teacher_name")
@Excel(name = "辅导员姓名")
private String teacherName;
/**
* 附件id
*/
@ApiModelProperty("附件id")
@TableField("affix_id")
@Excel(name = "附件id")
private String affixId;
/**
* 流程部署编号
*/
@ApiModelProperty("流程部署编号")
@TableField("deploy_id")
@Excel(name = "流程部署编号")
private String deployId;
/**
* Flowable流程实例ID
*/
@ApiModelProperty("Flowable流程实例ID")
@TableField("process_instance_id")
@Excel(name = "Flowable流程实例ID")
private String processInstanceId;
/**
* 身份证号码
*/
@ApiModelProperty("身份证号码")
@TableField("idCard")
@Excel(name = "身份证号码")
private String idCard;
/**
* 学生手机号码
*/
@ApiModelProperty("学生手机号码")
@TableField("studentPhone")
@Excel(name = "学生手机号码")
private String studentPhone;
/**
* 外宿原因学生签名URL
*/
@ApiModelProperty("外宿原因学生签名URL")
@TableField("student_signature")
@Excel(name = "外宿原因学生签名URL")
private String studentSignature;
}

View File

@@ -0,0 +1,139 @@
package com.srs.flowable.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.srs.common.annotation.Excel;
import com.srs.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import java.util.Date;
/**
* 外宿申请审批记录对象 dms_outside_accommodation_approval
*
* @author srs
* @date 2025-12-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(value = "DmsOutsideAccommodationApproval对象" , description = "外宿申请审批记录表")
@TableName("dms_outside_accommodation_approval")
public class OutsideAccommodationApproval extends BaseEntity{
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@ApiModelProperty("主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 外宿申请ID关联申请表
*/
@ApiModelProperty("外宿申请ID关联申请表")
@TableField("apply_id")
@Excel(name = "外宿申请ID" , readConverterExp = "关=联申请表")
private Long applyId;
/**
* 申请编号
*/
@ApiModelProperty("申请编号")
@TableField("apply_no")
@Excel(name = "申请编号")
private String applyNo;
/**
* 审批节点
*/
@ApiModelProperty("审批节点")
@TableField("approval_node")
@Excel(name = "审批节点")
private String approvalNode;
/**
* 审批人ID
*/
@ApiModelProperty("审批人ID")
@TableField("approver_id")
@Excel(name = "审批人ID")
private Long approverId;
/**
* 审批人姓名
*/
@ApiModelProperty("审批人姓名")
@TableField("approver_name")
@Excel(name = "审批人姓名")
private String approverName;
/**
* 审批人角色
*/
@ApiModelProperty("审批人角色")
@TableField("approver_role")
@Excel(name = "审批人角色")
private String approverRole;
/**
* 审批意见
*/
@ApiModelProperty("审批意见")
@TableField("approval_opinion")
@Excel(name = "审批意见")
private String approvalOpinion;
/**
* 审批结果1=同意0=驳回)
*/
@ApiModelProperty("审批结果1=同意0=驳回)")
@TableField("approval_result")
@Excel(name = "审批结果" , readConverterExp = "1==同意0=驳回")
private Long approvalResult;
/**
* 审批时间
*/
@ApiModelProperty("审批时间")
@TableField("approval_time")
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "审批时间" , width = 30, dateFormat = "yyyy-MM-dd")
private Date approvalTime;
/**
* 流程实例ID
*/
@ApiModelProperty("流程实例ID")
@TableField("process_instance_id")
@Excel(name = "流程实例ID")
private String processInstanceId;
/**
* 学生姓名
*/
@ApiModelProperty("学生姓名")
@TableField("student_name")
@Excel(name = "学生姓名")
private String studentName;
/**
* 学生学号
*/
@ApiModelProperty("学生学号")
@TableField("student_no")
@Excel(name = "学生学号")
private String studentNo;
}

View File

@@ -0,0 +1,128 @@
package com.srs.flowable.listener.outsideAccommodation;
import com.srs.common.utils.SecurityUtils;
import com.srs.common.utils.spring.SpringUtils;
import com.srs.dormitory.domain.DmsOutsideAccommodationApply;
import com.srs.flowable.domain.EnlistmentReserve;
import com.srs.flowable.domain.EnlistmentReserveApproval;
import com.srs.flowable.domain.OutsideAccommodationApply;
import com.srs.flowable.domain.OutsideAccommodationApproval;
import com.srs.flowable.mapper.EnlistmentReserveApprovalMapper;
import com.srs.flowable.mapper.EnlistmentReserveMapper;
import com.srs.flowable.mapper.OutsideAccommodationApplyMapper;
import com.srs.flowable.mapper.OutsideAccommodationApprovalMapper;
import com.srs.system.service.ISysUserService;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
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.Date;
/**
* 审批流程负责人自动流转监听器
* 用于节点审批通过时,添加审批记录
*/
@Component("OutsideAccommodationEndListener") // Spring Bean名称与BPMN表达式对应
public class OutsideAccommodationEndListener implements ExecutionListener {
// 用于查询流程定义中的节点信息
@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 + "的名称");
}
// 获取申请表id
Long accommodationId = Long.valueOf(execution.getVariable("accommodationId").toString());
// 获取审核意见
String approvalOpinion = (String) execution.getVariable("approvalOpinion");
// 获取审核状态兼容Integer/Long类型
Object approvalResultObj = execution.getVariable("approvalResult");
Long approvalResult = null;
if (approvalResultObj != null) {
// 先转为数字再获取long值
Number num = (Number) approvalResultObj;
approvalResult = num.longValue();
}
// 添加审批记录
OutsideAccommodationApplyMapper outsideAccommodationApplyMapper = SpringUtils.getBean(OutsideAccommodationApplyMapper.class);
// 根据Id查询外宿申请记录
OutsideAccommodationApply outsideAccommodationApply = outsideAccommodationApplyMapper.selectDmsOutsideAccommodationApplyById(accommodationId);
saveApprovalRecord(outsideAccommodationApply.getId(), outsideAccommodationApply.getProcessInstanceId(),outsideAccommodationApply.getApplyNo(),currentNodeName, outsideAccommodationApply.getStudentName(), outsideAccommodationApply.getStudentNo(), approvalOpinion, approvalResult);
// 如果到了最后一个审批人,则修改申请表审核状态
if (currentNodeName.equals("学校领导审批")){
// 改变申请表中的审核状态(审核通过)
outsideAccommodationApply.setStatus(5L);
outsideAccommodationApplyMapper.updateDmsOutsideAccommodationApply(outsideAccommodationApply);
}
}
/**
* 根据节点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 void saveApprovalRecord(Long ApplyId,String processInstanceId, String applyNo, String nodeName, String studentName, String studentNo, String approvalOpinion, Long approvalResult) {
OutsideAccommodationApproval outsideAccommodationApproval = new OutsideAccommodationApproval();
// 赋值
outsideAccommodationApproval.setApplyId(ApplyId);
outsideAccommodationApproval.setProcessInstanceId(processInstanceId);
outsideAccommodationApproval.setApplyNo(applyNo);
outsideAccommodationApproval.setApprovalNode(nodeName);
outsideAccommodationApproval.setApproverId(SecurityUtils.getLoginUser().getUser().getUserId());
// SecurityUtils.getUserName()是工号
outsideAccommodationApproval.setApproverName(SecurityUtils.getLoginUser().getUser().getNickName());
System.out.println(SecurityUtils.getLoginUser().getUser());
// 若变量未传递,直接用默认值“同意”(前端点击同意按钮的默认意见)
outsideAccommodationApproval.setApprovalOpinion(approvalOpinion);
// 审核状态
outsideAccommodationApproval.setApprovalResult(approvalResult == null ? 0L : approvalResult);
// 审批时间:当前系统时间
outsideAccommodationApproval.setApprovalTime(new Date());
outsideAccommodationApproval.setStudentName(studentName);
outsideAccommodationApproval.setStudentNo(studentNo);
OutsideAccommodationApprovalMapper outsideAccommodationApprovalMapper = (OutsideAccommodationApprovalMapper) SpringUtils.getBean(OutsideAccommodationApprovalMapper.class);
// 查询审批记录是否存在
OutsideAccommodationApproval approval = outsideAccommodationApprovalMapper.selectOutsideAccommodationApprovalByStuName(studentName, studentNo, SecurityUtils.getLoginUser().getUser().getUserId());
if (approval == null) {
outsideAccommodationApprovalMapper.insertDmsOutsideAccommodationApproval(approval);
} else {
approval.setId(approval.getId());
outsideAccommodationApprovalMapper.insertDmsOutsideAccommodationApproval(approval);
}
}
}

View File

@@ -0,0 +1,169 @@
package com.srs.flowable.listener.outsideAccommodation;
import com.srs.common.core.domain.entity.SysUser;
import com.srs.common.doman.vo.TeacherVo;
import com.srs.common.utils.spring.SpringUtils;
import com.srs.dormitory.domain.DmsOutsideAccommodationApply;
import com.srs.flowable.domain.EnlistmentReserve;
import com.srs.flowable.domain.OutsideAccommodationApply;
import com.srs.flowable.mapper.EnlistmentReserveMapper;
import com.srs.flowable.mapper.OutsideAccommodationApplyMapper;
import com.srs.system.service.ISysUserService;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
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("OutsideAccommodationStartListener") // Spring Bean名称与BPMN表达式对应
public class OutsideAccommodationStartListener implements ExecutionListener {
@Autowired
private ISysUserService sysUserService; // 用户服务(查询部门/学院负责人)
// 用于查询流程定义中的节点信息
@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 + "的名称");
}
// 获取申请表id
Long accommodationId = Long.valueOf(execution.getVariable("accommodationId").toString());
// 后续逻辑不变:查询下一个节点负责人并更新变量
Long nextAssigneeId = getNextAssignee(currentNodeName, accommodationId);
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, Long accommodationId) {
OutsideAccommodationApplyMapper outsideAccommodationApplyMapper = SpringUtils.getBean(OutsideAccommodationApplyMapper.class);
// 根据Id查询外宿申请记录
OutsideAccommodationApply outsideAccommodationApply = outsideAccommodationApplyMapper.selectDmsOutsideAccommodationApplyById(accommodationId);
// 根据学生学号来获取对应辅导员的信息
TeacherVo counselorInfo = outsideAccommodationApplyMapper.getCounselorInfo(outsideAccommodationApply.getStudentNo());
// 获取辅导员的部门id
Long currentDeptId = counselorInfo.getDeptId();
if (currentDeptId == null) {
throw new RuntimeException("未分配部门,无法匹配负责人");
}
// 注意节点名称需与BPMN模型中完全一致区分大小写
switch (currentNodeName) {
case "辅导员审批":
// 辅导员开始审批前 → 找到对应辅导员
// 返回匹配的辅导员用户ID作为当前节点负责人
return counselorInfo.getUserId();
case "二级学院书记审批":
// 二级学院书记开始审批前 → 找到对应二级学院书记
// 查询角色ID=106二级学院书记的所有用户
SysUser queryUser = new SysUser();
queryUser.setRoleId(106L); // 学务角色固定ID
List<SysUser> academicAffairsUsers = sysUserService.selectAllocatedList(queryUser);
if (academicAffairsUsers.isEmpty()) {
throw new RuntimeException("未查询到角色(二级学院书记)的用户");
}
// 从学务用户中筛选出部门ID与当前二级学院书记部门一致的用户
SysUser targetAcademic = academicAffairsUsers.stream()
.filter(user -> currentDeptId.equals(user.getDeptId())) // 部门ID匹配
.findFirst() // 取第一个匹配的二级学院书记(若有多个,可根据排序或优先级调整)
.orElseThrow(() -> new RuntimeException("未找到部门ID=" + currentDeptId + "的二级学院书记负责人"));
// 返回匹配的二级学院书记用户ID作为当前节点负责人
return targetAcademic.getUserId();
case "学工处审批":
// 学工处审批前 → 找到对应学工处
// 查询角色ID=100学工处的所有用户
SysUser qUser = new SysUser();
qUser.setRoleId(100L); // 学工处角色固定ID=112
List<SysUser> collegeUsers = sysUserService.selectAllocatedList(qUser);
if (collegeUsers.isEmpty()) {
throw new RuntimeException("未查询到角色(学工处)的用户");
}
// 筛选出部门ID学院ID与登录用户所属学院一致的学工处负责人
SysUser targetCollegeLeader = collegeUsers.stream()
.filter(user -> currentDeptId.equals(user.getDeptId())) // 学院ID匹配部门ID即学院ID
.findFirst()
.orElseThrow(() -> new RuntimeException("未找到学院ID=" + currentDeptId + "的学工处负责人"));
// 返回匹配的学工处负责人ID
return targetCollegeLeader.getUserId();
case "学校领导审批":
// 学校领导审批前 → 找到对应学校领导
// 查询角色ID=107学校领导的所有用户
SysUser sysUser = new SysUser();
sysUser.setRoleId(107L); // 学校领导角色固定ID=107
List<SysUser> sysUsers = sysUserService.selectAllocatedList(sysUser);
if (sysUsers.isEmpty()) {
throw new RuntimeException("未查询到角色(学校领导)的用户");
}
// 筛选出部门ID学院ID与登录用户所属学院一致的学校领导负责人
// 改造findFirst() 找不到则取列表第一个,而非直接抛异常
SysUser userByDeptId = sysUsers.stream()
.filter(user -> currentDeptId.equals(user.getDeptId())) // 学院ID匹配部门ID即学院ID
.findFirst()
// 找不到匹配的则取列表第一个用户
.orElse(sysUsers.get(0));
// 兜底校验防止极端情况理论上sysUsers非空sysUsers.get(0)不会为null
if (userByDeptId == null) {
throw new RuntimeException("学校领导用户数据异常,无可用负责人");
}
// 返回匹配的学校领导负责人ID优先匹配学院无匹配则取第一个
return userByDeptId.getUserId();
default:
throw new RuntimeException("未配置节点[" + currentNodeName + "]的当前负责人规则");
}
}
}

View File

@@ -0,0 +1,85 @@
package com.srs.flowable.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.srs.common.doman.vo.TeacherVo;
import com.srs.flowable.domain.OutsideAccommodationApply;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 外宿申请Mapper接口
*
* @author srs
* @date 2025-12-05
*/
public interface OutsideAccommodationApplyMapper extends BaseMapper<OutsideAccommodationApply> {
/**
* 查询外宿申请
*
* @param id 外宿申请主键
* @return 外宿申请
*/
public OutsideAccommodationApply selectDmsOutsideAccommodationApplyById(Long id);
/**
* 查询外宿申请列表
*
* @param outsideAccommodationApply 外宿申请
* @return 外宿申请集合
*/
List<OutsideAccommodationApply> selectDmsOutsideAccommodationApplyList(OutsideAccommodationApply outsideAccommodationApply);
// <!-- 根据学号查询辅导员信息 -->
public TeacherVo getCounselorInfo(String stuNo);
/**
* 获取审批用户信息
* @param roleName
* @return
* 邵政文
*/
List<TeacherVo> getShenDataInfo(String roleName);
/**
* 查询外宿申请
*
* @param studentName 学生姓名
* @return 应征入伍保留学籍申请
*/
public OutsideAccommodationApply getAccommodationByStuNameAndStuNo(@Param("studentName") String studentName, @Param("studentNo") String studentNo);
/**
* 新增外宿申请
*
* @param outsideAccommodationApply 外宿申请
* @return 结果
*/
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
int insertDmsOutsideAccommodationApply(OutsideAccommodationApply outsideAccommodationApply);
/**
* 修改外宿申请
*
* @param dmsOutsideAccommodationApply 外宿申请
* @return 结果
*/
int updateDmsOutsideAccommodationApply(OutsideAccommodationApply outsideAccommodationApply);
/**
* 删除外宿申请
*
* @param id 外宿申请主键
* @return 结果
*/
int deleteDmsOutsideAccommodationApplyById(Long id);
/**
* 批量删除外宿申请
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
int deleteDmsOutsideAccommodationApplyByIds(Long[] ids);
}

View File

@@ -0,0 +1,71 @@
package com.srs.flowable.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.srs.flowable.domain.OutsideAccommodationApproval;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 外宿申请审批记录Mapper接口
*
* @author srs
* @date 2025-12-05
*/
public interface OutsideAccommodationApprovalMapper extends BaseMapper<OutsideAccommodationApproval> {
/**
* 查询外宿申请审批记录
*
* @param id 外宿申请审批记录主键
* @return 外宿申请审批记录
*/
public OutsideAccommodationApproval selectDmsOutsideAccommodationApprovalById(Long id);
/**
* 根据学生姓名学号和审批人id查询保留学籍审批记录
*
* @param
* @return 结果
*/
OutsideAccommodationApproval selectOutsideAccommodationApprovalByStuName(@Param("studentName") String studentName, @Param("studentNo") String studentNo, @Param("approverId") Long approverId);
/**
* 查询外宿申请审批记录列表
*
* @param dmsOutsideAccommodationApproval 外宿申请审批记录
* @return 外宿申请审批记录集合
*/
List<OutsideAccommodationApproval> selectDmsOutsideAccommodationApprovalList(OutsideAccommodationApproval dmsOutsideAccommodationApproval);
/**
* 新增外宿申请审批记录
*
* @param dmsOutsideAccommodationApproval 外宿申请审批记录
* @return 结果
*/
int insertDmsOutsideAccommodationApproval(OutsideAccommodationApproval dmsOutsideAccommodationApproval);
/**
* 修改外宿申请审批记录
*
* @param dmsOutsideAccommodationApproval 外宿申请审批记录
* @return 结果
*/
int updateDmsOutsideAccommodationApproval(OutsideAccommodationApproval dmsOutsideAccommodationApproval);
/**
* 删除外宿申请审批记录
*
* @param id 外宿申请审批记录主键
* @return 结果
*/
int deleteDmsOutsideAccommodationApprovalById(Long id);
/**
* 批量删除外宿申请审批记录
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
int deleteDmsOutsideAccommodationApprovalByIds(Long[] ids);
}

View File

@@ -0,0 +1,374 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.srs.flowable.mapper.OutsideAccommodationApplyMapper">
<resultMap type="OutsideAccommodationApply" id="DmsOutsideAccommodationApplyResult">
<result property="id" column="id"/>
<result property="applyNo" column="apply_no"/>
<result property="studentId" column="student_id"/>
<result property="studentNo" column="student_no"/>
<result property="studentName" column="student_name"/>
<result property="gender" column="gender"/>
<result property="birthDate" column="birth_date"/>
<result property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
<result property="majorId" column="major_id"/>
<result property="majorName" column="major_name"/>
<result property="classId" column="class_id"/>
<result property="className" column="class_name"/>
<result property="originalDormitory" column="original_dormitory"/>
<result property="accommodationFee" column="accommodation_fee"/>
<result property="accommodationFeeStatus" column="accommodation_fee_status"/>
<result property="applyReason" column="apply_reason"/>
<result property="outsideAddress" column="outside_address"/>
<result property="address" column="address"/>
<result property="emergencyPhone" column="emergency_phone"/>
<result property="emergencyContact" column="emergency_contact"/>
<result property="parentOpinion" column="parent_opinion"/>
<result property="parentSignAttachment" column="parent_sign_attachment"/>
<result property="parentPhone" column="parent_phone"/>
<result property="parentAddress" column="parent_address"/>
<result property="parentDetailAddress" column="parent_detail_address"/>
<result property="studentPromiseSign" column="student_promise_sign"/>
<result property="promiseDate" column="promise_date"/>
<result property="startDate" column="start_date"/>
<result property="endDate" column="end_date"/>
<result property="status" column="status"/>
<result property="rejectReason" column="reject_reason"/>
<result property="createTime" column="create_time"/>
<result property="createBy" column="create_by"/>
<result property="updateTime" column="update_time"/>
<result property="updateBy" column="update_by"/>
<result property="isValid" column="is_valid"/>
<result property="teacherName" column="teacher_name"/>
<result property="affixId" column="affix_id"/>
<result property="deployId" column="deploy_id"/>
<result property="processInstanceId" column="process_instance_id"/>
<result property="idCard" column="idCard"/>
<result property="studentPhone" column="studentPhone"/>
<result property="studentSignature" column="student_signature"/>
</resultMap>
<sql id="selectDmsOutsideAccommodationApplyVo">
select id,
apply_no,
student_id,
student_no,
student_name,
gender,
birth_date,
dept_id,
dept_name,
major_id,
major_name,
class_id,
class_name,
original_dormitory,
accommodation_fee,
accommodation_fee_status,
apply_reason,
outside_address,
address,
emergency_phone,
emergency_contact,
parent_opinion,
parent_sign_attachment,
parent_phone,
parent_address,
parent_detail_address,
student_promise_sign,
promise_date,
start_date,
end_date,
status,
reject_reason,
create_time,
create_by,
update_time,
update_by,
is_valid,
teacher_name,
affix_id,
deploy_id,
process_instance_id,
idCard,
studentPhone,
student_signature
from dms_outside_accommodation_apply
</sql>
<select id="selectDmsOutsideAccommodationApplyList" parameterType="DmsOutsideAccommodationApply"
resultMap="DmsOutsideAccommodationApplyResult">
<include refid="selectDmsOutsideAccommodationApplyVo"/>
<where>
<if test="applyNo != null and applyNo != ''">and apply_no = #{applyNo}</if>
<if test="studentId != null ">and student_id = #{studentId}</if>
<if test="studentNo != null and studentNo != ''">and student_no = #{studentNo}</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="birthDate != null ">and birth_date = #{birthDate}</if>
<if test="deptId != null ">and dept_id = #{deptId}</if>
<if test="deptName != null and deptName != ''">and dept_name like concat('%', #{deptName}, '%')</if>
<if test="majorId != null ">and major_id = #{majorId}</if>
<if test="majorName != null and majorName != ''">and major_name like concat('%', #{majorName}, '%')</if>
<if test="classId != null ">and class_id = #{classId}</if>
<if test="className != null and className != ''">and class_name like concat('%', #{className}, '%')</if>
<if test="originalDormitory != null and originalDormitory != ''">and original_dormitory =
#{originalDormitory}
</if>
<if test="accommodationFee != null and accommodationFee != ''">and accommodation_fee =
#{accommodationFee}
</if>
<if test="accommodationFeeStatus != null ">and accommodation_fee_status = #{accommodationFeeStatus}</if>
<if test="applyReason != null and applyReason != ''">and apply_reason = #{applyReason}</if>
<if test="outsideAddress != null and outsideAddress != ''">and outside_address = #{outsideAddress}</if>
<if test="address != null and address != ''">and address = #{address}</if>
<if test="emergencyPhone != null and emergencyPhone != ''">and emergency_phone = #{emergencyPhone}</if>
<if test="emergencyContact != null and emergencyContact != ''">and emergency_contact =
#{emergencyContact}
</if>
<if test="parentOpinion != null ">and parent_opinion = #{parentOpinion}</if>
<if test="parentSignAttachment != null and parentSignAttachment != ''">and parent_sign_attachment =
#{parentSignAttachment}
</if>
<if test="parentPhone != null and parentPhone != ''">and parent_phone = #{parentPhone}</if>
<if test="parentAddress != null and parentAddress != ''">and parent_address = #{parentAddress}</if>
<if test="parentDetailAddress != null and parentDetailAddress != ''">and parent_detail_address =
#{parentDetailAddress}
</if>
<if test="studentPromiseSign != null and studentPromiseSign != ''">and student_promise_sign =
#{studentPromiseSign}
</if>
<if test="promiseDate != null ">and promise_date = #{promiseDate}</if>
<if test="startDate != null ">and start_date = #{startDate}</if>
<if test="endDate != null ">and end_date = #{endDate}</if>
<if test="status != null ">and status = #{status}</if>
<if test="rejectReason != null and rejectReason != ''">and reject_reason = #{rejectReason}</if>
<if test="isValid != null ">and is_valid = #{isValid}</if>
<if test="teacherName != null and teacherName != ''">and teacher_name like concat('%', #{teacherName},
'%')
</if>
<if test="affixId != null and affixId != ''">and affix_id = #{affixId}</if>
<if test="deployId != null and deployId != ''">and deploy_id = #{deployId}</if>
<if test="processInstanceId != null and processInstanceId != ''">and process_instance_id =
#{processInstanceId}
</if>
<if test="idCard != null and idCard != ''">and idCard = #{idCard}</if>
<if test="studentPhone != null and studentPhone != ''">and studentPhone = #{studentPhone}</if>
<if test="studentSignature != null and studentSignature != ''">and student_signature =
#{studentSignature}
</if>
</where>
</select>
<select id="selectDmsOutsideAccommodationApplyById" parameterType="Long"
resultMap="DmsOutsideAccommodationApplyResult">
<include refid="selectDmsOutsideAccommodationApplyVo"/>
where id = #{id}
</select>
<!--根据学生姓名和学号查询申请表-->
<select id="getAccommodationByStuNameAndStuNo" resultMap="DmsOutsideAccommodationApplyResult">
select *
from rt_enlistment_reserve
<where>
<if test="studentName != null and studentName != ''">
and student_name = #{studentName}
</if>
<if test="studentNo != null and studentNo != ''">
and student_no = #{studentNo}
</if>
</where>
</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
FROM srs_student a
LEFT JOIN srs_class b ON a.class_id = b.class_id
LEFT JOIN cph_teacher c ON b.teacher_id = c.teacher_id
LEFT JOIN sys_user d ON c.employee_id = d.user_name
WHERE a.stu_no = #{stuNo}
</select>
<!-- 获取审批用户信息 -->
<select id="getShenDataInfo" resultType="com.srs.common.doman.vo.TeacherVo">
SELECT a.user_id userId, a.dept_id deptId, a.nick_name userNick, a.user_name userName
FROM sys_user a
LEFT JOIN sys_user_role b ON a.user_id = b.user_id
LEFT JOIN sys_role c ON b.role_id = c.role_id
WHERE c.role_name = #{roleName}
</select>
<insert id="insertDmsOutsideAccommodationApply" parameterType="OutsideAccommodationApply" useGeneratedKeys="true"
keyProperty="id">
insert into dms_outside_accommodation_apply
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="applyNo != null and applyNo != ''">apply_no,</if>
<if test="studentId != null">student_id,</if>
<if test="studentNo != null and studentNo != ''">student_no,</if>
<if test="studentName != null and studentName != ''">student_name,</if>
<if test="gender != null">gender,</if>
<if test="birthDate != null">birth_date,</if>
<if test="deptId != null">dept_id,</if>
<if test="deptName != null and deptName != ''">dept_name,</if>
<if test="majorId != null">major_id,</if>
<if test="majorName != null and majorName != ''">major_name,</if>
<if test="classId != null">class_id,</if>
<if test="className != null and className != ''">class_name,</if>
<if test="originalDormitory != null and originalDormitory != ''">original_dormitory,</if>
<if test="accommodationFee != null and accommodationFee != ''">accommodation_fee,</if>
<if test="accommodationFeeStatus != null">accommodation_fee_status,</if>
<if test="applyReason != null and applyReason != ''">apply_reason,</if>
<if test="outsideAddress != null and outsideAddress != ''">outside_address,</if>
<if test="address != null and address != ''">address,</if>
<if test="emergencyPhone != null and emergencyPhone != ''">emergency_phone,</if>
<if test="emergencyContact != null and emergencyContact != ''">emergency_contact,</if>
<if test="parentOpinion != null">parent_opinion,</if>
<if test="parentSignAttachment != null and parentSignAttachment != ''">parent_sign_attachment,</if>
<if test="parentPhone != null and parentPhone != ''">parent_phone,</if>
<if test="parentAddress != null and parentAddress != ''">parent_address,</if>
<if test="parentDetailAddress != null and parentDetailAddress != ''">parent_detail_address,</if>
<if test="studentPromiseSign != null and studentPromiseSign != ''">student_promise_sign,</if>
<if test="promiseDate != null">promise_date,</if>
<if test="startDate != null">start_date,</if>
<if test="endDate != null">end_date,</if>
<if test="status != null">status,</if>
<if test="rejectReason != null">reject_reason,</if>
<if test="createTime != null">create_time,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="isValid != null">is_valid,</if>
<if test="teacherName != null and teacherName != ''">teacher_name,</if>
<if test="affixId != null">affix_id,</if>
<if test="deployId != null">deploy_id,</if>
<if test="processInstanceId != null">process_instance_id,</if>
<if test="idCard != null and idCard != ''">idCard,</if>
<if test="studentPhone != null">studentPhone,</if>
<if test="studentSignature != null">student_signature,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="applyNo != null and applyNo != ''">#{applyNo},</if>
<if test="studentId != null">#{studentId},</if>
<if test="studentNo != null and studentNo != ''">#{studentNo},</if>
<if test="studentName != null and studentName != ''">#{studentName},</if>
<if test="gender != null">#{gender},</if>
<if test="birthDate != null">#{birthDate},</if>
<if test="deptId != null">#{deptId},</if>
<if test="deptName != null and deptName != ''">#{deptName},</if>
<if test="majorId != null">#{majorId},</if>
<if test="majorName != null and majorName != ''">#{majorName},</if>
<if test="classId != null">#{classId},</if>
<if test="className != null and className != ''">#{className},</if>
<if test="originalDormitory != null and originalDormitory != ''">#{originalDormitory},</if>
<if test="accommodationFee != null and accommodationFee != ''">#{accommodationFee},</if>
<if test="accommodationFeeStatus != null">#{accommodationFeeStatus},</if>
<if test="applyReason != null and applyReason != ''">#{applyReason},</if>
<if test="outsideAddress != null and outsideAddress != ''">#{outsideAddress},</if>
<if test="address != null and address != ''">#{address},</if>
<if test="emergencyPhone != null and emergencyPhone != ''">#{emergencyPhone},</if>
<if test="emergencyContact != null and emergencyContact != ''">#{emergencyContact},</if>
<if test="parentOpinion != null">#{parentOpinion},</if>
<if test="parentSignAttachment != null and parentSignAttachment != ''">#{parentSignAttachment},</if>
<if test="parentPhone != null and parentPhone != ''">#{parentPhone},</if>
<if test="parentAddress != null and parentAddress != ''">#{parentAddress},</if>
<if test="parentDetailAddress != null and parentDetailAddress != ''">#{parentDetailAddress},</if>
<if test="studentPromiseSign != null and studentPromiseSign != ''">#{studentPromiseSign},</if>
<if test="promiseDate != null">#{promiseDate},</if>
<if test="startDate != null">#{startDate},</if>
<if test="endDate != null">#{endDate},</if>
<if test="status != null">#{status},</if>
<if test="rejectReason != null">#{rejectReason},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="isValid != null">#{isValid},</if>
<if test="teacherName != null and teacherName != ''">#{teacherName},</if>
<if test="affixId != null">#{affixId},</if>
<if test="deployId != null">#{deployId},</if>
<if test="processInstanceId != null">#{processInstanceId},</if>
<if test="idCard != null and idCard != ''">#{idCard},</if>
<if test="studentPhone != null">#{studentPhone},</if>
<if test="studentSignature != null">#{studentSignature},</if>
</trim>
</insert>
<update id="updateDmsOutsideAccommodationApply" parameterType="OutsideAccommodationApply">
update dms_outside_accommodation_apply
<trim prefix="SET" suffixOverrides=",">
<if test="applyNo != null and applyNo != ''">apply_no = #{applyNo},</if>
<if test="studentId != null">student_id = #{studentId},</if>
<if test="studentNo != null and studentNo != ''">student_no = #{studentNo},</if>
<if test="studentName != null and studentName != ''">student_name = #{studentName},</if>
<if test="gender != null">gender = #{gender},</if>
<if test="birthDate != null">birth_date = #{birthDate},</if>
<if test="deptId != null">dept_id = #{deptId},</if>
<if test="deptName != null and deptName != ''">dept_name = #{deptName},</if>
<if test="majorId != null">major_id = #{majorId},</if>
<if test="majorName != null and majorName != ''">major_name = #{majorName},</if>
<if test="classId != null">class_id = #{classId},</if>
<if test="className != null and className != ''">class_name = #{className},</if>
<if test="originalDormitory != null and originalDormitory != ''">original_dormitory =
#{originalDormitory},
</if>
<if test="accommodationFee != null and accommodationFee != ''">accommodation_fee = #{accommodationFee},</if>
<if test="accommodationFeeStatus != null">accommodation_fee_status = #{accommodationFeeStatus},</if>
<if test="applyReason != null and applyReason != ''">apply_reason = #{applyReason},</if>
<if test="outsideAddress != null and outsideAddress != ''">outside_address = #{outsideAddress},</if>
<if test="address != null and address != ''">address = #{address},</if>
<if test="emergencyPhone != null and emergencyPhone != ''">emergency_phone = #{emergencyPhone},</if>
<if test="emergencyContact != null and emergencyContact != ''">emergency_contact = #{emergencyContact},</if>
<if test="parentOpinion != null">parent_opinion = #{parentOpinion},</if>
<if test="parentSignAttachment != null and parentSignAttachment != ''">parent_sign_attachment =
#{parentSignAttachment},
</if>
<if test="parentPhone != null and parentPhone != ''">parent_phone = #{parentPhone},</if>
<if test="parentAddress != null and parentAddress != ''">parent_address = #{parentAddress},</if>
<if test="parentDetailAddress != null and parentDetailAddress != ''">parent_detail_address =
#{parentDetailAddress},
</if>
<if test="studentPromiseSign != null and studentPromiseSign != ''">student_promise_sign =
#{studentPromiseSign},
</if>
<if test="promiseDate != null">promise_date = #{promiseDate},</if>
<if test="startDate != null">start_date = #{startDate},</if>
<if test="endDate != null">end_date = #{endDate},</if>
<if test="status != null">status = #{status},</if>
<if test="rejectReason != null">reject_reason = #{rejectReason},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="isValid != null">is_valid = #{isValid},</if>
<if test="teacherName != null and teacherName != ''">teacher_name = #{teacherName},</if>
<if test="affixId != null">affix_id = #{affixId},</if>
<if test="deployId != null">deploy_id = #{deployId},</if>
<if test="processInstanceId != null">process_instance_id = #{processInstanceId},</if>
<if test="idCard != null and idCard != ''">idCard = #{idCard},</if>
<if test="studentPhone != null">studentPhone = #{studentPhone},</if>
<if test="studentSignature != null">student_signature = #{studentSignature},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteDmsOutsideAccommodationApplyById" parameterType="Long">
delete
from dms_outside_accommodation_apply
where id = #{id}
</delete>
<delete id="deleteDmsOutsideAccommodationApplyByIds" parameterType="String">
delete from dms_outside_accommodation_apply where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.srs.flowable.mapper.OutsideAccommodationApprovalMapper">
<resultMap type="DmsOutsideAccommodationApproval" id="DmsOutsideAccommodationApprovalResult">
<result property="id" column="id" />
<result property="applyId" column="apply_id" />
<result property="applyNo" column="apply_no" />
<result property="approvalNode" column="approval_node" />
<result property="approverId" column="approver_id" />
<result property="approverName" column="approver_name" />
<result property="approverRole" column="approver_role" />
<result property="approvalOpinion" column="approval_opinion" />
<result property="approvalResult" column="approval_result" />
<result property="approvalTime" column="approval_time" />
<result property="processInstanceId" column="process_instance_id" />
<result property="studentName" column="student_name" />
<result property="studentNo" column="student_no" />
</resultMap>
<sql id="selectDmsOutsideAccommodationApprovalVo">
select id, apply_id, apply_no, approval_node, approver_id, approver_name, approver_role, approval_opinion, approval_result, approval_time, process_instance_id, student_name, student_no from dms_outside_accommodation_approval
</sql>
<select id="selectDmsOutsideAccommodationApprovalList" parameterType="DmsOutsideAccommodationApproval" resultMap="DmsOutsideAccommodationApprovalResult">
<include refid="selectDmsOutsideAccommodationApprovalVo"/>
<where>
<if test="applyId != null "> and apply_id = #{applyId}</if>
<if test="applyNo != null and applyNo != ''"> and apply_no = #{applyNo}</if>
<if test="approvalNode != null "> and approval_node = #{approvalNode}</if>
<if test="approverId != null "> and approver_id = #{approverId}</if>
<if test="approverName != null and approverName != ''"> and approver_name like concat('%', #{approverName}, '%')</if>
<if test="approverRole != null and approverRole != ''"> and approver_role = #{approverRole}</if>
<if test="approvalOpinion != null and approvalOpinion != ''"> and approval_opinion = #{approvalOpinion}</if>
<if test="approvalResult != null "> and approval_result = #{approvalResult}</if>
<if test="approvalTime != null "> and approval_time = #{approvalTime}</if>
<if test="processInstanceId != null and processInstanceId != ''"> and process_instance_id = #{processInstanceId}</if>
<if test="studentName != null and studentName != ''"> and student_name like concat('%', #{studentName}, '%')</if>
<if test="studentNo != null and studentNo != ''"> and student_no = #{studentNo}</if>
</where>
</select>
<select id="selectDmsOutsideAccommodationApprovalById" parameterType="Long" resultMap="DmsOutsideAccommodationApprovalResult">
<include refid="selectDmsOutsideAccommodationApprovalVo"/>
where id = #{id}
</select>
<select id="selectOutsideAccommodationApprovalByStuName" resultMap="DmsOutsideAccommodationApprovalResult">
select *
from dms_outside_accommodation_approval
<where>
<if test="studentName != null and studentName != ''">
and student_name = #{studentName}
</if>
<if test="studentNo != null and studentNo != ''">
and student_no = #{studentNo}
</if>
<if test="approverId != null and approverId != ''">
and approver_id = #{approverId}
</if>
</where>
</select>
<insert id="insertDmsOutsideAccommodationApproval" parameterType="DmsOutsideAccommodationApproval" useGeneratedKeys="true" keyProperty="id">
insert into dms_outside_accommodation_approval
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="applyId != null">apply_id,</if>
<if test="applyNo != null and applyNo != ''">apply_no,</if>
<if test="approvalNode != null">approval_node,</if>
<if test="approverId != null">approver_id,</if>
<if test="approverName != null and approverName != ''">approver_name,</if>
<if test="approverRole != null and approverRole != ''">approver_role,</if>
<if test="approvalOpinion != null">approval_opinion,</if>
<if test="approvalResult != null">approval_result,</if>
<if test="approvalTime != null">approval_time,</if>
<if test="processInstanceId != null">process_instance_id,</if>
<if test="studentName != null and studentName != ''">student_name,</if>
<if test="studentNo != null and studentNo != ''">student_no,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="applyId != null">#{applyId},</if>
<if test="applyNo != null and applyNo != ''">#{applyNo},</if>
<if test="approvalNode != null">#{approvalNode},</if>
<if test="approverId != null">#{approverId},</if>
<if test="approverName != null and approverName != ''">#{approverName},</if>
<if test="approverRole != null and approverRole != ''">#{approverRole},</if>
<if test="approvalOpinion != null">#{approvalOpinion},</if>
<if test="approvalResult != null">#{approvalResult},</if>
<if test="approvalTime != null">#{approvalTime},</if>
<if test="processInstanceId != null">#{processInstanceId},</if>
<if test="studentName != null and studentName != ''">#{studentName},</if>
<if test="studentNo != null and studentNo != ''">#{studentNo},</if>
</trim>
</insert>
<update id="updateDmsOutsideAccommodationApproval" parameterType="DmsOutsideAccommodationApproval">
update dms_outside_accommodation_approval
<trim prefix="SET" suffixOverrides=",">
<if test="applyId != null">apply_id = #{applyId},</if>
<if test="applyNo != null and applyNo != ''">apply_no = #{applyNo},</if>
<if test="approvalNode != null">approval_node = #{approvalNode},</if>
<if test="approverId != null">approver_id = #{approverId},</if>
<if test="approverName != null and approverName != ''">approver_name = #{approverName},</if>
<if test="approverRole != null and approverRole != ''">approver_role = #{approverRole},</if>
<if test="approvalOpinion != null">approval_opinion = #{approvalOpinion},</if>
<if test="approvalResult != null">approval_result = #{approvalResult},</if>
<if test="approvalTime != null">approval_time = #{approvalTime},</if>
<if test="processInstanceId != null">process_instance_id = #{processInstanceId},</if>
<if test="studentName != null and studentName != ''">student_name = #{studentName},</if>
<if test="studentNo != null and studentNo != ''">student_no = #{studentNo},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteDmsOutsideAccommodationApprovalById" parameterType="Long">
delete from dms_outside_accommodation_approval where id = #{id}
</delete>
<delete id="deleteDmsOutsideAccommodationApprovalByIds" parameterType="String">
delete from dms_outside_accommodation_approval where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -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);
}

View File

@@ -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;
}
}