diff --git a/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/engine/history/HistoricCaseInstanceQuery.java b/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/engine/history/HistoricCaseInstanceQuery.java index 861b80172a537f973acb3d34f87510a580f1e59b..7583e8769298f4cef6cff6e7523e4158b104e0d5 100644 --- a/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/engine/history/HistoricCaseInstanceQuery.java +++ b/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/engine/history/HistoricCaseInstanceQuery.java @@ -29,6 +29,11 @@ public interface HistoricCaseInstanceQuery extends Query caseInstanceIds); + /** * Only select historic case instances with the given business key. */ diff --git a/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/engine/runtime/CaseInstanceQuery.java b/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/engine/runtime/CaseInstanceQuery.java index 2704b1c0532ad12badc80150ce8fb5350350b500..57f650a56c8bbc55d4a21a07c9b510bf4faff7ca 100644 --- a/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/engine/runtime/CaseInstanceQuery.java +++ b/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/engine/runtime/CaseInstanceQuery.java @@ -29,6 +29,7 @@ public interface CaseInstanceQuery extends Query caseInstanceIds); CaseInstanceQuery caseInstanceBusinessKey(String caseInstanceBusinessKey); CaseInstanceQuery caseInstanceParentId(String parentId); CaseInstanceQuery caseInstanceStartedBefore(Date beforeTime); diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricCaseInstanceQueryImpl.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricCaseInstanceQueryImpl.java index 689e29f2e555c97ce199d95517d98c64ad916af6..2ea6160ea9d3725127979e827741e0a2902da06b 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricCaseInstanceQueryImpl.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricCaseInstanceQueryImpl.java @@ -37,6 +37,7 @@ public class HistoricCaseInstanceQueryImpl extends AbstractQuery caseInstanceIds; protected String businessKey; protected String caseInstanceParentId; protected String deploymentId; @@ -117,6 +118,15 @@ public class HistoricCaseInstanceQueryImpl extends AbstractQuery caseInstanceIds) { + if (caseInstanceIds == null) { + throw new FlowableIllegalArgumentException("Case instance ids is null"); + } + this.caseInstanceIds = caseInstanceIds; + return this; + } @Override public HistoricCaseInstanceQueryImpl caseInstanceBusinessKey(String businessKey) { diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java index 7f5df9d3124e2cbd6b43c4a9d14dd774941e9472..26fd1875db12c87c4e9997cccce4b023f8bc7858 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java @@ -38,6 +38,7 @@ public class CaseInstanceQueryImpl extends AbstractQuery caseInstanceIds; protected String caseInstanceParentId; protected String caseInstanceParentPlanItemInstanceId; protected Date startedBefore; @@ -112,6 +113,15 @@ public class CaseInstanceQueryImpl extends AbstractQuery caseInstanceIds) { + if (caseInstanceIds == null) { + throw new FlowableIllegalArgumentException("Case instance ids is null"); + } + this.caseInstanceIds = caseInstanceIds; + return this; + } @Override public CaseInstanceQueryImpl caseInstanceBusinessKey(String businessKey) { diff --git a/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/CaseInstance.xml b/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/CaseInstance.xml index 6fe3e5235a111d2c97fa315a22dd47b85cad4cbf..e78a9792a06603a474975c713f3ef16d5754312e 100644 --- a/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/CaseInstance.xml +++ b/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/CaseInstance.xml @@ -152,6 +152,12 @@ and RES.ID_ = #{caseInstanceId} + + and RES.ID_ IN + + #{caseInstanceId} + + RES.CASE_DEF_ID_ = #{caseDefinitionId} diff --git a/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/HistoricCaseInstance.xml b/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/HistoricCaseInstance.xml index 361608b89a11da6be76ea446c8c8e93282316992..d26da234edc251b542a13915d2d4ab1c759a445a 100644 --- a/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/HistoricCaseInstance.xml +++ b/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/HistoricCaseInstance.xml @@ -158,6 +158,13 @@ RES.ID_ = #{caseInstanceId} + + and RES.ID_ IN + + #{caseInstanceId} + + and RES.CASE_DEF_ID_ = #{caseDefinitionId} @@ -188,7 +195,7 @@ open="(" separator="," close=")"> #{deploymentId} - + and RES.BUSINESS_KEY_ = #{businessKey} diff --git a/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/i18n/en.json b/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/i18n/en.json index a8cf7810e97725a39afd0fcf07cd5ffa04def888..00149bc88a99c475428c66acb9945dd9bd42401e 100644 --- a/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/i18n/en.json +++ b/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/i18n/en.json @@ -154,6 +154,7 @@ "ASSIGNEE": "Assignee", "DUE": "Due", "PROCESS-INSTANCE": "Part of process", + "CASE-INSTANCE": "Part of case", "ENDED": "Ended", "DURATION": "Duration" }, diff --git a/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/scripts/controllers/task.js b/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/scripts/controllers/task.js index 30e4af5c6524601e880082039dcfdccedc2d251f..3a2fd4a580e0e42a9f5bfdd204888416846c8032 100644 --- a/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/scripts/controllers/task.js +++ b/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/scripts/controllers/task.js @@ -235,11 +235,17 @@ angular.module('flowableApp') $scope.loadComments(); $scope.loadRelatedContent(); - if($scope.model.task.processInstanceId) { + if ($scope.model.task.processInstanceId) { $scope.loadProcessInstance(); } else { $scope.model.processInstance = null; } + + if ($scope.model.task.scopeId) { + $scope.loadCaseInstance(); + } else { + $scope.model.caseInstance = null; + } $scope.refreshInvolvmentSummary(); @@ -483,7 +489,6 @@ angular.module('flowableApp') }); }; - // TODO: move process instance loading to separate service and merge with process.js $scope.loadProcessInstance = function() { $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + $scope.model.task.processInstanceId}). success(function(response, status, headers, config) { @@ -502,6 +507,25 @@ angular.module('flowableApp') } $location.path(path + "/processes"); }; + + $scope.loadCaseInstance = function() { + $http({method: 'GET', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/case-instances/' + $scope.model.task.scopeId}). + success(function(response, status, headers, config) { + $scope.model.caseInstance = response; + }). + error(function(response, status, headers, config) { + // Do nothing. User is not allowed to see the process instance + }); + }; + + $scope.openCaseInstance = function(id) { + $rootScope.root.selectedCaseId = id; + var path=''; + if($rootScope.activeAppDefinition && !FLOWABLE.CONFIG.integrationProfile) { + path = "/apps/" + $rootScope.activeAppDefinition.id; + } + $location.path(path + "/cases"); + }; $scope.returnToTaskList = function() { var path=''; diff --git a/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/scripts/services/task-service.js b/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/scripts/services/task-service.js index 4ef746a41e9efd6030afeaaf9b8150288f2ce12a..3c4476f05f607f0c0fb440f04034566134a6f6ce 100644 --- a/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/scripts/services/task-service.js +++ b/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/scripts/services/task-service.js @@ -241,18 +241,5 @@ angular.module('flowableApp').service('TaskService', ['$http', '$q', '$rootScope var promise = deferred.promise; return promise; }; - - this.getProcessInstanceVariables = function(taskId) { - var data = { - taskId: taskId - }; - - return httpAsPromise( - { - method: 'GET', - url: FLOWABLE.CONFIG.contextRoot + '/app/rest/task-forms/' + taskId + '/variables', - data: data - } - ); - } + }]); diff --git a/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/views/task-detail.html b/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/views/task-detail.html index c2cd837e064c5069f426531865d0e90131810182..ba94ac0b51620bdbc73cddbeffed250d4e171c62 100644 --- a/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/views/task-detail.html +++ b/modules/flowable-ui-task/flowable-ui-task-app/src/main/webapp/workflow/views/task-detail.html @@ -95,6 +95,10 @@ {{model.processInstance.name && model.processInstance.name || model.processInstance.processDefinitionName}} + {{'TASK.FIELD.CASE-INSTANCE' | translate}}: + + {{model.caseInstance.name && model.caseInstance.name || model.caseInstance.caseDefinitionName}} + {{'TASK.FIELD.ENDED' | translate}}: {{model.task.endDate | dateformat:'fromNow'}} diff --git a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/model/runtime/TaskRepresentation.java b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/model/runtime/TaskRepresentation.java index bf783f792c11da05fb88c8c0ddda079c9c459866..09dde7d614ad7d7f2735ab690ae76c5a9b5a0a03 100644 --- a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/model/runtime/TaskRepresentation.java +++ b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/model/runtime/TaskRepresentation.java @@ -17,6 +17,7 @@ import java.util.List; import org.flowable.app.model.common.AbstractRepresentation; import org.flowable.app.model.common.UserRepresentation; +import org.flowable.cmmn.engine.repository.CaseDefinition; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.task.service.Task; import org.flowable.task.service.TaskInfo; @@ -45,6 +46,7 @@ public class TaskRepresentation extends AbstractRepresentation { protected Integer priority; protected String processInstanceId; protected String processInstanceName; + protected String processDefinitionId; protected String processDefinitionName; protected String processDefinitionDescription; @@ -52,6 +54,19 @@ public class TaskRepresentation extends AbstractRepresentation { protected String processDefinitionCategory; protected int processDefinitionVersion; protected String processDefinitionDeploymentId; + + protected String scopeId; + protected String scopeType; + protected String caseInstanceName; + + protected String scopeDefinitionId; + protected String caseDefinitionName; + protected String caseDefinitionDescription; + protected String caseDefinitionKey; + protected String caseDefinitionCategory; + protected int caseDefinitionVersion; + protected String caseDefinitionDeploymentId; + protected String formKey; protected String processInstanceStartUserId; protected boolean initiatorCanCompleteTask; @@ -67,14 +82,50 @@ public class TaskRepresentation extends AbstractRepresentation { } public TaskRepresentation(Task task) { - this(task, null); + initializeTaskDetails(task); } public TaskRepresentation(HistoricTaskInstance task) { - this(task, null); + initializeTaskDetails(task); } public TaskRepresentation(TaskInfo taskInfo, ProcessDefinition processDefinition) { + initializeTaskDetails(taskInfo); + + if (processDefinition != null) { + this.processDefinitionName = processDefinition.getName(); + this.processDefinitionDescription = processDefinition.getDescription(); + this.processDefinitionKey = processDefinition.getKey(); + this.processDefinitionCategory = processDefinition.getCategory(); + this.processDefinitionVersion = processDefinition.getVersion(); + this.processDefinitionDeploymentId = processDefinition.getDeploymentId(); + } + } + + public TaskRepresentation(TaskInfo taskInfo, CaseDefinition caseDefinition) { + initializeTaskDetails(taskInfo); + + if (caseDefinition != null) { + this.caseDefinitionName = caseDefinition.getName(); + this.caseDefinitionDescription = caseDefinition.getDescription(); + this.caseDefinitionKey = caseDefinition.getKey(); + this.caseDefinitionCategory = caseDefinition.getCategory(); + this.caseDefinitionVersion = caseDefinition.getVersion(); + this.caseDefinitionDeploymentId = caseDefinition.getDeploymentId(); + } + } + + public TaskRepresentation(TaskInfo taskInfo, ProcessDefinition processDefinition, String processInstanceName) { + this(taskInfo, processDefinition); + this.processInstanceName = processInstanceName; + } + + public TaskRepresentation(TaskInfo taskInfo, CaseDefinition caseDefinition, String caseInstanceName) { + this(taskInfo, caseDefinition); + this.caseInstanceName = caseInstanceName; + } + + public void initializeTaskDetails(TaskInfo taskInfo) { this.id = taskInfo.getId(); this.name = taskInfo.getName(); this.description = taskInfo.getDescription(); @@ -84,6 +135,9 @@ public class TaskRepresentation extends AbstractRepresentation { this.priority = taskInfo.getPriority(); this.processInstanceId = taskInfo.getProcessInstanceId(); this.processDefinitionId = taskInfo.getProcessDefinitionId(); + this.scopeId = taskInfo.getScopeId(); + this.scopeType = taskInfo.getScopeType(); + this.scopeDefinitionId = taskInfo.getScopeDefinitionId(); if (taskInfo instanceof HistoricTaskInstance) { this.endDate = ((HistoricTaskInstance) taskInfo).getEndTime(); @@ -93,21 +147,6 @@ public class TaskRepresentation extends AbstractRepresentation { // Rendering of forms for historic tasks not supported currently this.formKey = taskInfo.getFormKey(); } - - if (processDefinition != null) { - this.processDefinitionName = processDefinition.getName(); - this.processDefinitionDescription = processDefinition.getDescription(); - this.processDefinitionKey = processDefinition.getKey(); - this.processDefinitionCategory = processDefinition.getCategory(); - this.processDefinitionVersion = processDefinition.getVersion(); - this.processDefinitionDeploymentId = processDefinition.getDeploymentId(); - } - } - - public TaskRepresentation(TaskInfo taskInfo, ProcessDefinition processDefinition, String processInstanceName) { - // todo Once a ProcessInstanceInfo class is implemented, lets send in that as the 3rd parameter instead - this(taskInfo, processDefinition); - this.processInstanceName = processInstanceName; } public void fillTask(Task task) { @@ -258,6 +297,86 @@ public class TaskRepresentation extends AbstractRepresentation { public void setProcessDefinitionDeploymentId(String processDefinitionDeploymentId) { this.processDefinitionDeploymentId = processDefinitionDeploymentId; } + + public String getScopeId() { + return scopeId; + } + + public void setScopeId(String scopeId) { + this.scopeId = scopeId; + } + + public String getScopeType() { + return scopeType; + } + + public void setScopeType(String scopeType) { + this.scopeType = scopeType; + } + + public String getCaseInstanceName() { + return caseInstanceName; + } + + public void setCaseInstanceName(String caseInstanceName) { + this.caseInstanceName = caseInstanceName; + } + + public String getScopeDefinitionId() { + return scopeDefinitionId; + } + + public void setScopeDefinitionId(String scopeDefinitionId) { + this.scopeDefinitionId = scopeDefinitionId; + } + + public String getCaseDefinitionName() { + return caseDefinitionName; + } + + public void setCaseDefinitionName(String caseDefinitionName) { + this.caseDefinitionName = caseDefinitionName; + } + + public String getCaseDefinitionDescription() { + return caseDefinitionDescription; + } + + public void setCaseDefinitionDescription(String caseDefinitionDescription) { + this.caseDefinitionDescription = caseDefinitionDescription; + } + + public String getCaseDefinitionKey() { + return caseDefinitionKey; + } + + public void setCaseDefinitionKey(String caseDefinitionKey) { + this.caseDefinitionKey = caseDefinitionKey; + } + + public String getCaseDefinitionCategory() { + return caseDefinitionCategory; + } + + public void setCaseDefinitionCategory(String caseDefinitionCategory) { + this.caseDefinitionCategory = caseDefinitionCategory; + } + + public int getCaseDefinitionVersion() { + return caseDefinitionVersion; + } + + public void setCaseDefinitionVersion(int caseDefinitionVersion) { + this.caseDefinitionVersion = caseDefinitionVersion; + } + + public String getCaseDefinitionDeploymentId() { + return caseDefinitionDeploymentId; + } + + public void setCaseDefinitionDeploymentId(String caseDefinitionDeploymentId) { + this.caseDefinitionDeploymentId = caseDefinitionDeploymentId; + } public String getFormKey() { return formKey; diff --git a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableAbstractTaskService.java b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableAbstractTaskService.java index bc1a9149bf12be4312b3a2db3898fcb721fa013c..6532fc426b7d80380f80c4c10ca027d5e157ce4f 100644 --- a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableAbstractTaskService.java +++ b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableAbstractTaskService.java @@ -23,6 +23,7 @@ import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.ExtensionElement; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.UserTask; +import org.flowable.cmmn.engine.CmmnRepositoryService; import org.flowable.cmmn.engine.CmmnTaskService; import org.flowable.editor.language.json.converter.util.CollectionUtils; import org.flowable.engine.HistoryService; @@ -42,6 +43,9 @@ public abstract class FlowableAbstractTaskService { @Autowired protected RepositoryService repositoryService; + + @Autowired + protected CmmnRepositoryService cmmnRepositoryService; @Autowired protected TaskService taskService; diff --git a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskFormService.java b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskFormService.java index 5f795fd27d8f698fb9573f1f4a7e91e6c5d46b61..c31566b9df3ca341b7bcb8a746a7180e1747ba15 100644 --- a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskFormService.java +++ b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskFormService.java @@ -12,17 +12,12 @@ */ package org.flowable.app.service.runtime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.flowable.app.model.runtime.CompleteFormRepresentation; -import org.flowable.app.model.runtime.ProcessInstanceVariableRepresentation; import org.flowable.app.model.runtime.SaveFormRepresentation; import org.flowable.app.security.SecurityUtils; import org.flowable.app.service.exception.NotFoundException; import org.flowable.app.service.exception.NotPermittedException; +import org.flowable.cmmn.engine.CmmnTaskService; import org.flowable.engine.HistoryService; import org.flowable.engine.RepositoryService; import org.flowable.engine.TaskService; @@ -32,7 +27,6 @@ import org.flowable.form.model.FormModel; import org.flowable.idm.api.User; import org.flowable.task.service.Task; import org.flowable.task.service.history.HistoricTaskInstance; -import org.flowable.variable.service.history.HistoricVariableInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -52,6 +46,9 @@ public class FlowableTaskFormService { @Autowired protected TaskService taskService; + + @Autowired + protected CmmnTaskService cmmnTaskService; @Autowired protected RepositoryService repositoryService; @@ -73,7 +70,11 @@ public class FlowableTaskFormService { public FormModel getTaskForm(String taskId) { HistoricTaskInstance task = permissionService.validateReadPermissionOnTask(SecurityUtils.getCurrentUserObject(), taskId); - return taskService.getTaskFormModel(task.getId()); + if (task.getProcessInstanceId() != null) { + return taskService.getTaskFormModel(task.getId()); + } else { + return cmmnTaskService.getTaskFormModel(task.getId()); + } } public void saveTaskForm(String taskId, SaveFormRepresentation saveFormRepresentation) { @@ -109,28 +110,16 @@ public class FlowableTaskFormService { checkCurrentUserCanModifyTask(task); - taskService.completeTaskWithForm(taskId, completeTaskFormRepresentation.getFormId(), - completeTaskFormRepresentation.getOutcome(), completeTaskFormRepresentation.getValues()); - } - - public List getProcessInstanceVariables(String taskId) { - HistoricTaskInstance task = permissionService.validateReadPermissionOnTask(SecurityUtils.getCurrentUserObject(), taskId); - List historicVariables = historyService.createHistoricVariableInstanceQuery().processInstanceId(task.getProcessInstanceId()).list(); - - // Get all process-variables to extract values from - Map processInstanceVariables = new HashMap<>(); - - for (HistoricVariableInstance historicVariableInstance : historicVariables) { - ProcessInstanceVariableRepresentation processInstanceVariableRepresentation = new ProcessInstanceVariableRepresentation( - historicVariableInstance.getVariableName(), historicVariableInstance.getVariableTypeName(), historicVariableInstance.getValue()); - processInstanceVariables.put(historicVariableInstance.getId(), processInstanceVariableRepresentation); + if (task.getProcessInstanceId() != null) { + taskService.completeTaskWithForm(taskId, completeTaskFormRepresentation.getFormId(), + completeTaskFormRepresentation.getOutcome(), completeTaskFormRepresentation.getValues()); + } else { + cmmnTaskService.completeTaskWithForm(taskId, completeTaskFormRepresentation.getFormId(), completeTaskFormRepresentation.getOutcome(), + completeTaskFormRepresentation.getValues()); } - - List processInstanceVariableRepresenations = new ArrayList<>(processInstanceVariables.values()); - return processInstanceVariableRepresenations; } - private void checkCurrentUserCanModifyTask(Task task) { + protected void checkCurrentUserCanModifyTask(Task task) { User currentUser = SecurityUtils.getCurrentUserObject(); if (!permissionService.isTaskOwnerOrAssignee(currentUser, task.getId())) { if (!permissionService.validateIfUserIsInitiatorAndCanCompleteTask(currentUser, task)) { diff --git a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskQueryService.java b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskQueryService.java index 742b9dd46a055324eaab7a572eb58c31ebdb3e29..6527edbefb3b344b0df28ce0b638c8613fa8f040 100644 --- a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskQueryService.java +++ b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskQueryService.java @@ -30,6 +30,12 @@ import org.flowable.app.security.SecurityUtils; import org.flowable.app.service.api.UserCache; import org.flowable.app.service.api.UserCache.CachedUser; import org.flowable.app.service.exception.BadRequestException; +import org.flowable.cmmn.engine.CmmnHistoryService; +import org.flowable.cmmn.engine.CmmnRepositoryService; +import org.flowable.cmmn.engine.CmmnRuntimeService; +import org.flowable.cmmn.engine.history.HistoricCaseInstance; +import org.flowable.cmmn.engine.repository.CaseDefinition; +import org.flowable.cmmn.engine.runtime.CaseInstance; import org.flowable.editor.language.json.converter.util.CollectionUtils; import org.flowable.engine.HistoryService; import org.flowable.engine.RepositoryService; @@ -71,15 +77,24 @@ public class FlowableTaskQueryService { @Autowired protected RepositoryService repositoryService; + + @Autowired + protected CmmnRepositoryService cmmnRepositoryService; @Autowired protected TaskService taskService; @Autowired protected RuntimeService runtimeService; + + @Autowired + protected CmmnRuntimeService cmmnRuntimeService; @Autowired protected HistoryService historyService; + + @Autowired + protected CmmnHistoryService cmmnHistoryService; @Autowired protected UserCache userCache; @@ -172,13 +187,14 @@ public class FlowableTaskQueryService { List tasks = taskInfoQueryWrapper.getTaskInfoQuery().listPage(page * size, size); JsonNode includeProcessInstanceNode = requestNode.get("includeProcessInstance"); - // todo Once a ProcessInstanceInfo class has been implement use it instead rather than just the name Map processInstancesNames = new HashMap<>(); + Map caseInstancesNames = new HashMap<>(); if (includeProcessInstanceNode != null) { handleIncludeProcessInstance(taskInfoQueryWrapper, includeProcessInstanceNode, tasks, processInstancesNames); + handleIncludeCaseInstance(taskInfoQueryWrapper, includeProcessInstanceNode, tasks, caseInstancesNames); } - ResultListDataRepresentation result = new ResultListDataRepresentation(convertTaskInfoList(tasks, processInstancesNames)); + ResultListDataRepresentation result = new ResultListDataRepresentation(convertTaskInfoList(tasks, processInstancesNames, caseInstancesNames)); // In case we're not on the first page and the size exceeds the page size, we need to do an additional count for the total if (page != 0 || tasks.size() == size) { @@ -312,26 +328,58 @@ public class FlowableTaskQueryService { } } } + + protected void handleIncludeCaseInstance(TaskInfoQueryWrapper taskInfoQueryWrapper, JsonNode includeProcessInstanceNode, List tasks, Map caseInstanceNames) { + if (includeProcessInstanceNode.asBoolean() && CollectionUtils.isNotEmpty(tasks)) { + Set caseInstanceIds = new HashSet<>(); + for (TaskInfo task : tasks) { + if (task.getScopeId() != null) { + caseInstanceIds.add(task.getScopeId()); + } + } + if (CollectionUtils.isNotEmpty(caseInstanceIds)) { + if (taskInfoQueryWrapper.getTaskInfoQuery() instanceof HistoricTaskInstanceQuery) { + List caseInstances = cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceIds(caseInstanceIds).list(); + for (HistoricCaseInstance caseInstance : caseInstances) { + caseInstanceNames.put(caseInstance.getId(), caseInstance.getName()); + } + } else { + List caseInstances = cmmnRuntimeService.createCaseInstanceQuery().caseInstanceIds(caseInstanceIds).list(); + for (CaseInstance caseInstance : caseInstances) { + caseInstanceNames.put(caseInstance.getId(), caseInstance.getName()); + } + } + } + } + } - protected List convertTaskInfoList(List tasks, Map processInstanceNames) { + protected List convertTaskInfoList(List tasks, Map processInstanceNames, Map caseInstancesNames) { List result = new ArrayList<>(); if (CollectionUtils.isNotEmpty(tasks)) { for (TaskInfo task : tasks) { - ProcessDefinitionEntity processDefinition = null; - if (task.getProcessDefinitionId() != null) { - processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(task.getProcessDefinitionId()); + + TaskRepresentation taskRepresentation = null; + if (task.getScopeDefinitionId() != null) { + CaseDefinition caseDefinition = cmmnRepositoryService.getCaseDefinition(task.getScopeDefinitionId()); + taskRepresentation = new TaskRepresentation(task, caseDefinition, caseInstancesNames.get(task.getScopeId())); + + } else { + ProcessDefinitionEntity processDefinition = null; + if (task.getProcessDefinitionId() != null) { + processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(task.getProcessDefinitionId()); + } + taskRepresentation = new TaskRepresentation(task, processDefinition, processInstanceNames.get(task.getProcessInstanceId())); } - TaskRepresentation representation = new TaskRepresentation(task, processDefinition, processInstanceNames.get(task.getProcessInstanceId())); if (StringUtils.isNotEmpty(task.getAssignee())) { CachedUser cachedUser = userCache.getUser(task.getAssignee()); if (cachedUser != null && cachedUser.getUser() != null) { User assignee = cachedUser.getUser(); - representation.setAssignee(new UserRepresentation(assignee)); + taskRepresentation.setAssignee(new UserRepresentation(assignee)); } } - result.add(representation); + result.add(taskRepresentation); } } return result; diff --git a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskService.java b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskService.java index 004d003e112ba275f1be289c2fc1d996b0caacb7..e86af29ca6e52178f2607373b01bd2e2ff84a784 100644 --- a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskService.java +++ b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/FlowableTaskService.java @@ -24,6 +24,7 @@ import org.flowable.app.model.runtime.TaskUpdateRepresentation; import org.flowable.app.security.SecurityUtils; import org.flowable.app.service.api.UserCache.CachedUser; import org.flowable.app.service.exception.NotFoundException; +import org.flowable.cmmn.engine.repository.CaseDefinition; import org.flowable.engine.common.api.FlowableException; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.identitylink.service.IdentityLinkType; @@ -50,16 +51,26 @@ public class FlowableTaskService extends FlowableAbstractTaskService { User currentUser = SecurityUtils.getCurrentUserObject(); HistoricTaskInstance task = permissionService.validateReadPermissionOnTask(currentUser, taskId); - ProcessDefinition processDefinition = null; + TaskRepresentation rep = null; if (StringUtils.isNotEmpty(task.getProcessDefinitionId())) { try { - processDefinition = repositoryService.getProcessDefinition(task.getProcessDefinitionId()); + ProcessDefinition processDefinition = repositoryService.getProcessDefinition(task.getProcessDefinitionId()); + rep = new TaskRepresentation(task, processDefinition); + } catch (FlowableException e) { LOGGER.error("Error getting process definition {}", task.getProcessDefinitionId(), e); } + + } else if (StringUtils.isNotEmpty(task.getScopeDefinitionId())) { + try { + CaseDefinition caseDefinition = cmmnRepositoryService.getCaseDefinition(task.getScopeDefinitionId()); + rep = new TaskRepresentation(task, caseDefinition); + + } catch (FlowableException e) { + LOGGER.error("Error getting case definition {}", task.getScopeDefinitionId(), e); + } } - TaskRepresentation rep = new TaskRepresentation(task, processDefinition); fillPermissionInformation(rep, task, currentUser); // Populate the people diff --git a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/PermissionService.java b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/PermissionService.java index 12ff6fd8ea3471e97b34e6b8ba73658ff14f0462..b737ad235e05d1a54899fe75774904786ca82b7d 100644 --- a/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/PermissionService.java +++ b/modules/flowable-ui-task/flowable-ui-task-logic/src/main/java/org/flowable/app/service/runtime/PermissionService.java @@ -24,6 +24,8 @@ import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.ExtensionElement; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.UserTask; +import org.flowable.cmmn.engine.CmmnHistoryService; +import org.flowable.cmmn.engine.history.HistoricCaseInstance; import org.flowable.content.api.ContentItem; import org.flowable.editor.language.json.converter.util.CollectionUtils; import org.flowable.engine.HistoryService; @@ -63,6 +65,9 @@ public class PermissionService { @Autowired protected HistoryService historyService; + + @Autowired + protected CmmnHistoryService cmmnHistoryService; @Autowired protected RemoteIdmService remoteIdmService; @@ -146,6 +151,15 @@ public class PermissionService { } } } + + } else if (task.getScopeId() != null) { + HistoricCaseInstance historicCaseInstance = cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(task.getScopeId()).singleResult(); + if (historicCaseInstance != null && StringUtils.isNotEmpty(historicCaseInstance.getStartUserId())) { + String caseInstanceStartUserId = historicCaseInstance.getStartUserId(); + if (String.valueOf(user.getId()).equals(caseInstanceStartUserId)) { + canCompleteTask = true; + } + } } return canCompleteTask; } diff --git a/modules/flowable-ui-task/flowable-ui-task-rest/src/main/java/org/flowable/app/rest/runtime/TaskFormResource.java b/modules/flowable-ui-task/flowable-ui-task-rest/src/main/java/org/flowable/app/rest/runtime/TaskFormResource.java index e09fd994cfb7712399c46e4c09fb659860df672f..2715d57662758fcb2a7a720494c1c85b309b0c27 100644 --- a/modules/flowable-ui-task/flowable-ui-task-rest/src/main/java/org/flowable/app/rest/runtime/TaskFormResource.java +++ b/modules/flowable-ui-task/flowable-ui-task-rest/src/main/java/org/flowable/app/rest/runtime/TaskFormResource.java @@ -12,10 +12,7 @@ */ package org.flowable.app.rest.runtime; -import java.util.List; - import org.flowable.app.model.runtime.CompleteFormRepresentation; -import org.flowable.app.model.runtime.ProcessInstanceVariableRepresentation; import org.flowable.app.model.runtime.SaveFormRepresentation; import org.flowable.app.service.runtime.FlowableTaskFormService; import org.flowable.form.model.FormModel; @@ -54,9 +51,4 @@ public class TaskFormResource { public void saveTaskForm(@PathVariable String taskId, @RequestBody SaveFormRepresentation saveFormRepresentation) { taskFormService.saveTaskForm(taskId, saveFormRepresentation); } - - @RequestMapping(value = "/{taskId}/variables", method = RequestMethod.GET, produces = "application/json") - public List getProcessInstanceVariables(@PathVariable String taskId) { - return taskFormService.getProcessInstanceVariables(taskId); - } } diff --git a/modules/flowable-variable-service/src/main/resources/org/flowable/variable/db/mapping/entity/HistoricVariableInstance.xml b/modules/flowable-variable-service/src/main/resources/org/flowable/variable/db/mapping/entity/HistoricVariableInstance.xml index 5814faa41eef89e093376f315dba4002efd13c98..8ff7376918a66714443889a19510077b7d1b56b2 100644 --- a/modules/flowable-variable-service/src/main/resources/org/flowable/variable/db/mapping/entity/HistoricVariableInstance.xml +++ b/modules/flowable-variable-service/src/main/resources/org/flowable/variable/db/mapping/entity/HistoricVariableInstance.xml @@ -224,6 +224,15 @@ and RES.TASK_ID_ is NULL + + and RES.SCOPE_ID_ = #{scopeId} + + + and RES.SUB_SCOPE_ID_ = #{subScopeId} + + + and RES.SCOPE_TYPE_ = #{scopeType} + and RES.NAME_ = #{variableName}