Commit e3b86b3d7a58b34bcb6e12e48beb21784a7cdf24
1 parent
d839aded
bpm 增加任务分配到指定人时,发送短信通知
Showing
9 changed files
with
215 additions
and
0 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/message/BpmMessageConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.convert.message; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; | ||
| 4 | +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; | ||
| 5 | +import org.activiti.api.task.model.Task; | ||
| 6 | +import org.activiti.engine.runtime.ProcessInstance; | ||
| 7 | +import org.mapstruct.Mapper; | ||
| 8 | +import org.mapstruct.Mapping; | ||
| 9 | +import org.mapstruct.MappingTarget; | ||
| 10 | +import org.mapstruct.Mappings; | ||
| 11 | +import org.mapstruct.factory.Mappers; | ||
| 12 | + | ||
| 13 | +@Mapper | ||
| 14 | +public interface BpmMessageConvert { | ||
| 15 | + | ||
| 16 | + BpmMessageConvert INSTANCE = Mappers.getMapper(BpmMessageConvert.class); | ||
| 17 | + | ||
| 18 | + default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, SysUserDO startUser, Task task) { | ||
| 19 | + BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); | ||
| 20 | + copyTo(processInstance, reqDTO); | ||
| 21 | + copyTo(startUser, reqDTO); | ||
| 22 | + copyTo(task, reqDTO); | ||
| 23 | + return reqDTO; | ||
| 24 | + } | ||
| 25 | + @Mapping(source = "name", target = "processInstanceName") | ||
| 26 | + void copyTo(ProcessInstance from, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); | ||
| 27 | + @Mappings({ | ||
| 28 | + @Mapping(source = "id", target = "startUserId"), | ||
| 29 | + @Mapping(source = "nickname", target = "startUserNickname") | ||
| 30 | + }) | ||
| 31 | + void copyTo(SysUserDO from, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); | ||
| 32 | + @Mappings({ | ||
| 33 | + @Mapping(source = "id", target = "taskId"), | ||
| 34 | + @Mapping(source = "name", target = "taskName"), | ||
| 35 | + @Mapping(source = "assignee", target = "assigneeUserId") | ||
| 36 | + }) | ||
| 37 | + void copyTo(Task task, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); | ||
| 38 | + | ||
| 39 | +} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/message/BpmMessageEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.enums.message; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; | ||
| 4 | +import lombok.AllArgsConstructor; | ||
| 5 | +import lombok.Getter; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * Bpm 消息的枚举 | ||
| 9 | + * | ||
| 10 | + * @author 芋道源码 | ||
| 11 | + */ | ||
| 12 | +@AllArgsConstructor | ||
| 13 | +@Getter | ||
| 14 | +public enum BpmMessageEnum { | ||
| 15 | + | ||
| 16 | + TASK_ASSIGNED("bpm_task_assigned"); // 任务被分配时,发送给审批人 | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 短信模板的标识 | ||
| 20 | + * | ||
| 21 | + * 关联 {@link SysSmsTemplateDO#getCode()} | ||
| 22 | + */ | ||
| 23 | + private final String smsCode; | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmTaskEventListener.java
| @@ -53,6 +53,12 @@ public class BpmTaskEventListener<T extends RuntimeEvent<?, ?>> | @@ -53,6 +53,12 @@ public class BpmTaskEventListener<T extends RuntimeEvent<?, ?>> | ||
| 53 | return; | 53 | return; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | + // 审核人修改时,进行拓展表,并额外发送通知 | ||
| 57 | + if (event.getEventType() == TaskRuntimeEvent.TaskEvents.TASK_ASSIGNED) { | ||
| 58 | + taskService.updateTaskExtAssign(event.getEntity()); | ||
| 59 | + return; | ||
| 60 | + } | ||
| 61 | + | ||
| 56 | // 其它事件,进行更新拓展表 | 62 | // 其它事件,进行更新拓展表 |
| 57 | taskService.updateTaskExt(event.getEntity()); | 63 | taskService.updateTaskExt(event.getEntity()); |
| 58 | } | 64 | } |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/BpmMessageService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.service.message; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; | ||
| 4 | + | ||
| 5 | +import javax.validation.Valid; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * BPM 消息 Service 接口 | ||
| 9 | + * | ||
| 10 | + * TODO 芋艿:未来支持消息的可配置;不同的流程,在什么场景下,需要发送什么消息,消息的内容是什么; | ||
| 11 | + * | ||
| 12 | + * @author 芋道源码 | ||
| 13 | + */ | ||
| 14 | +public interface BpmMessageService { | ||
| 15 | + | ||
| 16 | + void sendMessageWhenTaskAssigned(@Valid BpmMessageSendWhenTaskCreatedReqDTO reqDTO); | ||
| 17 | + | ||
| 18 | +} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import javax.validation.constraints.NotEmpty; | ||
| 6 | +import javax.validation.constraints.NotNull; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * BPM 发送任务创建的 Request DTO | ||
| 10 | + */ | ||
| 11 | +@Data | ||
| 12 | +public class BpmMessageSendWhenTaskCreatedReqDTO { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 流程实例的编号 | ||
| 16 | + */ | ||
| 17 | + @NotEmpty(message = "流程实例的编号不能为空") | ||
| 18 | + private String processInstanceId; | ||
| 19 | + /** | ||
| 20 | + * 流程实例的名字 | ||
| 21 | + */ | ||
| 22 | + @NotEmpty(message = "流程实例的名字不能为空") | ||
| 23 | + private String processInstanceName; | ||
| 24 | + @NotEmpty(message = "发起人的用户编号") | ||
| 25 | + private String startUserId; | ||
| 26 | + @NotEmpty(message = "发起人的昵称") | ||
| 27 | + private String startUserNickname; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 流程任务的编号 | ||
| 31 | + */ | ||
| 32 | + @NotEmpty(message = "流程任务的编号不能为空") | ||
| 33 | + private String taskId; | ||
| 34 | + /** | ||
| 35 | + * 流程任务的名字 | ||
| 36 | + */ | ||
| 37 | + @NotEmpty(message = "流程任务的名字不能为空") | ||
| 38 | + private String taskName; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 审批人的用户编号 | ||
| 42 | + */ | ||
| 43 | + @NotNull(message = "审批人的用户编号不能为空") | ||
| 44 | + private Long assigneeUserId; | ||
| 45 | + | ||
| 46 | +} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/impl/BpmMessageServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.service.message.impl; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.adminserver.modules.bpm.enums.message.BpmMessageEnum; | ||
| 4 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.message.BpmMessageService; | ||
| 5 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; | ||
| 6 | +import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService; | ||
| 7 | +import lombok.extern.slf4j.Slf4j; | ||
| 8 | +import org.springframework.beans.factory.annotation.Value; | ||
| 9 | +import org.springframework.stereotype.Service; | ||
| 10 | +import org.springframework.validation.annotation.Validated; | ||
| 11 | + | ||
| 12 | +import javax.annotation.Resource; | ||
| 13 | +import java.util.HashMap; | ||
| 14 | +import java.util.Map; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * BPM 消息 Service 实现类 | ||
| 18 | + * | ||
| 19 | + * @author 芋道源码 | ||
| 20 | + */ | ||
| 21 | +@Service | ||
| 22 | +@Validated | ||
| 23 | +@Slf4j | ||
| 24 | +public class BpmMessageServiceImpl implements BpmMessageService { | ||
| 25 | + | ||
| 26 | + @Resource | ||
| 27 | + private SysSmsCoreService smsCoreService; | ||
| 28 | + | ||
| 29 | + @Value("${yudao.url.admin-ui}") | ||
| 30 | + private String adminUiUrl; | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public void sendMessageWhenTaskAssigned(BpmMessageSendWhenTaskCreatedReqDTO reqDTO) { | ||
| 34 | + Map<String, Object> templateParams = new HashMap<>(); | ||
| 35 | + templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); | ||
| 36 | + templateParams.put("taskName", reqDTO.getTaskName()); | ||
| 37 | + templateParams.put("startUserNickname", reqDTO.getStartUserNickname()); | ||
| 38 | + templateParams.put("taskDetailUrl", getTaskDetailUrl(reqDTO.getTaskId())); | ||
| 39 | + smsCoreService.sendSingleSmsToAdmin(null, reqDTO.getAssigneeUserId(), | ||
| 40 | + BpmMessageEnum.TASK_ASSIGNED.getSmsCode(), templateParams); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + private String getTaskDetailUrl(String taskId) { | ||
| 44 | + return adminUiUrl + "bpm/process-instance/detail?id=" + taskId; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | +} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java
| @@ -127,6 +127,13 @@ public interface BpmTaskService { | @@ -127,6 +127,13 @@ public interface BpmTaskService { | ||
| 127 | void updateTaskExt(org.activiti.api.task.model.Task task); | 127 | void updateTaskExt(org.activiti.api.task.model.Task task); |
| 128 | 128 | ||
| 129 | /** | 129 | /** |
| 130 | + * 更新 Task 拓展记录,并发送通知 | ||
| 131 | + * | ||
| 132 | + * @param task 任务实体 | ||
| 133 | + */ | ||
| 134 | + void updateTaskExtAssign(org.activiti.api.task.model.Task task); | ||
| 135 | + | ||
| 136 | + /** | ||
| 130 | * 更新 Task 拓展记录为取消 | 137 | * 更新 Task 拓展记录为取消 |
| 131 | * | 138 | * |
| 132 | * @param task 任务实体 | 139 | * @param task 任务实体 |
| @@ -148,4 +155,5 @@ public interface BpmTaskService { | @@ -148,4 +155,5 @@ public interface BpmTaskService { | ||
| 148 | */ | 155 | */ |
| 149 | List<BpmTaskExtDO> getTaskExtListByProcessInstanceId(String processInstanceId); | 156 | List<BpmTaskExtDO> getTaskExtListByProcessInstanceId(String processInstanceId); |
| 150 | 157 | ||
| 158 | + | ||
| 151 | } | 159 | } |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java
| 1 | package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl; | 1 | package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.thread.ThreadUtil; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*; | 6 | import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*; |
| 7 | +import cn.iocoder.yudao.adminserver.modules.bpm.convert.message.BpmMessageConvert; | ||
| 6 | import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmTaskConvert; | 8 | import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmTaskConvert; |
| 7 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; | 9 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; |
| 8 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmTaskExtMapper; | 10 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmTaskExtMapper; |
| 9 | import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; | 11 | import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; |
| 12 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.message.BpmMessageService; | ||
| 10 | import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; | 13 | import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; |
| 11 | import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; | 14 | import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; |
| 12 | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; | 15 | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; |
| @@ -29,10 +32,13 @@ import org.activiti.engine.task.TaskQuery; | @@ -29,10 +32,13 @@ import org.activiti.engine.task.TaskQuery; | ||
| 29 | import org.springframework.context.annotation.Lazy; | 32 | import org.springframework.context.annotation.Lazy; |
| 30 | import org.springframework.stereotype.Service; | 33 | import org.springframework.stereotype.Service; |
| 31 | import org.springframework.transaction.annotation.Transactional; | 34 | import org.springframework.transaction.annotation.Transactional; |
| 35 | +import org.springframework.transaction.support.TransactionSynchronization; | ||
| 36 | +import org.springframework.transaction.support.TransactionSynchronizationManager; | ||
| 32 | 37 | ||
| 33 | import javax.annotation.Resource; | 38 | import javax.annotation.Resource; |
| 34 | import javax.validation.Valid; | 39 | import javax.validation.Valid; |
| 35 | import java.util.*; | 40 | import java.util.*; |
| 41 | +import java.util.concurrent.TimeUnit; | ||
| 36 | 42 | ||
| 37 | import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; | 43 | import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; |
| 38 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 44 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| @@ -61,6 +67,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -61,6 +67,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 61 | @Resource | 67 | @Resource |
| 62 | @Lazy // 解决循环依赖 | 68 | @Lazy // 解决循环依赖 |
| 63 | private BpmProcessInstanceService processInstanceService; | 69 | private BpmProcessInstanceService processInstanceService; |
| 70 | + @Resource | ||
| 71 | + private BpmMessageService messageService; | ||
| 64 | 72 | ||
| 65 | @Resource | 73 | @Resource |
| 66 | private BpmTaskExtMapper taskExtMapper; | 74 | private BpmTaskExtMapper taskExtMapper; |
| @@ -278,6 +286,21 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -278,6 +286,21 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 278 | } | 286 | } |
| 279 | 287 | ||
| 280 | @Override | 288 | @Override |
| 289 | + public void updateTaskExtAssign(org.activiti.api.task.model.Task task) { | ||
| 290 | + // 更新 | ||
| 291 | + updateTaskExt(task); | ||
| 292 | + // 发送通知。由于 Activiti 操作是在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。 | ||
| 293 | + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { | ||
| 294 | + @Override | ||
| 295 | + public void afterCommit() { | ||
| 296 | + ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); | ||
| 297 | + SysUserDO startUser = userService.getUser(Long.valueOf(processInstance.getStartUserId())); | ||
| 298 | + messageService.sendMessageWhenTaskAssigned(BpmMessageConvert.INSTANCE.convert(processInstance, startUser, task)); | ||
| 299 | + } | ||
| 300 | + }); | ||
| 301 | + } | ||
| 302 | + | ||
| 303 | + @Override | ||
| 281 | public void updateTaskExtCancel(org.activiti.api.task.model.Task task) { | 304 | public void updateTaskExtCancel(org.activiti.api.task.model.Task task) { |
| 282 | BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert(task) | 305 | BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert(task) |
| 283 | .setEndTime(new Date()) // 由于 Task 里没有办法拿到 endTime,所以这里设置 | 306 | .setEndTime(new Date()) // 由于 Task 里没有办法拿到 endTime,所以这里设置 |
yudao-admin-server/src/main/resources/application.yaml
| @@ -72,5 +72,7 @@ yudao: | @@ -72,5 +72,7 @@ yudao: | ||
| 72 | - cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants | 72 | - cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants |
| 73 | tenant: # 多租户相关配置项 | 73 | tenant: # 多租户相关配置项 |
| 74 | tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置 | 74 | tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置 |
| 75 | + url: | ||
| 76 | + admin-ui: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址 | ||
| 75 | 77 | ||
| 76 | debug: false | 78 | debug: false |