增加 BpmProcessInstanceResultEvent 实现,实现自定义的流程实例的状态的监听

pull/2/head
YunaiV 2022-01-22 23:56:15 +08:00
parent 7c62b1a211
commit 5437775172
15 changed files with 224 additions and 64 deletions

View File

@ -1,18 +1,21 @@
package cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo;
import lombok.*;
import io.swagger.annotations.*;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import javax.validation.constraints.AssertTrue;
@ApiModel("请假申请创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BpmOALeaveCreateReqVO extends BpmOALeaveBaseVO {
@AssertTrue(message = "结束时间,需要在开始时间之后")
public boolean isEndTimeValid() {
return !getEndTime().before(getStartTime());
}
}

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmP
import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskRespVO;
import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEvent;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -98,4 +99,22 @@ public interface BpmProcessInstanceConvert {
void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessInstanceRespVO.ProcessDefinition to);
BpmProcessInstanceRespVO.User convert2(SysUserDO bean);
default BpmProcessInstanceResultEvent convert(Object source, ProcessInstance instance, Integer result) {
BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source);
event.setId(instance.getId());
event.setProcessDefinitionKey(instance.getProcessDefinitionKey());
event.setBusinessKey(instance.getBusinessKey());
event.setResult(result);
return event;
}
default BpmProcessInstanceResultEvent convert(Object source, HistoricProcessInstance instance, Integer result) {
BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source);
event.setId(instance.getId());
event.setProcessDefinitionKey(instance.getProcessDefinitionKey());
event.setBusinessKey(instance.getBusinessKey());
event.setResult(result);
return event;
}
}

View File

@ -13,7 +13,8 @@ import lombok.Getter;
@AllArgsConstructor
public enum BpmProcessInstanceDeleteReasonEnum {
REJECT_TASK("不通过任务,原因:{}"); // 修改文案时,需要注意 isRejectReason 方法
REJECT_TASK("不通过任务,原因:{}"), // 修改文案时,需要注意 isRejectReason 方法
CANCEL_TASK("主动取消任务,原因:{}");
private final String reason;

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.config;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.BpmActivityBehaviorFactory;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEventPublisher;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.identity.EmptyUserGroupManager;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.listener.BpmTackActivitiEventListener;
import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService;
@ -11,6 +12,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermiss
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import org.activiti.api.runtime.shared.identity.UserGroupManager;
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -71,4 +73,9 @@ public class BpmActivitiConfiguration {
return bpmActivityBehaviorFactory;
}
@Bean
public BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher(ApplicationEventPublisher publisher) {
return new BpmProcessInstanceResultEventPublisher(publisher);
}
}

View File

@ -0,0 +1,44 @@
package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event;
import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import lombok.Data;
import org.springframework.context.ApplicationEvent;
import javax.validation.constraints.NotNull;
/**
* Event
* {@link BpmProcessInstanceExtDO#getResult()}
*
* @author
*/
@SuppressWarnings("ALL")
@Data
public class BpmProcessInstanceResultEvent extends ApplicationEvent {
/**
*
*/
@NotNull(message = "流程实例的编号不能为空")
private String id;
/**
* key
*/
@NotNull(message = "流程实例的 key 不能为空")
private String processDefinitionKey;
/**
*
*/
@NotNull(message = "流程实例的结果不能为空")
private Integer result;
/**
*
*
*/
private String businessKey;
public BpmProcessInstanceResultEvent(Object source) {
super(source);
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event;
import cn.hutool.core.util.StrUtil;
import org.springframework.context.ApplicationListener;
/**
* {@link BpmProcessInstanceResultEvent}
*
* @author
*/
public abstract class BpmProcessInstanceResultEventListener
implements ApplicationListener<BpmProcessInstanceResultEvent> {
@Override
public final void onApplicationEvent(BpmProcessInstanceResultEvent event) {
if (!StrUtil.equals(event.getProcessDefinitionKey(), getProcessDefinitionKey())) {
return;
}
onEvent(event);
}
/**
* @return Key
*/
protected abstract String getProcessDefinitionKey();
/**
*
*
* @param event
*/
protected abstract void onEvent(BpmProcessInstanceResultEvent event);
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
/**
* {@link BpmProcessInstanceResultEvent}
*
* @author
*/
@AllArgsConstructor
@Validated
public class BpmProcessInstanceResultEventPublisher {
private final ApplicationEventPublisher publisher;
public void sendProcessInstanceResultEvent(@Valid BpmProcessInstanceResultEvent event) {
publisher.publishEvent(event);
}
}

View File

@ -0,0 +1,6 @@
/**
* Event 便 Listener
*
* @author
*/
package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event;

View File

@ -2,10 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;
import javax.validation.constraints.AssertTrue;

View File

@ -24,6 +24,14 @@ public interface BpmOALeaveService {
*/
Long createLeave(Long userId, @Valid BpmOALeaveCreateReqVO createReqVO);
/**
*
*
* @param id
* @param result
*/
void updateLeaveResult(Long id, Integer result);
/**
*
*

View File

@ -1,40 +0,0 @@
package cn.iocoder.yudao.adminserver.modules.bpm.service.oa;
import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.OALeaveDO;
import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa.BpmOALeaveMapper;
import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Objects;
/**
*
*/
@Component
public class LeaveApplyEndProcessor implements ExecutionListener {
@Resource
private BpmOALeaveMapper leaveMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void notify(DelegateExecution delegateExecution) {
final String businessKey = delegateExecution.getProcessInstanceBusinessKey();
final Object approved = delegateExecution.getVariable("approved");
OALeaveDO updateDo = new OALeaveDO();
updateDo.setId(Long.valueOf(businessKey));
if (Objects.equals(approved, true)) {
updateDo.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult());
} else {
updateDo.setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
}
leaveMapper.updateById(updateDo);
}
}

View File

@ -34,7 +34,7 @@ public class OALeaveServiceImpl implements BpmOALeaveService {
/**
* OA KEY
*/
private static final String PROCESS_KEY = "oa_leave";
public static final String PROCESS_KEY = "oa_leave";
@Resource
private BpmOALeaveMapper leaveMapper;
@ -45,14 +45,8 @@ public class OALeaveServiceImpl implements BpmOALeaveService {
@Override
@Transactional(rollbackFor = Exception.class)
public Long createLeave(Long userId, BpmOALeaveCreateReqVO createReqVO) {
// TODO 芋道源码
// 校验是否超过请假天数的上限;
long day = DateUtil.betweenDay(createReqVO.getStartTime(), createReqVO.getEndTime(), false);
if (day <= 0) {
throw ServiceExceptionUtil.exception(OA_DAY_LEAVE_ERROR);
}
// 插入 OA 请假单
long day = DateUtil.betweenDay(createReqVO.getStartTime(), createReqVO.getEndTime(), false);
OALeaveDO leave = OALeaveConvert.INSTANCE.convert(createReqVO).setUserId(userId).setDay(day)
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
leaveMapper.insert(leave);
@ -69,6 +63,11 @@ public class OALeaveServiceImpl implements BpmOALeaveService {
return leave.getId();
}
@Override
public void updateLeaveResult(Long id, Integer result) {
leaveMapper.updateById(new OALeaveDO().setId(id).setResult(result));
}
@Override
public void cancelLeave(Long id) {
// TODO 需要重新实现

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.adminserver.modules.bpm.service.oa.listener;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEvent;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEventListener;
import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.BpmOALeaveService;
import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.impl.OALeaveServiceImpl;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* OA
*
* @author
*/
@Component
public class BpmOALeaveResultListener extends BpmProcessInstanceResultEventListener {
@Resource
private BpmOALeaveService leaveService;
@Override
protected String getProcessDefinitionKey() {
return OALeaveServiceImpl.PROCESS_KEY;
}
@Override
protected void onEvent(BpmProcessInstanceResultEvent event) {
leaveService.updateLeaveResult(Long.parseLong(event.getBusinessKey()), event.getResult());
}
}

View File

@ -152,7 +152,6 @@ public interface BpmProcessInstanceService {
* ProcessInstance
*
* @param instance
* @param reason
*/
void updateProcessInstanceExtComplete(org.activiti.api.process.model.ProcessInstance instance);

View File

@ -12,6 +12,9 @@ import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmProcessInstanc
import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEvent;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEventListener;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEventPublisher;
import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.adminserver.modules.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
@ -76,6 +79,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
@Resource
private BpmMessageService messageService;
@Resource
private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;
@Resource
private BpmProcessInstanceExtMapper processInstanceExtMapper;
@ -141,7 +147,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
}
// 通过删除流程实例,实现流程实例的取消
runtimeService.deleteProcessInstance(cancelReqVO.getId(), cancelReqVO.getReason());
runtimeService.deleteProcessInstance(cancelReqVO.getId(),
BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));
}
@Override
@ -247,16 +254,26 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
return;
}
// 需要主动查询,因为 instance 只有 id 属性
ProcessInstance processInstance = getProcessInstance(instance.getId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance)
.setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Override
public void updateProcessInstanceExtComplete(org.activiti.api.process.model.ProcessInstance instance) {
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance)
.setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
@ -265,10 +282,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
// 发送流程被通过的消息
messageService.sendMessageWhenProcessInstanceApprove(BpmMessageConvert.INSTANCE.convert(instance));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Transactional(rollbackFor = Exception.class)
public void updateProcessInstanceExtReject(String id, String comment) {
// 需要主动查询,因为 instance 只有 id 属性
ProcessInstance processInstance = getProcessInstance(id);
// 删除流程实例,以实现驳回任务时,取消整个审批流程
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(comment)));
@ -276,12 +298,17 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
// 更新 status + result
// 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
// 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL显然和 result 不一定是一致的
processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(id)
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult()));
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被不通过的消息
messageService.sendMessageWhenProcessInstanceReject(BpmMessageConvert.INSTANCE.convert(processInstance, comment));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
}