Ver Fonte

重构工作流(5)

zhouhao há 6 anos atrás
pai
commit
c2e07d9f9e
22 ficheiros alterados com 787 adições e 398 exclusões
  1. 6 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/pom.xml
  2. 2 1
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java
  3. 4 7
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/flowable/utils/CustomUserEntityManager.java
  4. 4 12
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/ActivityConfigurationService.java
  5. 0 9
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/BpmProcessService.java
  6. 40 38
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/BpmTaskService.java
  7. 16 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/WorkFlowFormService.java
  8. 9 7
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/dto/ActivityCandidateInfo.java
  9. 16 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/dto/ActivityConfiguration.java
  10. 11 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/dto/ProcessConfiguration.java
  11. 51 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/ActivityConfigurationServiceImpl.java
  12. 1 1
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmActivityServiceImp.java
  13. 0 137
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmProcessServiceImp.java
  14. 158 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmProcessServiceImpl.java
  15. 96 104
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmTaskServiceImp.java
  16. 94 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/WorkFlowFormServiceImpl.java
  17. 10 3
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/request/CompleteTaskRequest.java
  18. 30 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/request/SaveFormRequest.java
  19. 6 4
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/request/StartProcessRequest.java
  20. 75 75
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/web/FlowableCoreController.java
  21. 82 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/test/java/org/hswebframework/web/workflow/flowable/WorkFlowProcessTests.groovy
  22. 76 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/test/resources/processes/SimpleProcess.bpmn20.xml

+ 6 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/pom.xml

@@ -123,6 +123,12 @@
             <artifactId>hsweb-system-dynamic-form-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-dynamic-form-starter</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
 
         <dependency>
             <groupId>io.vavr</groupId>

+ 2 - 1
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java

@@ -12,6 +12,7 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.PlatformTransactionManager;
 
 import java.util.List;
 
@@ -26,7 +27,7 @@ public class FlowableAutoConfiguration {
     private List<SessionFactory> sessionFactories;
 
     @Bean
-    public ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer() {
+    public ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer(PlatformTransactionManager transactionManager) {
         return configuration -> {
             configuration
                     .setAsyncExecutorActivate(false)

+ 4 - 7
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/flowable/utils/CustomUserEntityManager.java

@@ -12,6 +12,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.dao.EmptyResultDataAccessException;
 
+import java.util.Collections;
 import java.util.List;
 
 public class CustomUserEntityManager extends UserEntityManager {
@@ -28,18 +29,14 @@ public class CustomUserEntityManager extends UserEntityManager {
         if (userId == null) {
             return null;
         }
-        try {
-            org.hswebframework.web.entity.authorization.UserEntity user = userService.selectByPk(userId);
-            return ActivitiUserUtil.toActivitiUser(user);
-        } catch (EmptyResultDataAccessException e) {
-            return null;
-        }
+        org.hswebframework.web.entity.authorization.UserEntity user = userService.selectByPk(userId);
+        return ActivitiUserUtil.toActivitiUser(user);
     }
 
     @Override
     public List<Group> findGroupsByUser(final String userId) {
         if (userId == null) {
-            return null;
+            return Collections.emptyList();
         }
 
         List<RoleEntity> sysRoles = userService.getUserRole(userId);

+ 4 - 12
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/ActivityConfigurationService.java

@@ -1,20 +1,12 @@
 package org.hswebframework.web.workflow.service;
 
-import org.hswebframework.web.workflow.service.dto.ActivityCandidateInfo;
-
-import java.util.List;
+import org.hswebframework.web.workflow.service.dto.ActivityConfiguration;
+import org.hswebframework.web.workflow.service.dto.ProcessConfiguration;
 
 public interface ActivityConfigurationService {
 
-    /**
-     * 获取一个流程环节的办理候选人
-     *
-     * @param doingUserId     当前办理用户ID
-     * @param processDefineId 流程定义ID
-     * @param activityId      环节Id
-     * @return 该环节的候选人, 如果没有候选人则返回空集合.不会返回null
-     */
-    List<ActivityCandidateInfo> getCandidate(String doingUserId, String processDefineId, String activityId);
+    ActivityConfiguration getActivityConfiguration(String doingUser, String processDefineId, String activityId);
 
+    ProcessConfiguration getProcessConfiguration(String processDefineId);
 
 }

+ 0 - 9
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/BpmProcessService.java

@@ -29,15 +29,6 @@ public interface BpmProcessService{
      */
     ProcessInstance startProcessInstance(StartProcessRequest request);
 
-    /**
-     * 根据流程图key获取所有运行中流程分页
-     * @param page
-     * @param num
-     * @param procDefKey
-     * @return
-     */
-    List<ProcessInstance> getProcessInstances(int page, int num, String procDefKey);
-
     /**
      * 流程实例挂起
      * @param procInstId 流程实例ID

+ 40 - 38
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/BpmTaskService.java

@@ -3,6 +3,7 @@ package org.hswebframework.web.workflow.service;
 import org.activiti.engine.history.HistoricProcessInstance;
 import org.activiti.engine.impl.pvm.process.ActivityImpl;
 import org.activiti.engine.task.Task;
+import org.hswebframework.web.workflow.service.request.CompleteTaskRequest;
 
 import java.util.Collection;
 import java.util.List;
@@ -10,10 +11,11 @@ import java.util.Map;
 
 /**
  * 流程任务操作相关接口
+ *
  * @Author wangwei
  * @Date 2017/8/4.
  */
-public interface BpmTaskService{
+public interface BpmTaskService {
 
     List<Task> selectNowTask(String procInstId);
 
@@ -21,14 +23,19 @@ public interface BpmTaskService{
 
     Task selectTaskByTaskId(String taskId);
 
-    String selectNowTaskName(String procInstId);
-
-    String selectNowTaskId(String procInstId);
-
     HistoricProcessInstance selectHisProInst(String procInstId);
 
+    /**
+     * 设置任务办理的候选人
+     *
+     * @param doingUserId 当前操作人
+     * @param task        任务
+     */
+    void setCandidate(String doingUserId, Task task);
+
     /**
      * 获取环节变量
+     *
      * @param taskId
      * @return
      */
@@ -36,6 +43,7 @@ public interface BpmTaskService{
 
     /**
      * 获取环节变量
+     *
      * @param taskId
      * @param variableName
      * @return
@@ -44,6 +52,7 @@ public interface BpmTaskService{
 
     /**
      * 根据taskId获取流程图对应的图元
+     *
      * @param taskId
      * @return
      */
@@ -78,83 +87,75 @@ public interface BpmTaskService{
     List<Task> todoList(String userId);
 
     /**
-     * 完成任务(环节)并指定下一环节办理人
+     * 完成任务
      *
-     * @param taskId    任务id
-     * @param userId    当前办理人用户id
-     * @param activityId 人为指定下一执行环节(预留)
-     * @param next_claim 人为指定下一步执行人(预留)
-     * @throws Exception 异常信息
+     * @param request 完成任务请求
      */
-    void complete(String taskId, String userId, String activityId, String next_claim);
+    void complete(CompleteTaskRequest request);
 
     /**
      * 流程任意跳转
-     * @param procInstId  流程实例ID
-     * @param activity           流程环节ID
-     * @param next_claim         人为指定下一步执行人(预留)
+     *
+     * @param procInstId 流程实例ID
+     * @param activity   流程环节ID
      */
-    void jumpTask(String procInstId, String activity, String next_claim);
+    Task jumpTask(String procInstId, String activity);
 
     /**
      * 驳回
+     *
      * @param taskId
      */
     void reject(String taskId);
 
-    /**
-     * 设置待办人
-     *
-     * @param taskId   当前环节ID
-     * @param actId   当前环节图元ID
-     * @param userId 用户ID
-     */
-    void addCandidateUser(String taskId, String actId, String userId);
-
     /**
      * 设置办理人
      *
-     * @param taskId   当前环节ID
+     * @param taskId 当前环节ID
      * @param userId 用户ID
      */
     void setAssignee(String taskId, String userId);
 
     /**
      * 结束流程
-     * @param procInstId   流程实例ID
+     *
+     * @param procInstId 流程实例ID
      */
     void endProcess(String procInstId);
 
     /**
      * 删除历史环节信息
-     * @param taskId  环节ID
+     *
+     * @param taskId 环节ID
      */
     void removeHiTask(String taskId);
 
     /**
      * 获取所有任务节点
-     * @param procDefKey  流程定义Key,该参数获取最新流程
+     *
+     * @param procDefKey 流程定义Key,该参数获取最新流程
      */
-    Map<String,Object> getUserTasksByProcDefKey(String procDefKey);
+    Map<String, Object> getUserTasksByProcDefKey(String procDefKey);
 
     /**
      * 获取所有任务节点
-     * @param procInstId            流程实例ID,该参数获取当前流程实例对应流程
+     *
+     * @param procInstId 流程实例ID,该参数获取当前流程实例对应流程
      */
-    Map<String,Object> getUserTasksByProcInstId(String procInstId);
+    Map<String, Object> getUserTasksByProcInstId(String procInstId);
 
     /**
      * 设置流程变量
      *
-     * @param taskId   当前环节ID
-     * @param map   key-value
+     * @param taskId 当前环节ID
+     * @param map    key-value
      */
     void setVariables(String taskId, Map<String, Object> map);
 
     /**
      * 删除流程变量
      *
-     * @param taskId   当前环节ID
+     * @param taskId 当前环节ID
      * @param var2   需要删除的 key
      */
     void removeVariables(String taskId, Collection<String> var2);
@@ -162,7 +163,7 @@ public interface BpmTaskService{
     /**
      * 设置任务变量
      *
-     * @param taskId   当前环节ID
+     * @param taskId 当前环节ID
      */
     void setVariablesLocal(String taskId, Map<String, Object> map);
 
@@ -170,12 +171,13 @@ public interface BpmTaskService{
      * 获取流程变量
      * @param procInstId  流程实例ID
      */
-    Map<String,Object> getVariablesByProcInstId(String procInstId);
+    Map<String, Object> getVariablesByProcInstId(String procInstId);
 
     /**
      * 获取流程变量
+     *
      * @param taskId
      * @return
      */
-    Map<String,Object> getVariablesByTaskId(String taskId);
+    Map<String, Object> getVariablesByTaskId(String taskId);
 }

+ 16 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/WorkFlowFormService.java

@@ -0,0 +1,16 @@
+package org.hswebframework.web.workflow.service;
+
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Task;
+import org.hswebframework.web.workflow.service.request.SaveFormRequest;
+
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+public interface WorkFlowFormService {
+    void saveProcessForm(ProcessInstance instance, SaveFormRequest request);
+
+    void saveTaskForm(Task task,SaveFormRequest request);
+}

+ 9 - 7
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/dto/ActivityCandidateInfo.java

@@ -1,14 +1,16 @@
 package org.hswebframework.web.workflow.service.dto;
 
-import lombok.Getter;
-import lombok.Setter;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.organizational.authorization.PersonnelAuthentication;
 
-@Getter
-@Setter
-public class ActivityCandidateInfo {
-    private Authentication user;
+public interface ActivityCandidateInfo {
+    /**
+     * 候选人的用户授权信息
+     */
+    Authentication user();
 
-    private PersonnelAuthentication person;
+    /**
+     * 候选人的组织架构人员信息
+     */
+    PersonnelAuthentication person();
 }

+ 16 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/dto/ActivityConfiguration.java

@@ -0,0 +1,16 @@
+package org.hswebframework.web.workflow.service.dto;
+
+import java.util.List;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+public interface ActivityConfiguration {
+    String getFormId();
+
+    boolean canClaim(String userId);
+
+    List<ActivityCandidateInfo> getCandidateInfo();
+
+}

+ 11 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/dto/ProcessConfiguration.java

@@ -0,0 +1,11 @@
+package org.hswebframework.web.workflow.service.dto;
+
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+public interface ProcessConfiguration {
+    String getFormId();
+
+}

+ 51 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/ActivityConfigurationServiceImpl.java

@@ -0,0 +1,51 @@
+package org.hswebframework.web.workflow.service.imp;
+
+import org.hswebframework.web.workflow.service.ActivityConfigurationService;
+import org.hswebframework.web.workflow.service.dto.ActivityCandidateInfo;
+import org.hswebframework.web.workflow.service.dto.ActivityConfiguration;
+import org.hswebframework.web.workflow.service.dto.ProcessConfiguration;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+@Service
+public class ActivityConfigurationServiceImpl implements ActivityConfigurationService {
+
+    static final EmptyActivityConfiguration emptyConfiguration = new EmptyActivityConfiguration();
+
+    @Override
+    public ActivityConfiguration getActivityConfiguration(String doingUser, String processDefineId, String activityId) {
+
+        return emptyConfiguration;
+    }
+
+    @Override
+    public ProcessConfiguration getProcessConfiguration(String processDefineId) {
+
+        return emptyConfiguration;
+    }
+
+    private final static class EmptyActivityConfiguration implements ActivityConfiguration, ProcessConfiguration {
+
+        @Override
+        public String getFormId() {
+            return null;
+        }
+
+        @Override
+        public boolean canClaim(String userId) {
+            return false;
+        }
+
+        @Override
+        public List<ActivityCandidateInfo> getCandidateInfo() {
+            return Collections.emptyList();
+        }
+    }
+}

+ 1 - 1
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmActivityServiceImp.java

@@ -23,7 +23,7 @@ import java.util.stream.Collectors;
  * @Date 2017/8/7.
  */
 @Service
-public class BpmActivityServiceImp extends AbstractFlowableService implements BpmActivityService {
+public class BpmActivityServiceImpl extends AbstractFlowableService implements BpmActivityService {
 
     /**
      * 获取指定节点

+ 0 - 137
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmProcessServiceImp.java

@@ -1,137 +0,0 @@
-package org.hswebframework.web.workflow.service.imp;
-
-import org.activiti.engine.repository.ProcessDefinition;
-import org.activiti.engine.runtime.Job;
-import org.activiti.engine.runtime.ProcessInstance;
-import org.activiti.engine.task.Task;
-import org.hswebframework.utils.StringUtils;
-import org.hswebframework.web.workflow.service.BpmProcessService;
-import org.hswebframework.web.workflow.service.BpmTaskService;
-import org.hswebframework.web.workflow.service.request.StartProcessRequest;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.annotation.Resource;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @Author wangwei
- * @Date 2017/8/7.
- */
-@Service
-@Transactional(rollbackFor = Throwable.class)
-public class BpmProcessServiceImp extends AbstractFlowableService implements BpmProcessService {
-    protected Logger logger = LoggerFactory.getLogger(this.getClass());
-
-    @Resource
-   private BpmTaskService bpmTaskService;
-
-    @Override
-    public List<ProcessDefinition> getAllProcessDefinition() {
-        return repositoryService.createProcessDefinitionQuery().latestVersion().active().list();
-    }
-
-    @Override
-    public ProcessInstance startProcessInstance(StartProcessRequest request) {
-        request.tryValidate();
-
-
-
-        return null;
-    }
-
-    public ProcessInstance startProcessInstance(String creatorId,
-                                                String procDefKey,
-                                                String activity,
-                                                String nextClaim,
-                                                String businessKey,
-                                                Map<String, Object> variables){
-        logger.debug("start flow :{}", procDefKey);
-        ProcessInstance processInstance = null;
-        try{
-            // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中
-            identityService.setAuthenticatedUserId(creatorId);
-            logger.debug("流程启动,work_flow_key:{}", procDefKey);
-            logger.debug("表单ID,businessKey:{}",businessKey);
-            logger.debug("流程变量保存,variables:{}",variables);
-            //启动流程,返回流程实例
-            processInstance = runtimeService.startProcessInstanceByKey(procDefKey, businessKey, variables);
-            //获取流程实例ID
-            String processInstanceId = processInstance.getId();
-            logger.debug("流程启动成功,流程ID:{}",processInstanceId);
-            List<Task> tasks = bpmTaskService.selectTaskByProcessId(processInstanceId);
-            //如果指定了下一步执行环节,则将流程跳转到指定环节,并删除当前未执行的环节历史信息
-            if(!StringUtils.isNullOrEmpty(activity)){
-                bpmTaskService.jumpTask(processInstanceId,activity,StringUtils.isNullOrEmpty(nextClaim)?"":nextClaim);
-                for(Task task:tasks){
-                    bpmTaskService.removeHiTask(task.getId());
-                }
-            }else{
-                // 设置待办人(单环节并且设定办理人可直接签收)
-                if(tasks.size()==1 && !StringUtils.isNullOrEmpty(nextClaim)) {
-                    bpmTaskService.claim(tasks.get(0).getId(), nextClaim);
-                } else {
-                    for(Task task:tasks){
-                        bpmTaskService.addCandidateUser(task.getId(), task.getTaskDefinitionKey(), creatorId);
-                    }
-                }
-            }
-
-            if (logger.isDebugEnabled()) {
-                logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", procDefKey, businessKey, processInstanceId, variables);
-            }
-        }catch (Exception e){
-            logger.warn("工作流启动失败,请联系管理员!");
-        }finally {
-            identityService.setAuthenticatedUserId(null);
-        }
-        return processInstance;
-    }
-
-    @Override
-    public List<ProcessInstance> getProcessInstances(int page, int num, String procDefKey) {
-        return runtimeService.createProcessInstanceQuery().processDefinitionKey(procDefKey).listPage(page, num);
-    }
-
-    @Override
-    public void closeProcessInstance(String processInstanceId) {
-        runtimeService.suspendProcessInstanceById(processInstanceId);
-    }
-
-    @Override
-    public void openProcessInstance(String processInstanceId) {
-        runtimeService.activateProcessInstanceById(processInstanceId);
-    }
-
-    @Override
-    public ProcessDefinition getProcessDefinitionById(String processDefinitionId){
-        return repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
-    }
-
-    @Override
-    public ProcessDefinition getProcessDefinitionByKey(String procDefKey) {
-        return repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).orderByProcessDefinitionVersion().desc().list().get(0);
-    }
-
-    @Override
-    public InputStream findProcessPic(String procDefId) {
-        ProcessDefinition definition = getProcessDefinitionById(procDefId);
-        String source = definition.getDiagramResourceName();
-        return repositoryService.getResourceAsStream(definition.getDeploymentId(),source);
-    }
-
-    @Override
-    public Job getJob(String processInstanceId) {
-        return managementService.createJobQuery().processInstanceId(processInstanceId).singleResult();
-    }
-
-    @Override
-    public int deleteJob(String jobId) {
-        return 0;
-    }
-
-}

+ 158 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmProcessServiceImpl.java

@@ -0,0 +1,158 @@
+package org.hswebframework.web.workflow.service.imp;
+
+import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.runtime.Job;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Task;
+import org.hswebframework.utils.StringUtils;
+import org.hswebframework.web.id.IDGenerator;
+import org.hswebframework.web.service.form.DynamicFormOperationService;
+import org.hswebframework.web.workflow.service.ActivityConfigurationService;
+import org.hswebframework.web.workflow.service.BpmProcessService;
+import org.hswebframework.web.workflow.service.BpmTaskService;
+import org.hswebframework.web.workflow.service.WorkFlowFormService;
+import org.hswebframework.web.workflow.service.dto.ActivityCandidateInfo;
+import org.hswebframework.web.workflow.service.request.SaveFormRequest;
+import org.hswebframework.web.workflow.service.request.StartProcessRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ * @Author wangwei
+ * @Date 2017/8/7.
+ */
+@Service
+@Transactional(rollbackFor = Throwable.class)
+public class BpmProcessServiceImpl extends AbstractFlowableService implements BpmProcessService {
+    protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private BpmTaskService bpmTaskService;
+
+    @Autowired
+    private WorkFlowFormService workFlowFormService;
+
+    @Override
+    public List<ProcessDefinition> getAllProcessDefinition() {
+        return repositoryService.createProcessDefinitionQuery().latestVersion().active().list();
+    }
+
+    @Override
+    public ProcessInstance startProcessInstance(StartProcessRequest request) {
+        request.tryValidate();
+        ProcessInstance processInstance;
+        logger.debug("start workflow :{}", request);
+        try {
+            identityService.setAuthenticatedUserId(request.getCreatorId());
+
+            //创建业务ID
+            String businessKey = IDGenerator.MD5.generate();
+
+            //启动流程
+            processInstance = runtimeService.startProcessInstanceById(
+                    request.getProcessDefineId()
+                    , businessKey
+                    , request.getVariables());
+
+            //候选人设置
+            Consumer<Task> candidateUserSetter = (task) -> {
+                if (task == null) {
+                    return;
+                }
+                //指定了下一环节的办理人
+                if (!StringUtils.isNullOrEmpty(request.getNextClaimUserId())) {
+                    taskService.addCandidateUser(task.getId(), request.getNextClaimUserId());
+                } else {
+                    bpmTaskService.setCandidate(request.getCreatorId(), task);
+                }
+            };
+
+            List<Task> tasks = bpmTaskService.selectTaskByProcessId(processInstance.getProcessDefinitionId());
+
+            //指定了下一环节
+            if (!StringUtils.isNullOrEmpty(request.getNextActivityId())) {
+                //跳转
+                Task afterJump = bpmTaskService.jumpTask(processInstance.getProcessDefinitionId(), request.getNextActivityId());
+
+                //设置候选人
+                candidateUserSetter.accept(afterJump);
+
+                tasks.stream()
+                        .map(Task::getId)
+                        .forEach(bpmTaskService::removeHiTask);
+            } else {
+                //当前节点
+                String activityId = processInstance.getActivityId();
+                if (activityId == null) {
+                    //所有task设置候选人
+                    tasks.forEach(candidateUserSetter);
+                } else {
+                    candidateUserSetter.accept(taskService
+                            .createTaskQuery()
+                            .processInstanceId(processInstance.getProcessInstanceId())
+                            .taskDefinitionKey(activityId)
+                            .active()
+                            .singleResult());
+                }
+            }
+
+            workFlowFormService.saveProcessForm(processInstance, SaveFormRequest
+                    .builder()
+                    .userId(request.getCreatorId())
+                    .userName(request.getCreatorName())
+                    .formData(request.getFormData())
+                    .build());
+        } finally {
+            identityService.setAuthenticatedUserId(null);
+        }
+        return processInstance;
+    }
+
+    @Override
+    public void closeProcessInstance(String processInstanceId) {
+        runtimeService.suspendProcessInstanceById(processInstanceId);
+    }
+
+    @Override
+    public void openProcessInstance(String processInstanceId) {
+        runtimeService.activateProcessInstanceById(processInstanceId);
+    }
+
+    @Override
+    public ProcessDefinition getProcessDefinitionById(String processDefinitionId) {
+        return repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
+    }
+
+    @Override
+    public ProcessDefinition getProcessDefinitionByKey(String procDefKey) {
+        return repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).orderByProcessDefinitionVersion().desc().list().get(0);
+    }
+
+    @Override
+    public InputStream findProcessPic(String procDefId) {
+        ProcessDefinition definition = getProcessDefinitionById(procDefId);
+        String source = definition.getDiagramResourceName();
+        return repositoryService.getResourceAsStream(definition.getDeploymentId(), source);
+    }
+
+    @Override
+    public Job getJob(String processInstanceId) {
+        return managementService.createJobQuery().processInstanceId(processInstanceId).singleResult();
+    }
+
+    @Override
+    public int deleteJob(String jobId) {
+        return 0;
+    }
+
+}

+ 96 - 104
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmTaskServiceImp.java

@@ -14,10 +14,16 @@ import org.activiti.engine.runtime.Execution;
 import org.activiti.engine.runtime.ProcessInstance;
 import org.activiti.engine.task.Task;
 import org.hswebframework.utils.StringUtils;
+import org.hswebframework.web.BusinessException;
 import org.hswebframework.web.NotFoundException;
+import org.hswebframework.web.workflow.service.ActivityConfigurationService;
 import org.hswebframework.web.workflow.service.BpmActivityService;
 import org.hswebframework.web.workflow.service.BpmTaskService;
 import org.hswebframework.web.workflow.flowable.utils.JumpTaskCmd;
+import org.hswebframework.web.workflow.service.WorkFlowFormService;
+import org.hswebframework.web.workflow.service.dto.ActivityCandidateInfo;
+import org.hswebframework.web.workflow.service.request.CompleteTaskRequest;
+import org.hswebframework.web.workflow.service.request.SaveFormRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -34,16 +40,24 @@ import java.util.*;
  */
 @Service
 @Transactional(rollbackFor = Throwable.class)
-public class BpmTaskServiceImp extends AbstractFlowableService implements BpmTaskService {
+public class BpmTaskServiceImpl extends AbstractFlowableService implements BpmTaskService {
 
     protected Logger logger = LoggerFactory.getLogger(this.getClass());
 
-    @Resource
+    @Autowired
     private BpmActivityService bpmActivityService;
 
+    @Autowired
+    private ActivityConfigurationService activityConfigurationService;
+
+    @Autowired
+    private WorkFlowFormService workFlowFormService;
+
     @Override
     public List<Task> selectNowTask(String procInstId) {
-        return taskService.createTaskQuery().processInstanceId(procInstId).active().list();
+        return taskService.createTaskQuery()
+                .processInstanceId(procInstId)
+                .active().list();
     }
 
     @Override
@@ -56,47 +70,15 @@ public class BpmTaskServiceImp extends AbstractFlowableService implements BpmTas
         return taskService.createTaskQuery().taskId(taskId).active().singleResult();
     }
 
-    @Override
-    public String selectNowTaskName(String procInstId) {
-        List<Task> tasks = selectNowTask(procInstId);
-        if (tasks.size() == 1) {
-            return tasks.get(0).getName();
-        } else {
-            StringBuilder builder = new StringBuilder();
-            for (int i = 0; i < tasks.size(); i++) {
-                if (i != 0) {
-                    builder.append(",");
-                }
-                builder.append(tasks.get(i).getName());
-            }
-            return builder.toString();
-        }
-
-    }
-
-    @Override
-    public String selectNowTaskId(String procInstId) {
-        List<Task> tasks = selectNowTask(procInstId);
-        if (tasks.size() == 1) {
-            return tasks.get(0).getId();
-        } else {
-            StringBuilder builder = new StringBuilder();
-            for (int i = 0; i < tasks.size(); i++) {
-                if (i != 0) {
-                    builder.append(",");
-                }
-                builder.append(tasks.get(i).getId());
-            }
-            return builder.toString();
-        }
-    }
-
     @Override
     public void claim(String taskId, String userId) {
-        Task task = taskService.createTaskQuery().taskId(taskId).taskCandidateUser(userId).active().singleResult();
+        Task task = taskService.createTaskQuery().
+                taskId(taskId)
+                .taskCandidateUser(userId)
+                .active()
+                .singleResult();
         if (task == null) {
-            logger.warn("获取任务失败!");
-            throw new NotFoundException("task not found");
+            throw new NotFoundException("无法签收此任务");
             //return; // fix null point
         }
         if (!StringUtils.isNullOrEmpty(task.getAssignee())) {
@@ -110,64 +92,78 @@ public class BpmTaskServiceImp extends AbstractFlowableService implements BpmTas
     @Override
     public List<Task> claimList(String userId) {
         // 等待签收的任务
-        List<Task> claimList = taskService.createTaskQuery()
+        return taskService.createTaskQuery()
                 .taskCandidateUser(userId)
                 .includeProcessVariables()
                 .active()
                 .list();
-        return claimList;
     }
 
     @Override
     public List<Task> todoList(String userId) {
         // 已经签收的任务
-        List<Task> todoList = taskService.createTaskQuery()
+        return taskService.createTaskQuery()
                 .taskAssignee(userId)
                 .includeProcessVariables()
                 .active()
                 .list();
-        return todoList;
     }
 
     @Override
-    public void complete(String taskId, String userId, String activityId, String nextClaim) {
-        Task task = taskService.createTaskQuery().taskId(taskId).includeProcessVariables().active().singleResult();
-        if (StringUtils.isNullOrEmpty(task)) {
-            logger.warn("任务不存在!");
-            throw new NotFoundException("task not found");
-        }
+    public void complete(CompleteTaskRequest request) {
+        request.tryValidate();
+
+        Task task = taskService.createTaskQuery()
+                .taskId(request.getTaskId())
+                .includeProcessVariables()
+                .active()
+                .singleResult();
+
+        Objects.requireNonNull(task, "任务不存在");
         String assignee = task.getAssignee();
-        if (StringUtils.isNullOrEmpty(assignee)) {
-            logger.warn("请先签收任务!");
-            throw new NotFoundException("Please sign for the task first");
+        Objects.requireNonNull(assignee, "任务未签收");
+        if (!assignee.equals(request.getCompleteUserId())) {
+            throw new BusinessException("只能完成自己的任务");
         }
-        if (!userId.equals(assignee)) {
-            logger.warn("只能完成自己的任务");
-            throw new NotFoundException("You can only do your own work");
+        Map<String, Object> variable = new HashMap<>();
+        variable.put("oldTaskId", task.getId());
+        Map<String, Object> transientVariables = new HashMap<>();
+
+        if (null != request.getVariables()) {
+            variable.putAll(request.getVariables());
+            transientVariables.putAll(request.getVariables());
         }
-        Map<String, Object> map = new HashMap<>();
-        map.put("oldTaskId", task.getId());
-        //完成此任务
-        if (StringUtils.isNullOrEmpty(activityId)) {
-            taskService.complete(taskId, map);
-        } else {
-            jumpTask(taskId, activityId, nextClaim);
+
+        //保存表单数据
+        workFlowFormService.saveTaskForm(task, SaveFormRequest.builder()
+                .userName(request.getCompleteUserName())
+                .userId(request.getCompleteUserId())
+                .formData(request.getFormData())
+                .build());
+
+        if (null != request.getFormData()) {
+            transientVariables.putAll(request.getFormData());
+        }
+
+        taskService.complete(task.getId(), variable, transientVariables);
+
+        //跳转
+        if (!StringUtils.isNullOrEmpty(request.getNextActivityId())) {
+            jumpTask(task, request.getNextActivityId());
         }
-        //根据流程ID查找执行计划,存在则进行下一步,没有则结束(定制化流程预留)
-        List<Execution> execution = runtimeService.createExecutionQuery().processInstanceId(task.getProcessInstanceId()).list();
-        if (execution.size() > 0) {
-            List<Task> tasks = selectNowTask(task.getProcessInstanceId());
-            // 自定义下一执行人
-            if (tasks.size() == 1 && !StringUtils.isNullOrEmpty(nextClaim)) {
-                claim(tasks.get(0).getId(), nextClaim);
+
+        //下一步候选人
+        List<Task> tasks = selectNowTask(task.getProcessInstanceId());
+        for (Task next : tasks) {
+            if (!StringUtils.isNullOrEmpty(request.getNextClaimUserId())) {
+                taskService.addCandidateUser(next.getId(), request.getNextClaimUserId());
             } else {
-                for (Task t : tasks) {
-                    addCandidateUser(t.getId(), t.getTaskDefinitionKey(), userId);
-                }
+                setCandidate(request.getCompleteUserId(), next);
             }
         }
     }
 
+
     @Override
     public void reject(String taskId) {
         // 先判定是否存在历史环节
@@ -241,39 +237,15 @@ public class BpmTaskServiceImp extends AbstractFlowableService implements BpmTas
 
     }
 
-    @Override
-    public void jumpTask(String taskId, String activity, String next_claim) {
-        Task task = selectTaskByTaskId(taskId);
+    public Task jumpTask(Task task, String activityId) {
         TaskServiceImpl taskServiceImpl = (TaskServiceImpl) taskService;
-        taskServiceImpl.getCommandExecutor().execute(new JumpTaskCmd(task.getExecutionId(), activity));
-        if(!StringUtils.isNullOrEmpty(next_claim)){
-            task = selectTaskByTaskId(taskId);
-            if (null != task) {
-                claim(task.getId(), next_claim);
-            }
-        }
+        taskServiceImpl.getCommandExecutor().execute(new JumpTaskCmd(task.getExecutionId(), activityId));
+        return task;
     }
 
     @Override
-    public void addCandidateUser(String taskId, String actId, String userId) {
-        if (!StringUtils.isNullOrEmpty(actId)) {
-            // 获取节点配置信息
-//            ActDefEntity actDefEntity = actDefService.selectSingle(single(ActDefEntity.actId, actId));
-            // 根据配置类型  获取人员信息 设置待办人
-//            if (actDefEntity!=null) {
-//                List<String> list = bpmUtilsService.selectUserIdsBy(userId,actDefEntity);
-//                list.forEach(uId -> taskService.addCandidateUser(taskId,uId));
-//            } else {
-                taskService.addCandidateUser(taskId,
-                        runtimeService.getIdentityLinksForProcessInstance(selectTaskByTaskId(taskId).getProcessInstanceId())
-                        .stream()
-                        .filter(linkEntity -> "starter".equals(linkEntity.getType()))
-                        .findFirst().orElseThrow(()-> new NotFoundException("发起人获取失败")).getUserId()
-                );
-//            }
-        } else {
-            taskService.addCandidateUser(taskId, userId);
-        }
+    public Task jumpTask(String taskId, String activity) {
+        return jumpTask(selectTaskByTaskId(taskId), activity);
     }
 
     @Override
@@ -285,7 +257,7 @@ public class BpmTaskServiceImp extends AbstractFlowableService implements BpmTas
     public void endProcess(String procInstId) {
         ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
         ActivityImpl activity = bpmActivityService.getEndEvent(processInstance.getProcessDefinitionId());
-        jumpTask(procInstId, activity.getId(), null);
+        jumpTask(procInstId, activity.getId());
     }
 
     @Override
@@ -308,6 +280,26 @@ public class BpmTaskServiceImp extends AbstractFlowableService implements BpmTas
         return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult();
     }
 
+    @Override
+    public void setCandidate(String doingUserId, Task task) {
+        if (task == null) {
+            return;
+        }
+        if (task.getTaskDefinitionKey() != null) {
+            //从配置中获取候选人
+            List<ActivityCandidateInfo> candidateInfoList = activityConfigurationService
+                    .getActivityConfiguration(doingUserId
+                            , task.getProcessDefinitionId()
+                            , task.getTaskDefinitionKey())
+                    .getCandidateInfo();
+            for (ActivityCandidateInfo candidateInfo : candidateInfoList) {
+                taskService.addCandidateUser(task.getId(), candidateInfo.user().getUser().getId());
+            }
+        } else {
+            logger.warn("未能成功设置环节候选人,task:{}", task);
+        }
+    }
+
     @Override
     public ActivityImpl selectActivityImplByTask(String taskId) {
         if (StringUtils.isNullOrEmpty(taskId)) {

+ 94 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/WorkFlowFormServiceImpl.java

@@ -0,0 +1,94 @@
+package org.hswebframework.web.workflow.service.imp;
+
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Task;
+import org.hswebframework.web.service.form.DynamicFormOperationService;
+import org.hswebframework.web.workflow.service.ActivityConfigurationService;
+import org.hswebframework.web.workflow.service.WorkFlowFormService;
+import org.hswebframework.web.workflow.service.dto.ActivityConfiguration;
+import org.hswebframework.web.workflow.service.dto.ProcessConfiguration;
+import org.hswebframework.web.workflow.service.request.SaveFormRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Map;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+@Service
+public class WorkFlowFormServiceImpl extends AbstractFlowableService implements WorkFlowFormService {
+
+    @Autowired
+    private ActivityConfigurationService activityConfigurationService;
+
+    @Autowired
+    private DynamicFormOperationService dynamicFormOperationService;
+
+    @Override
+    public void saveProcessForm(ProcessInstance instance, SaveFormRequest request) {
+        request.tryValidate();
+
+        ProcessConfiguration configuration = activityConfigurationService
+                .getProcessConfiguration(instance.getProcessDefinitionId());
+
+        if (configuration == null || StringUtils.isEmpty(configuration.getFormId())) {
+            return;
+        }
+        Map<String, Object> formData = request.getFormData();
+
+        acceptStartProcessFormData(instance, formData);
+
+        dynamicFormOperationService.saveOrUpdate(configuration.getFormId(), formData);
+
+    }
+
+    @Override
+    public void saveTaskForm(Task task, SaveFormRequest request) {
+        request.tryValidate();
+
+        ActivityConfiguration configuration = activityConfigurationService
+                .getActivityConfiguration(request.getUserId()
+                        , task.getProcessDefinitionId()
+                        , task.getTaskDefinitionKey());
+
+        if (configuration == null || StringUtils.isEmpty(configuration.getFormId())) {
+            return;
+        }
+
+        Map<String, Object> formData = request.getFormData();
+
+        acceptTaskFormData(task, formData);
+
+        dynamicFormOperationService.saveOrUpdate(configuration.getFormId(), formData);
+
+    }
+
+    protected void acceptTaskFormData(Task task,
+                                      Map<String, Object> formData) {
+
+        ProcessInstance instance = runtimeService.createProcessInstanceQuery()
+                .processInstanceId(task.getProcessInstanceId())
+                .singleResult();
+
+        acceptStartProcessFormData(instance, formData);
+
+        formData.put("taskId", task.getId());
+        formData.put("taskDefineKey", task.getTaskDefinitionKey());
+
+    }
+
+    protected void acceptStartProcessFormData(ProcessInstance instance,
+                                              Map<String, Object> formData) {
+
+        formData.put("id", instance.getBusinessKey());
+        formData.put("processDefineId", instance.getProcessDefinitionId());
+        formData.put("processDefineKey", instance.getProcessDefinitionKey());
+        formData.put("processDefineName", instance.getProcessDefinitionName());
+        formData.put("processDefineName", instance.getProcessDefinitionVersion());
+        formData.put("processInstanceId", instance.getProcessInstanceId());
+
+    }
+}

+ 10 - 3
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/request/CompleteTaskRequest.java

@@ -1,7 +1,10 @@
 package org.hswebframework.web.workflow.service.request;
 
 import lombok.*;
+import org.hibernate.validator.constraints.NotBlank;
+import org.hswebframework.web.commons.bean.ValidateBean;
 
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -13,20 +16,24 @@ import java.util.Map;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class CompleteTaskRequest {
+public class CompleteTaskRequest implements ValidateBean {
+    private static final long serialVersionUID = -2548459805655649449L;
     /**
      * 任务ID
      */
+    @NotBlank
     private String taskId;
 
     /**
      * 完成此任务的用户ID
      */
+    @NotBlank
     private String completeUserId;
 
     /**
      * 完成此任务的用户姓名
      */
+    @NotBlank
     private String completeUserName;
 
     /**
@@ -42,10 +49,10 @@ public class CompleteTaskRequest {
     /**
      * 变量
      */
-    private Map<String, Object> variables;
+    private Map<String, Object> variables = new HashMap<>();
 
     /**
      * 表单数据
      */
-    private Map<String, Object> formData;
+    private Map<String, Object> formData = new HashMap<>();
 }

+ 30 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/request/SaveFormRequest.java

@@ -0,0 +1,30 @@
+package org.hswebframework.web.workflow.service.request;
+
+import lombok.*;
+import org.hibernate.validator.constraints.NotBlank;
+import org.hswebframework.web.commons.bean.ValidateBean;
+
+import javax.validation.constraints.NotNull;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SaveFormRequest implements ValidateBean {
+    private static final long serialVersionUID = 7575220908978610735L;
+
+    @NotBlank
+    private String userId;
+
+    @NotBlank
+    private String userName;
+
+    private Map<String, Object> formData = new HashMap<>();
+}

+ 6 - 4
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/request/StartProcessRequest.java

@@ -7,6 +7,7 @@ import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.User;
 import org.hswebframework.web.commons.bean.ValidateBean;
 
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -21,9 +22,10 @@ import java.util.Map;
 @NoArgsConstructor
 @AllArgsConstructor
 @ToString
-public class StartProcessRequest implements ValidateBean{
+public class StartProcessRequest implements ValidateBean {
+    private static final long serialVersionUID = -344629653235864995L;
     /**
-     * 流程定义KEY
+     * 流程定义ID
      *
      * @see ProcessDefinition#getId()
      */
@@ -61,10 +63,10 @@ public class StartProcessRequest implements ValidateBean{
     /**
      * 流程变量
      */
-    private Map<String, Object> variables;
+    private Map<String, Object> variables = new HashMap<>();
 
     /**
      * 表单数据
      */
-    private Map<String, Object> formData;
+    private Map<String, Object> formData = new HashMap<>();
 }

+ 75 - 75
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/web/FlowableCoreController.java

@@ -2,12 +2,17 @@ package org.hswebframework.web.workflow.web;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.activiti.engine.RepositoryService;
+import org.activiti.engine.RuntimeService;
 import org.activiti.engine.impl.pvm.process.ActivityImpl;
 import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.runtime.ProcessInstance;
 import org.activiti.engine.task.Task;
 import org.hswebframework.web.NotFoundException;
+import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.Permission;
 import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.commons.entity.PagerResult;
 import org.hswebframework.web.commons.entity.param.QueryParamEntity;
 import org.hswebframework.web.controller.message.ResponseMessage;
@@ -16,6 +21,8 @@ import org.hswebframework.web.service.form.DynamicFormOperationService;
 import org.hswebframework.web.workflow.service.BpmActivityService;
 import org.hswebframework.web.workflow.service.BpmProcessService;
 import org.hswebframework.web.workflow.service.BpmTaskService;
+import org.hswebframework.web.workflow.service.request.CompleteTaskRequest;
+import org.hswebframework.web.workflow.service.request.StartProcessRequest;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.Assert;
 import org.springframework.web.bind.annotation.*;
@@ -26,110 +33,103 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
- * @Author wangwei
- * @Date 2017/9/5.
+ * @author zhouhao
+ * @date 2017/9/5.
  */
 @RestController
-@RequestMapping("/workflow/proc-def/")
-@Api(tags = "工作流-流程管理",description = "工作流流程管理")
-@Authorize(permission = "workflow-process",description = "工作流流程管理")
+@RequestMapping("/workflow/process/")
+@Api(tags = "工作流-流程管理", description = "工作流流程管理")
+@Authorize(permission = "workflow-process", description = "工作流流程管理")
 public class FlowableCoreController {
+
     @Autowired
-    BpmTaskService bpmTaskService;
+    private BpmTaskService bpmTaskService;
+
     @Autowired
-    BpmProcessService bpmProcessService;
+    private BpmProcessService bpmProcessService;
+
     @Autowired
-    BpmActivityService bpmActivityService;
-    @Autowired(required = false)
-    DynamicFormOperationService dynamicFormOperationService;
+    private RepositoryService repositoryService;
 
-    private void assertDynamicFormReady(){
-        Assert.notNull(dynamicFormOperationService,"未引入动态表单依赖");
-    }
-    /**
-     * 获取所有可用流程(流程配置与流程启动都可用该方法获取)
-     * @return key为流程定义的id。value为name
-     */
-    @GetMapping("/available")
-    @ApiOperation("获取所有可用流程定义信息")
-    @Authorize(action = Permission.ACTION_QUERY)
-    public ResponseMessage<Map<String, String>> getALlAvailableProcessDefinition(){
-        List<ProcessDefinition> list = bpmProcessService.getAllProcessDefinition();
-        return ResponseMessage.ok(list
-                .stream()
-                .collect(Collectors.toMap(ProcessDefinition::getId,ProcessDefinition::getName)));
-    }
+    @PostMapping("start/key/{defineKey}")
+    @ApiOperation("提交表单数据并启动流程")
+    public ResponseMessage<String> startProcessByKey(@PathVariable String defineKey,
+                                                     @RequestBody Map<String, Object> data,
+                                                     Authentication authentication) {
+        String id = repositoryService.createProcessDefinitionQuery()
+                .processDefinitionKey(defineKey)
+                .active()
+                .singleResult()
+                .getId();
 
-    /**
-     * 查询流程表单数据
-     * @param procDefId 流程定义id
-     */
-    @GetMapping("form/{id}")
-    @ApiOperation("查询流程的表单数据")
-    @Authorize(action = Permission.ACTION_QUERY)
-    public ResponseMessage<PagerResult<Object>> openForm(@PathVariable("id") String procDefId, QueryParamEntity param){
-        assertDynamicFormReady();
-        Map<String,PagerResult<Object>> map = new HashMap<>();
-        ActivityImpl activity = bpmActivityService.getStartEvent(procDefId);
-
-//        ActDefEntity actDefEntity = actDefService.selectSingle(single(ActDefEntity.actId,activity.getId()));
-//        if(actDefEntity!=null){
-//            return ResponseMessage.ok(dynamicFormOperationService.selectPager(actDefEntity.getFormId(),param));
-//        }
-        throw new NotFoundException("表单不存在");
+        ProcessInstance instance = bpmProcessService.startProcessInstance(StartProcessRequest.builder()
+                .creatorId(authentication.getUser().getId())
+                .creatorName(authentication.getUser().getName())
+                .formData(data)
+                .processDefineId(id)
+                .build());
+
+        return ResponseMessage.ok(instance.getId());
     }
 
     /**
      * 提交表单数据并启动流程
      */
-    @PostMapping("start/{formId}-{defId}")
+    @PostMapping("start/id/{defId}")
     @ApiOperation("提交表单数据并启动流程")
-    public ResponseMessage<Map<String, Object>> startProc(@PathVariable String formId,@PathVariable String defId, @RequestBody Map<String, Object> data) {
-        assertDynamicFormReady();
-        PersonnelAuthentication authorization = PersonnelAuthentication
-                .current()
-                .orElseThrow(NotFoundException::new);
-        dynamicFormOperationService.insert(formId, data);
-        ProcessDefinition processDefinition = bpmProcessService.getProcessDefinitionById(defId);
-//        bpmProcessService.startProcessInstance(authorization.getPersonnel().getId(),processDefinition.getKey(),null,null,formId,null);
-        return ResponseMessage.ok(data);
+    public ResponseMessage<String> startProcess(@PathVariable String defId,
+                                                @RequestBody Map<String, Object> data,
+                                                Authentication authentication) {
+
+        ProcessInstance instance = bpmProcessService.startProcessInstance(StartProcessRequest.builder()
+                .creatorId(authentication.getUser().getId())
+                .creatorName(authentication.getUser().getName())
+                .formData(data)
+                .processDefineId(defId)
+                .build());
+
+        return ResponseMessage.ok(instance.getId());
     }
 
     /**
      * 获取待办任务
-     * @return
      */
-    @GetMapping("tasks")
+    @GetMapping("claims")
     @ApiOperation("获取代办任务")
-    public ResponseMessage<List<Task>> getMyTasks() {
-        PersonnelAuthentication authorization = PersonnelAuthentication
-                .current()
-                .orElseThrow(NotFoundException::new);
-        String userId = authorization.getPersonnel().getId();
-        List<Task> tasks = bpmTaskService.claimList(userId);
-        return ResponseMessage.ok(tasks).include(Task.class, "id", "name", "createTime", "executionId"
-                , "parentTaskId", "processInstanceId", "processDefinitionId", "taskDefinitionKey")
+    public ResponseMessage<List<Task>> getMyTasks(Authentication authentication) {
+
+        List<Task> tasks = bpmTaskService.claimList(authentication.getUser().getId());
+
+        return ResponseMessage.ok(tasks)
+                .include(Task.class, "id", "name", "createTime", "executionId"
+                        , "parentTaskId", "processInstanceId", "processDefinitionId", "taskDefinitionKey")
                 .exclude(Task.class, "definition", "mainFormData");
     }
 
+    @PutMapping("claim/{taskId}")
+    @ApiOperation("签收任务")
+    public ResponseMessage<Void> claim(@PathVariable String taskId, Authentication authentication) {
+        bpmTaskService.claim(taskId, authentication.getUser().getId());
+        return ResponseMessage.ok();
+    }
+
     /**
      * 办理任务
-     * @param formId
+     *
      * @param taskId
      * @return
      */
-    @PutMapping("complete/{formId}-{taskId}")
-    public ResponseMessage<Map<String,Object>> complete(@PathVariable String formId,@PathVariable String taskId){
-        assertDynamicFormReady();
-        PersonnelAuthentication authorization = PersonnelAuthentication
-                .current()
-                .orElseThrow(NotFoundException::new);
-        String userId = authorization.getPersonnel().getId();
-//        dynamicFormOperationService.update(formId,null);
-        // 认领
-        bpmTaskService.claim(taskId,userId);
+    @PutMapping("complete/{taskId}")
+    public ResponseMessage<Map<String, Object>> complete(@PathVariable String taskId,
+                                                         @RequestBody(required = false) Map<String, Object> formData,
+                                                         Authentication authentication) {
         // 办理
-        bpmTaskService.complete(taskId, userId, null, null);
+        bpmTaskService.complete(CompleteTaskRequest.builder()
+                .taskId(taskId)
+                .completeUserId(authentication.getUser().getId())
+                .completeUserName(authentication.getUser().getName())
+                .formData(formData)
+                .build());
         return ResponseMessage.ok();
     }
 }

+ 82 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/test/java/org/hswebframework/web/workflow/flowable/WorkFlowProcessTests.groovy

@@ -0,0 +1,82 @@
+package org.hswebframework.web.workflow.flowable
+
+import com.alibaba.fastjson.JSON
+import org.activiti.engine.RuntimeService
+import org.activiti.engine.impl.persistence.entity.ExecutionEntity
+import org.activiti.engine.runtime.ProcessInstance
+import org.hswebframework.web.authorization.AuthenticationInitializeService
+import org.hswebframework.web.workflow.service.BpmProcessService
+import org.hswebframework.web.workflow.service.BpmTaskService
+import org.hswebframework.web.workflow.service.request.CompleteTaskRequest
+import org.hswebframework.web.workflow.service.request.StartProcessRequest
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.context.ConfigurableApplicationContext
+import org.springframework.http.MediaType
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.web.WebAppConfiguration
+import org.springframework.test.web.servlet.MockMvc
+import org.springframework.test.web.servlet.setup.MockMvcBuilders
+import spock.lang.Shared
+import spock.lang.Specification
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author zhouhao
+ * @since
+ */
+@WebAppConfiguration
+@ContextConfiguration
+@SpringBootTest(classes = [TestApplication.class], properties = ["classpath:application.yml"])
+class WorkFlowProcessTests extends Specification {
+    @Autowired
+    private ConfigurableApplicationContext context;
+
+    @Shared
+    private MockMvc mockMvc;
+
+    @Autowired
+    private AuthenticationInitializeService initializeService;
+
+    @Autowired
+    private BpmProcessService bpmProcessService;
+
+    @Autowired
+    private BpmTaskService bpmTaskService;
+
+    @Autowired
+    private RuntimeService runtimeService;
+
+    void setup() {
+        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
+    }
+
+    def "Start Process"() {
+        setup:
+        def request = new StartProcessRequest();
+        request.setCreatorId("admin");
+        request.setCreatorName("admin");
+        request.setProcessDefineId("testid:1:4");
+        request.setNextClaimUserId("admin")
+        and:
+        def instance = (ExecutionEntity) bpmProcessService.startProcessInstance(request);
+        expect:
+        instance != null
+        !instance.getTasks().isEmpty()
+        def taskId = instance.getTasks().get(0).getId();
+
+        bpmTaskService.claim(taskId, "admin");
+
+        bpmTaskService.complete(CompleteTaskRequest.builder()
+                .taskId(instance.getTasks().get(0).getId())
+                .completeUserId("admin")
+                .completeUserName("admin")
+                .nextClaimUserId("admin")
+                .build());
+
+
+    }
+
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 76 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/test/resources/processes/SimpleProcess.bpmn20.xml