diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseapply/ExpenseApplyServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseapply/ExpenseApplyServiceImpl.java index 143487a4..fe1f95eb 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseapply/ExpenseApplyServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseapply/ExpenseApplyServiceImpl.java @@ -91,6 +91,8 @@ public class ExpenseApplyServiceImpl extends MPJBaseServiceImpl variables = new HashMap<>(); variables.put("billType", expenseApply.getBillType()); + variables.put("billId", expenseApply.getId()); + variables.put("billName", BillTypeEnum.getNameByValue(expenseApply.getBillType())); variables.put("amount", expenseApply.getAmount()); variables.put("deptId", expenseApply.getDeptId()); String processInstanceId = processInstanceApi.createProcessInstance(expenseApply.getUserId(), diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimServiceImpl.java index 834cc558..659b4b31 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/expenseclaim/ExpenseClaimServiceImpl.java @@ -104,6 +104,8 @@ public class ExpenseClaimServiceImpl extends MPJBaseServiceImpl variables = new HashMap<>(); variables.put("billType", expenseClaim.getBillType()); + variables.put("billId", expenseClaim.getId()); + variables.put("billName", BillTypeEnum.getNameByValue(expenseClaim.getBillType())); variables.put("amount", expenseClaim.getAmount()); variables.put("deptId", expenseClaim.getDeptId()); String processInstanceId = processInstanceApi.createProcessInstance(expenseClaim.getUserId(), diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java index ff51ae30..13dadef3 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcess import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; import javax.validation.Valid; +import java.util.Map; /** * BPM 消息 Service 接口 @@ -25,9 +26,10 @@ public interface BpmMessageService { /** * 发送流程实例被不通过的消息 * - * @param reqDTO 发送信息 + * @param reqDTO 发送信息 + * @param variables */ - void sendMessageWhenProcessInstanceReject(@Valid BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO); + void sendMessageWhenProcessInstanceReject(@Valid BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO, Map variables); /** * 发送任务被分配的消息 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java index 90c47763..6243a81c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java @@ -1,18 +1,19 @@ package cn.iocoder.yudao.module.bpm.service.message; import cn.iocoder.yudao.framework.web.config.WebProperties; -import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert; -import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum; import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; +import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; +import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; import cn.iocoder.yudao.module.system.api.sms.SmsSendApi; import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.RuntimeService; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.HashMap; import java.util.Map; /** @@ -30,9 +31,15 @@ public class BpmMessageServiceImpl implements BpmMessageService { @Resource private WebProperties webProperties; - + @Resource + @Lazy + private NotifyMessageSendApi notifyMessageSendApi; + @Resource + @Lazy + private RuntimeService runtimeService; @Override public void sendMessageWhenProcessInstanceApprove(BpmMessageSendWhenProcessInstanceApproveReqDTO reqDTO) { + sendNotifyMessage(reqDTO.getProcessInstanceId(), reqDTO.getStartUserId(), "_PASS", null); // Map templateParams = new HashMap<>(); // templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); // templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); @@ -41,7 +48,8 @@ public class BpmMessageServiceImpl implements BpmMessageService { } @Override - public void sendMessageWhenProcessInstanceReject(BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO) { + public void sendMessageWhenProcessInstanceReject(BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO, Map variables) { + sendNotifyMessage(reqDTO.getProcessInstanceId(), reqDTO.getStartUserId(), "_NOPASS",variables); // Map templateParams = new HashMap<>(); // templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); // templateParams.put("reason", reqDTO.getReason()); @@ -52,6 +60,7 @@ public class BpmMessageServiceImpl implements BpmMessageService { @Override public void sendMessageWhenTaskAssigned(BpmMessageSendWhenTaskCreatedReqDTO reqDTO) { +// sendNotifyMessage(reqDTO.getProcessInstanceId(), reqDTO.getStartUserId(), "_UNDEAL", null); // Map templateParams = new HashMap<>(); // templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); // templateParams.put("taskName", reqDTO.getTaskName()); @@ -61,6 +70,23 @@ public class BpmMessageServiceImpl implements BpmMessageService { // BpmMessageEnum.TASK_ASSIGNED.getSmsTemplateCode(), templateParams)); } + private void sendNotifyMessage(String reqDTO, Long reqDTO1, String type, Map variables) { + if (variables == null) { + variables = runtimeService.getVariables(reqDTO); + } + if (variables.containsKey("billType")) { + String billType = variables.get("billType").toString(); + NotifySendSingleToUserReqDTO notifyReq = new NotifySendSingleToUserReqDTO(); + notifyReq.setUserId(reqDTO1); + notifyReq.setTemplateCode(billType+ type); + notifyReq.setTemplateParams(variables); + notifyReq.setBillType(billType); + notifyReq.setExtraData(variables); + notifyReq.setJumpFlag("1"); + notifyMessageSendApi.sendSingleMessageToAdmin(notifyReq); + } + } + private String getProcessInstanceDetailUrl(String taskId) { return webProperties.getAdminUi().getUrl() + "/bpm/process-instance/detail?id=" + taskId; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 325bf4c9..60ad0d93 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -1 +1 @@ -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).processInstanceTenantId(TenantContextHolder.getTenantId().toString()).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).processInstanceTenantId(TenantContextHolder.getTenantId().toString()).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).processInstanceTenantId(TenantContextHolder.getTenantId().toString()).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).processInstanceTenantId(TenantContextHolder.getTenantId().toString()).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 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(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .tenantId(TenantContextHolder.getTenantId().toString()) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); return instance.getId(); } } \ No newline at end of file +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).processInstanceTenantId(TenantContextHolder.getTenantId().toString()).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).processInstanceTenantId(TenantContextHolder.getTenantId().toString()).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).processInstanceTenantId(TenantContextHolder.getTenantId().toString()).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).processInstanceTenantId(TenantContextHolder.getTenantId().toString()).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 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(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); Map variables = runtimeService.getVariables(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason),variables); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .tenantId(TenantContextHolder.getTenantId().toString()) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); return instance.getId(); } } \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 44c91ebe..d99fcf48 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -22,10 +22,13 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; +import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; +import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.runtime.ProcessInstance; @@ -33,6 +36,7 @@ import org.flowable.task.api.Task; import org.flowable.task.api.TaskQuery; import org.flowable.task.api.history.HistoricTaskInstance; import org.flowable.task.api.history.HistoricTaskInstanceQuery; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; @@ -74,7 +78,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { private BpmTaskExtMapper taskExtMapper; @Resource private BpmMessageService messageService; - + @Resource + @Lazy + private RuntimeService runtimeService; + @Resource + @Lazy + private NotifyMessageSendApi notifyMessageSendApi; @Override public PageResult getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) { // 查询待办任务 @@ -253,6 +262,18 @@ public class BpmTaskServiceImpl implements BpmTaskService { BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); taskExtMapper.insert(taskExtDO); + Map variables = runtimeService.getVariables(task.getProcessInstanceId()); + if (variables.containsKey("billType")) { + String billType = variables.get("billType").toString(); + NotifySendSingleToUserReqDTO notifyReq = new NotifySendSingleToUserReqDTO(); + notifyReq.setUserId(taskExtDO.getAssigneeUserId()); + notifyReq.setTemplateCode(billType + "_UNDEAL"); + notifyReq.setTemplateParams(variables); + notifyReq.setBillType(billType); + notifyReq.setExtraData(variables); + notifyReq.setJumpFlag("1"); + notifyMessageSendApi.sendSingleMessageToAdmin(notifyReq); + } } @Override diff --git a/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/BillTypeEnum.java b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/BillTypeEnum.java index 9f3dfd50..feb61999 100644 --- a/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/BillTypeEnum.java +++ b/yudao-module-bs/yudao-module-bs-api/src/main/java/cn/iocoder/yudao/module/bs/enums/BillTypeEnum.java @@ -31,5 +31,12 @@ public enum BillTypeEnum { */ private final String name; - + public static String getNameByValue(String targetValue) { + for (BillTypeEnum billTypeEnum : BillTypeEnum.values()) { + if (billTypeEnum.getValue().equals(targetValue)) { + return billTypeEnum.getName(); + } + } + return null; + } } diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/suppliercompany/SupplierCompanyDO.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/suppliercompany/SupplierCompanyDO.java index 80723f63..4d492e22 100644 --- a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/suppliercompany/SupplierCompanyDO.java +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/dal/dataobject/suppliercompany/SupplierCompanyDO.java @@ -99,6 +99,12 @@ public class SupplierCompanyDO extends BaseDO { * 关联账号id */ private Long correlationUserId; + + /** + * 多租户编号 + */ + private Long tenantId; + /** * 附件 */ diff --git a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/suppliercompany/SupplierCompanyServiceImpl.java b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/suppliercompany/SupplierCompanyServiceImpl.java index 04dbf733..f79d4b50 100644 --- a/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/suppliercompany/SupplierCompanyServiceImpl.java +++ b/yudao-module-bs/yudao-module-bs-biz/src/main/java/cn/iocoder/yudao/module/bs/service/suppliercompany/SupplierCompanyServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.bs.service.suppliercompany; import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.UserCreateReqDTO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -32,6 +34,9 @@ public class SupplierCompanyServiceImpl implements SupplierCompanyService { @Resource private SupplierCompanyMapper supplierCompanyMapper; + @Resource + private AdminUserApi adminUserApi; + @Override public Long createSupplierCompany(SupplierCompanyCreateReqVO createReqVO) { @@ -40,7 +45,13 @@ public class SupplierCompanyServiceImpl implements SupplierCompanyService { String companyNumber = numberCreate(); supplierCompany.setCompanyNumber(companyNumber); supplierCompanyMapper.insert(supplierCompany); - + UserCreateReqDTO userCreateReqDTO=new UserCreateReqDTO(); + userCreateReqDTO.setPassword("123456Aa@"); + userCreateReqDTO.setUsername(supplierCompany.getPhone()); + userCreateReqDTO.setNickname(supplierCompany.getBankName()); + userCreateReqDTO.setMobile(supplierCompany.getPhone()); +// userCreateReqDTO.setTenantId(supplierCompany.getCompanyNumber()); + adminUserApi.addUser(userCreateReqDTO); // 返回 return supplierCompany.getId(); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/notify/dto/NotifySendSingleToUserReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/notify/dto/NotifySendSingleToUserReqDTO.java index 502d3eb3..b3e03559 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/notify/dto/NotifySendSingleToUserReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/notify/dto/NotifySendSingleToUserReqDTO.java @@ -30,4 +30,18 @@ public class NotifySendSingleToUserReqDTO { * 站内信模板参数 */ private Map templateParams; + + /** + * 单据类型 + */ + private String billType; + /** + * 扩展数据,比如单据ID + */ + private Map extraData; + + /** + * 是否需跳转 + */ + private String jumpFlag = "0"; } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java index 35e11f02..cb8cdc52 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.api.user; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.system.api.user.dto.UserCreateReqDTO; import java.util.Collection; import java.util.List; @@ -66,4 +67,10 @@ public interface AdminUserApi { */ void validateUserList(Collection ids); + /** + * 建好供应商信息后新建账号 + * @param createReqVO + */ + void addUser(UserCreateReqDTO createReqVO); + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/UserCreateReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/UserCreateReqDTO.java new file mode 100644 index 00000000..b3d8b697 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/UserCreateReqDTO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.system.api.user.dto; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import java.util.Set; + + +@Data +public class UserCreateReqDTO { + + @NotBlank(message = "用户账号不能为空") + @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成") + @Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符") + private String username; + + @Size(max = 30, message = "用户昵称长度不能超过30个字符") + private String nickname; + + private String remark; + + private Long deptId; + + private Set postIds; + + @Email(message = "邮箱格式不正确") + @Size(max = 50, message = "邮箱长度不能超过 50 个字符") + private String email; + + @Mobile + private String mobile; + + private Integer sex; + + private String avatar; + + private String password; + + /** + * 多租户编号 + */ +// private Long tenantId; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/notify/NotifyMessageSendApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/notify/NotifyMessageSendApiImpl.java index fc5ba1d1..ca5ce5d5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/notify/NotifyMessageSendApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/notify/NotifyMessageSendApiImpl.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.system.api.notify; import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; -import cn.iocoder.yudao.module.system.service.notify.NotifyMessageService; import cn.iocoder.yudao.module.system.service.notify.NotifySendService; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.HashMap; /** * 站内信发送 API 实现类 @@ -21,7 +21,7 @@ public class NotifyMessageSendApiImpl implements NotifyMessageSendApi { @Override public Long sendSingleMessageToAdmin(NotifySendSingleToUserReqDTO reqDTO) { return notifySendService.sendSingleNotifyToAdmin(reqDTO.getUserId(), - reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); + reqDTO.getTemplateCode(), reqDTO.getTemplateParams(), reqDTO.getBillType(), reqDTO.getExtraData(), reqDTO.getJumpFlag()); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java index 2271420c..656b572f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.module.system.api.user; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.system.api.user.dto.UserCreateReqDTO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserCreateReqVO; import cn.iocoder.yudao.module.system.convert.user.UserConvert; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -50,4 +53,11 @@ public class AdminUserApiImpl implements AdminUserApi { userService.validateUserList(ids); } + @Override + public void addUser(UserCreateReqDTO createReqVO) { + + UserCreateReqVO reqVO = new UserCreateReqVO(); + BeanUtils.copyProperties(createReqVO, reqVO); + userService.createUser(reqVO); + } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java index 0299836d..15d77eb0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java @@ -17,6 +17,8 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.HashMap; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - 站内信模版") @@ -77,7 +79,7 @@ public class NotifyTemplateController { @PreAuthorize("@ss.hasPermission('system:notify-template:send-notify')") public CommonResult sendNotify(@Valid @RequestBody NotifyTemplateSendReqVO sendReqVO) { return success(notifySendService.sendSingleNotifyToAdmin(sendReqVO.getUserId(), - sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams())); + sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams(), null, new HashMap(), "0")); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java index 8e4b3fd0..8ef1427c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java @@ -56,5 +56,28 @@ public class NotifyMessageBaseVO { @Schema(description = "阅读时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime readTime; - + /** + * 消息开始时间 + */ + private LocalDateTime startTime; + /** + * 截止时间 + */ + private LocalDateTime endTime; + /** + * 业务类型 + */ + private String billType; + /** + * 单据ID + */ + private Long billId; + /** + * 扩展数据,比如单据ID + */ + private Map extraData; + /** + * 是否需跳转 + */ + private String jumpFlag; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notify/NotifyMessageDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notify/NotifyMessageDO.java index e73badf2..dfa32af4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notify/NotifyMessageDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notify/NotifyMessageDO.java @@ -97,5 +97,30 @@ public class NotifyMessageDO extends BaseDO { * 阅读时间 */ private LocalDateTime readTime; + /** + * 消息开始时间 + */ + private LocalDateTime startTime; + /** + * 截止时间 + */ + private LocalDateTime endTime; + /** + * 业务类型 + */ + private String billType; + /** + * 单据ID + */ + private Long billId; + /** + * 扩展数据,比如单据ID + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private Map extraData; + /** + * 是否需跳转 + */ + private String jumpFlag; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageService.java index b06aef32..0fa567f7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO; import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -25,10 +26,13 @@ public interface NotifyMessageService { * @param template 模版信息 * @param templateContent 模版内容 * @param templateParams 模版参数 + * @param billType + * @param extraData + * @param jumpFlag * @return 站内信编号 */ Long createNotifyMessage(Long userId, Integer userType, - NotifyTemplateDO template, String templateContent, Map templateParams); + NotifyTemplateDO template, String templateContent, Map templateParams, String billType, Map extraData, String jumpFlag); /** * 获得站内信分页 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageServiceImpl.java index 3abcebcf..bc0df9c8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.system.service.notify; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.yudao.module.system.controller.admin.notify.vo.message.NotifyMessageMyPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.notify.vo.message.NotifyMessagePageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO; @@ -10,7 +12,9 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,12 +34,24 @@ public class NotifyMessageServiceImpl implements NotifyMessageService { @Override public Long createNotifyMessage(Long userId, Integer userType, - NotifyTemplateDO template, String templateContent, Map templateParams) { + NotifyTemplateDO template, String templateContent, Map templateParams, String billType, Map extraData, String jumpFlag) { NotifyMessageDO message = new NotifyMessageDO().setUserId(userId).setUserType(userType) .setTemplateId(template.getId()).setTemplateCode(template.getCode()) .setTemplateType(template.getType()).setTemplateNickname(template.getNickname()) - .setTemplateContent(templateContent).setTemplateParams(templateParams).setReadStatus(false); + .setTemplateContent(templateContent).setTemplateParams(templateParams).setReadStatus(false).setBillType(billType).setStartTime(LocalDateTime.now()).setExtraData(extraData).setJumpFlag(jumpFlag); + if (extraData.containsKey("billId")) { + message.setBillId(Long.valueOf(extraData.get("billId").toString())); + } notifyMessageMapper.insert(message); + if (billType != null && (template.getCode().contains("_PASS") || template.getCode().contains("_NOPASS"))) { + //如果同意和驳回需要将先前的待办删除 + if (extraData.containsKey("billId")) { + LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); + queryWrapperX.eqIfPresent(NotifyMessageDO::getBillId, Long.valueOf(extraData.get("billId").toString())); + queryWrapperX.eqIfPresent(NotifyMessageDO::getTemplateCode, billType + "_UNDEAL"); + notifyMessageMapper.delete(queryWrapperX); + } + } return message.getId(); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendService.java index f4a8d4f4..5264803c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendService.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.service.notify; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -18,10 +19,13 @@ public interface NotifySendService { * @param userId 用户编号 * @param templateCode 短信模板编号 * @param templateParams 短信模板参数 + * @param billType + * @param extraData + * @param jumpFlag * @return 发送日志编号 */ Long sendSingleNotifyToAdmin(Long userId, - String templateCode, Map templateParams); + String templateCode, Map templateParams, String billType, Map extraData, String jumpFlag); /** * 发送单条站内信给用户 APP 的用户 * @@ -42,10 +46,13 @@ public interface NotifySendService { * @param userType 用户类型 * @param templateCode 站内信模板编号 * @param templateParams 站内信模板参数 + * @param billType + * @param extraData + * @param jumpFlag * @return 发送日志编号 */ - Long sendSingleNotify( Long userId, Integer userType, - String templateCode, Map templateParams); + Long sendSingleNotify(Long userId, Integer userType, + String templateCode, Map templateParams, String billType, Map extraData, String jumpFlag); default void sendBatchNotify(List mobiles, List userIds, Integer userType, String templateCode, Map templateParams) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImpl.java index f71c5fe5..fe4b7843 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImpl.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -32,17 +33,16 @@ public class NotifySendServiceImpl implements NotifySendService { private NotifyMessageService notifyMessageService; @Override - public Long sendSingleNotifyToAdmin(Long userId, String templateCode, Map templateParams) { - return sendSingleNotify(userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams); + public Long sendSingleNotifyToAdmin(Long userId, String templateCode, Map templateParams, String billType, Map extraData, String jumpFlag) { + return sendSingleNotify(userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams, billType, extraData, jumpFlag); } @Override public Long sendSingleNotifyToMember(Long userId, String templateCode, Map templateParams) { - return sendSingleNotify(userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams); + return sendSingleNotify(userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams, null, new HashMap(), "0"); } - @Override - public Long sendSingleNotify(Long userId, Integer userType, String templateCode, Map templateParams) { + public Long sendSingleNotify(Long userId, Integer userType, String templateCode, Map templateParams, String billType, Map extraData, String jumpFlag) { // 校验模版 NotifyTemplateDO template = validateNotifyTemplate(templateCode); if (Objects.equals(template.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { @@ -54,7 +54,7 @@ public class NotifySendServiceImpl implements NotifySendService { // 发送站内信 String content = notifyTemplateService.formatNotifyTemplateContent(template.getContent(), templateParams); - return notifyMessageService.createNotifyMessage(userId, userType, template, content, templateParams); + return notifyMessageService.createNotifyMessage(userId, userType, template, content, templateParams, billType, extraData, jumpFlag); } @VisibleForTesting diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageServiceImplTest.java index 9e2158da..2ae30482 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyMessageServiceImplTest.java @@ -15,10 +15,7 @@ import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; @@ -54,7 +51,7 @@ public class NotifyMessageServiceImplTest extends BaseDbUnitTest { // 调用 Long messageId = notifyMessageService.createNotifyMessage(userId, userType, - template, templateContent, templateParams); + template, templateContent, templateParams, "xx", new HashMap(), "xxx"); // 断言 NotifyMessageDO message = notifyMessageMapper.selectById(messageId); assertNotNull(message); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImplTest.java index 7c507833..7f105e83 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImplTest.java @@ -53,10 +53,10 @@ class NotifySendServiceImplTest extends BaseMockitoUnitTest { // mock NotifyMessageService 的方法 Long messageId = randomLongId(); when(notifyMessageService.createNotifyMessage(eq(userId), eq(UserTypeEnum.ADMIN.getValue()), - eq(template), eq(content), eq(templateParams))).thenReturn(messageId); + eq(template), eq(content), eq(templateParams), "xx", new HashMap(), "xxx")).thenReturn(messageId); // 调用 - Long resultMessageId = notifySendService.sendSingleNotifyToAdmin(userId, templateCode, templateParams); + Long resultMessageId = notifySendService.sendSingleNotifyToAdmin(userId, templateCode, templateParams, null, new HashMap(), "0"); // 断言 assertEquals(messageId, resultMessageId); } @@ -81,7 +81,7 @@ class NotifySendServiceImplTest extends BaseMockitoUnitTest { // mock NotifyMessageService 的方法 Long messageId = randomLongId(); when(notifyMessageService.createNotifyMessage(eq(userId), eq(UserTypeEnum.MEMBER.getValue()), - eq(template), eq(content), eq(templateParams))).thenReturn(messageId); + eq(template), eq(content), eq(templateParams), "xx", new HashMap(), "xxx")).thenReturn(messageId); // 调用 Long resultMessageId = notifySendService.sendSingleNotifyToMember(userId, templateCode, templateParams); @@ -113,10 +113,10 @@ class NotifySendServiceImplTest extends BaseMockitoUnitTest { // mock NotifyMessageService 的方法 Long messageId = randomLongId(); when(notifyMessageService.createNotifyMessage(eq(userId), eq(userType), - eq(template), eq(content), eq(templateParams))).thenReturn(messageId); + eq(template), eq(content), eq(templateParams), "xx", new HashMap(), "xxx")).thenReturn(messageId); // 调用 - Long resultMessageId = notifySendService.sendSingleNotify(userId, userType, templateCode, templateParams); + Long resultMessageId = notifySendService.sendSingleNotify(userId, userType, templateCode, templateParams, "xx", new HashMap(), "xxx"); // 断言 assertEquals(messageId, resultMessageId); } @@ -141,11 +141,11 @@ class NotifySendServiceImplTest extends BaseMockitoUnitTest { when(notifyTemplateService.getNotifyTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); // 调用 - Long resultMessageId = notifySendService.sendSingleNotify(userId, userType, templateCode, templateParams); + Long resultMessageId = notifySendService.sendSingleNotify(userId, userType, templateCode, templateParams, "xx", new HashMap(), "xxx"); // 断言 assertNull(resultMessageId); verify(notifyTemplateService, never()).formatNotifyTemplateContent(anyString(), anyMap()); - verify(notifyMessageService, never()).createNotifyMessage(anyLong(), anyInt(), any(), anyString(), anyMap()); + verify(notifyMessageService, never()).createNotifyMessage(anyLong(), anyInt(), any(), anyString(), anyMap(), "xx", new HashMap(), "xxx"); } @Test