diff --git a/common/taskana-common-data/src/main/resources/sql/test-data/task.sql b/common/taskana-common-data/src/main/resources/sql/test-data/task.sql index 2a8a77086..c87d53310 100644 --- a/common/taskana-common-data/src/main/resources/sql/test-data/task.sql +++ b/common/taskana-common-data/src/main/resources/sql/test-data/task.sql @@ -81,6 +81,7 @@ INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000065', 'ETI:0000000 INSERT INTO TASK VALUES('TKI:100000000000000000000000000000000006', 'ETI:100000000000000000000000000000000006', '2018-01-29 15:55:06', '2018-01-30 15:55:06', '2018-01-30 16:55:06', '2018-01-30 16:55:06', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'COMPLETED' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000004' , 'TEAMLEAD-1' , 'DOMAIN_A', 'PI_0000000000041' , 'DOC_0000000000000000041' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null ); INSERT INTO TASK VALUES('TKI:200000000000000000000000000000000006', 'ETI:200000000000000000000000000000000006', '2018-03-29 15:55:06', '2018-03-30 15:55:06', null , '2018-03-30 15:55:06', '2018-03-29 15:55:00', '2018-03-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'COMPLETED' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000005' , 'TEAMLEAD-2' , 'DOMAIN_A', 'PI_0000000000006' , 'DOC_0000000000000000006' , null , '00' , 'PASystem' , '00' , 'SDNR' , '98765432' , false , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null ); INSERT INTO TASK VALUES('TKI:200000000000000000000000000000000007', 'ETI:200000000000000000000000000000000007', '2018-03-29 15:55:06', '2018-03-30 15:55:06', null , '2018-03-30 15:55:06', '2018-03-29 15:55:00', '2018-03-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000005' , 'TEAMLEAD-2' , 'DOMAIN_A', 'PI_0000000000006' , 'DOC_0000000000000000006' , null , '00' , 'PASystem' , '00' , 'SDNR' , '98765432' , false , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null ); +INSERT INTO TASK VALUES('TKI:200000000000000000000000000000000008', 'ETI:200000000000000000000000000000000008', '2018-03-29 15:55:06', '2018-03-30 15:55:06', null , '2018-03-30 15:55:06', '2018-03-29 15:55:00', '2018-03-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000010' , 'TPK_VIP' , 'DOMAIN_A', '' , '' , null , '00' , 'PASystem' , '00' , 'SDNR' , '98765432' , false , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null ); -- Tasks for state cancelled INSERT INTO TASK VALUES('TKI:300000000000000000000000000000000000', 'ETI:300000000000000000000000000000000000', '2018-01-29 15:55:24', '2018-01-30 15:55:24', '2018-01-30 16:55:24', '2018-01-30 16:55:24', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'CANCELLED' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000007' , 'USER-1-2' , 'DOMAIN_A', 'PI_0000000000036' , 'DOC_0000000000000000036' , 'user-1-2' , '00' , 'PASystem' , '00' , 'SDNR' , '00011122' , true , false , null , 'NONE' , null , null , null , null , null , 'ew' , null , null , null , null , null , null , null , null , 'abc' , null , null ); INSERT INTO TASK VALUES('TKI:300000000000000000000000000000000001', 'ETI:300000000000000000000000000000000001', '2018-01-29 15:55:24', '2018-01-30 15:55:24', '2018-01-30 16:55:24', '2018-01-30 16:55:24', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , 'CANCELLED' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000007' , 'USER-1-2' , 'DOMAIN_A', 'PI_0000000000037' , 'DOC_0000000000000000037' , 'user-1-2' , '00' , 'PASystem' , '00' , 'SDNR' , '00011122' , true , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null ); diff --git a/lib/taskana-core/src/main/java/pro/taskana/task/internal/TaskServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/task/internal/TaskServiceImpl.java index ad45e047c..7a4d181ed 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/task/internal/TaskServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/task/internal/TaskServiceImpl.java @@ -450,7 +450,7 @@ public class TaskServiceImpl implements TaskService { public BulkOperationResults transferTasks( String destinationWorkbasketId, List taskIds, boolean setTransferFlag) throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException { - return taskTransferrer.transferTasks(destinationWorkbasketId, taskIds, setTransferFlag); + return taskTransferrer.transfer(taskIds, destinationWorkbasketId, setTransferFlag); } @Override @@ -460,8 +460,8 @@ public class TaskServiceImpl implements TaskService { List taskIds, boolean setTransferFlag) throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException { - return taskTransferrer.transferTasks( - destinationWorkbasketKey, destinationWorkbasketDomain, taskIds, setTransferFlag); + return taskTransferrer.transfer( + taskIds, destinationWorkbasketKey, destinationWorkbasketDomain, setTransferFlag); } @Override @@ -930,20 +930,6 @@ public class TaskServiceImpl implements TaskService { return bulkLog; } - void removeNonExistingTasksFromTaskIdList( - List taskIds, BulkOperationResults bulkLog) { - - Iterator taskIdIterator = taskIds.iterator(); - while (taskIdIterator.hasNext()) { - String currentTaskId = taskIdIterator.next(); - if (currentTaskId == null || currentTaskId.equals("")) { - bulkLog.addError( - "", new InvalidArgumentException("IDs with EMPTY or NULL value are not allowed.")); - taskIdIterator.remove(); - } - } - } - List augmentTaskSummariesByContainedSummariesWithPartitioning( List taskSummaries) { diff --git a/lib/taskana-core/src/main/java/pro/taskana/task/internal/TaskTransferrer.java b/lib/taskana-core/src/main/java/pro/taskana/task/internal/TaskTransferrer.java index 29276dde8..f7e22fac4 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/task/internal/TaskTransferrer.java +++ b/lib/taskana-core/src/main/java/pro/taskana/task/internal/TaskTransferrer.java @@ -2,13 +2,9 @@ package pro.taskana.task.internal; import java.time.Instant; import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import pro.taskana.common.api.BulkOperationResults; import pro.taskana.common.api.exceptions.InvalidArgumentException; @@ -24,24 +20,23 @@ import pro.taskana.task.api.exceptions.TaskNotFoundException; import pro.taskana.task.api.models.Task; import pro.taskana.task.internal.models.MinimalTaskSummary; import pro.taskana.task.internal.models.TaskImpl; -import pro.taskana.task.internal.models.TaskSummaryImpl; import pro.taskana.workbasket.api.WorkbasketPermission; import pro.taskana.workbasket.api.WorkbasketService; import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException; -import pro.taskana.workbasket.api.models.Workbasket; import pro.taskana.workbasket.api.models.WorkbasketSummary; import pro.taskana.workbasket.internal.WorkbasketQueryImpl; -/** This class is responsible for the transfer of tasks. */ -class TaskTransferrer { +/** This class is responsible for the transfer of Tasks to another Workbasket. */ +final class TaskTransferrer { - private static final String WAS_NOT_FOUND2 = " was not found."; - private static final String TASK_IN_END_STATE_WITH_ID_CANNOT_BE_TRANSFERRED = - "Task in end state with id %s cannot be transferred."; - private static final String TASK_WITH_ID = "Task with id "; - private static final String WAS_MARKED_FOR_DELETION = " was marked for deletion"; - private static final String THE_WORKBASKET = "The workbasket "; - private static final Logger LOGGER = LoggerFactory.getLogger(TaskTransferrer.class); + private static final String TASK_ID_LIST_NULL_OR_EMPTY = "TaskIds must not be null or empty."; + private static final String TASK_IN_END_STATE = + "Task '%s' is in end state and cannot be transferred."; + private static final String TASK_NOT_FOUND = "Task '%s' was not found."; + private static final String WORKBASKET_MARKED_FOR_DELETION = + "Workbasket '%s' was marked for deletion."; + private static final String WORKBASKET_WITHOUT_TRANSFER_PERMISSION = + "Workbasket of Task '%s' got no TRANSFER permission."; private final InternalTaskanaEngine taskanaEngine; private final WorkbasketService workbasketService; private final TaskServiceImpl taskService; @@ -57,300 +52,226 @@ class TaskTransferrer { this.historyEventManager = taskanaEngine.getHistoryEventManager(); } - Task transfer( - String taskId, String destinationWorkbasketKey, String domain, boolean setTransferFlag) - throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException, - InvalidStateException { - TaskImpl task = null; - WorkbasketSummary oldWorkbasketSummary = null; - try { - taskanaEngine.openConnection(); - task = (TaskImpl) taskService.getTask(taskId); - - if (task.getState().isEndState()) { - throw new InvalidStateException( - String.format(TASK_IN_END_STATE_WITH_ID_CANNOT_BE_TRANSFERRED, task.getId())); - } - - // Save previous workbasket id before transfer it. - oldWorkbasketSummary = task.getWorkbasketSummary(); - - // transfer requires TRANSFER in source and APPEND on destination workbasket - workbasketService.checkAuthorization( - destinationWorkbasketKey, domain, WorkbasketPermission.APPEND); - workbasketService.checkAuthorization( - task.getWorkbasketSummary().getId(), WorkbasketPermission.TRANSFER); - - Workbasket destinationWorkbasket = - workbasketService.getWorkbasket(destinationWorkbasketKey, domain); - - task.setRead(false); - task.setTransferred(setTransferFlag); - - // transfer task from source to destination workbasket - if (!destinationWorkbasket.isMarkedForDeletion()) { - task.setWorkbasketSummary(destinationWorkbasket.asSummary()); - } else { - throw new WorkbasketNotFoundException( - destinationWorkbasket.getId(), - THE_WORKBASKET + destinationWorkbasket.getId() + WAS_MARKED_FOR_DELETION); - } - - task.setModified(Instant.now()); - task.setState(TaskState.READY); - task.setOwner(null); - taskMapper.update(task); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug( - "Method transfer() transferred Task '{}' to destination workbasket {}", - taskId, - destinationWorkbasket.getId()); - } - if (HistoryEventManager.isHistoryEnabled()) { - createTaskTransferredEvent( - task, oldWorkbasketSummary.getId(), destinationWorkbasket.asSummary().getId()); - } - return task; - } finally { - taskanaEngine.returnConnection(); - } - } - Task transfer(String taskId, String destinationWorkbasketId, boolean setTransferFlag) throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException, InvalidStateException { + WorkbasketSummary destinationWorkbasket = + workbasketService.getWorkbasket(destinationWorkbasketId); + return transferSingleTask(taskId, destinationWorkbasket, setTransferFlag); + } - TaskImpl task = null; - WorkbasketSummary oldWorkbasketSummary = null; + Task transfer( + String taskId, + String destinationWorkbasketKey, + String destinationDomain, + boolean setTransferFlag) + throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException, + InvalidStateException { + WorkbasketSummary destinationWorkbasket = + workbasketService.getWorkbasket(destinationWorkbasketKey, destinationDomain); + return transferSingleTask(taskId, destinationWorkbasket, setTransferFlag); + } + + BulkOperationResults transfer( + List taskIds, String destinationWorkbasketId, boolean setTransferFlag) + throws NotAuthorizedException, WorkbasketNotFoundException, InvalidArgumentException { + WorkbasketSummary destinationWorkbasket = + workbasketService.getWorkbasket(destinationWorkbasketId); + checkDestinationWorkbasket(destinationWorkbasket); + + return transferMultipleTasks(taskIds, destinationWorkbasket, setTransferFlag); + } + + BulkOperationResults transfer( + List taskIds, + String destinationWorkbasketKey, + String destinationDomain, + boolean setTransferFlag) + throws NotAuthorizedException, WorkbasketNotFoundException, InvalidArgumentException { + WorkbasketSummary destinationWorkbasket = + workbasketService.getWorkbasket(destinationWorkbasketKey, destinationDomain); + checkDestinationWorkbasket(destinationWorkbasket); + + return transferMultipleTasks(taskIds, destinationWorkbasket, setTransferFlag); + } + + private Task transferSingleTask( + String taskId, WorkbasketSummary destinationWorkbasket, boolean setTransferFlag) + throws NotAuthorizedException, TaskNotFoundException, WorkbasketNotFoundException, + InvalidStateException { + TaskImpl task = new TaskImpl(); try { taskanaEngine.openConnection(); task = (TaskImpl) taskService.getTask(taskId); + WorkbasketSummary originWorkbasket = task.getWorkbasketSummary(); + checkPreconditionsForTransferTask(task, destinationWorkbasket, originWorkbasket); - if (task.getState().isEndState()) { - throw new InvalidStateException( - String.format(TASK_IN_END_STATE_WITH_ID_CANNOT_BE_TRANSFERRED, task.getId())); - } - oldWorkbasketSummary = task.getWorkbasketSummary(); - - // transfer requires TRANSFER in source and APPEND on destination workbasket - workbasketService.checkAuthorization(destinationWorkbasketId, WorkbasketPermission.APPEND); - workbasketService.checkAuthorization( - task.getWorkbasketSummary().getId(), WorkbasketPermission.TRANSFER); - - Workbasket destinationWorkbasket = workbasketService.getWorkbasket(destinationWorkbasketId); - - task.setRead(false); - task.setTransferred(setTransferFlag); - - // transfer task from source to destination workbasket - if (!destinationWorkbasket.isMarkedForDeletion()) { - task.setWorkbasketSummary(destinationWorkbasket.asSummary()); - } else { - throw new WorkbasketNotFoundException( - destinationWorkbasket.getId(), - THE_WORKBASKET + destinationWorkbasket.getId() + WAS_MARKED_FOR_DELETION); - } - - task.setModified(Instant.now()); - task.setState(TaskState.READY); - task.setOwner(null); + modifyTaskParameters(task, destinationWorkbasket, setTransferFlag); taskMapper.update(task); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug( - "Method transfer() transferred Task '{}' to destination workbasket {}", - taskId, - destinationWorkbasketId); - } if (HistoryEventManager.isHistoryEnabled()) { - createTaskTransferredEvent(task, oldWorkbasketSummary.getId(), destinationWorkbasketId); + createTransferredEvent(task, originWorkbasket.getId(), destinationWorkbasket.getId()); } + return task; } finally { taskanaEngine.returnConnection(); } } - BulkOperationResults transferTasks( - String destinationWorkbasketKey, - String destinationWorkbasketDomain, - List taskIds, + private BulkOperationResults transferMultipleTasks( + List taskToBeTransferred, + WorkbasketSummary destinationWorkbasket, boolean setTransferFlag) - throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException { + throws InvalidArgumentException { + if (taskToBeTransferred == null || taskToBeTransferred.isEmpty()) { + throw new InvalidArgumentException(TASK_ID_LIST_NULL_OR_EMPTY); + } + BulkOperationResults bulkLog = new BulkOperationResults<>(); + List taskIds = new ArrayList<>(taskToBeTransferred); + try { taskanaEngine.openConnection(); - // Check pre-conditions with trowing Exceptions - if (destinationWorkbasketKey == null || destinationWorkbasketDomain == null) { - throw new InvalidArgumentException( - "DestinationWorkbasketKey or domain can“t be used as NULL-Parameter."); - } - Workbasket destinationWorkbasket = - workbasketService.getWorkbasket(destinationWorkbasketKey, destinationWorkbasketDomain); + List taskSummaries = taskMapper.findExistingTasks(taskIds, null); + removeNotTransferableTasks(taskIds, taskSummaries, bulkLog); + updateTransferableTasks(taskIds, taskSummaries, destinationWorkbasket, setTransferFlag); - return transferTasks(taskIds, destinationWorkbasket, setTransferFlag); + return bulkLog; } finally { taskanaEngine.returnConnection(); } } - BulkOperationResults transferTasks( - String destinationWorkbasketId, List taskIds, boolean setTransferFlag) - throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException { - try { - taskanaEngine.openConnection(); - - // Check pre-conditions with trowing Exceptions - if (destinationWorkbasketId == null || destinationWorkbasketId.isEmpty()) { - throw new InvalidArgumentException("DestinationWorkbasketId must not be null or empty."); - } - Workbasket destinationWorkbasket = workbasketService.getWorkbasket(destinationWorkbasketId); - - return transferTasks(taskIds, destinationWorkbasket, setTransferFlag); - } finally { - taskanaEngine.returnConnection(); + private void checkPreconditionsForTransferTask( + Task task, WorkbasketSummary destinationWorkbasket, WorkbasketSummary originWorkbasket) + throws NotAuthorizedException, WorkbasketNotFoundException, InvalidStateException { + if (task.getState().isEndState()) { + throw new InvalidStateException(String.format(TASK_IN_END_STATE, task.getId())); } + workbasketService.checkAuthorization(originWorkbasket.getId(), WorkbasketPermission.TRANSFER); + checkDestinationWorkbasket(destinationWorkbasket); } - private BulkOperationResults transferTasks( - List taskIdsToBeTransferred, - Workbasket destinationWorkbasket, - boolean setTransferFlag) - throws InvalidArgumentException, WorkbasketNotFoundException, NotAuthorizedException { - + private void checkDestinationWorkbasket(WorkbasketSummary destinationWorkbasket) + throws NotAuthorizedException, WorkbasketNotFoundException { workbasketService.checkAuthorization( destinationWorkbasket.getId(), WorkbasketPermission.APPEND); - if (taskIdsToBeTransferred == null) { - throw new InvalidArgumentException("TaskIds must not be null."); + if (destinationWorkbasket.isMarkedForDeletion()) { + throw new WorkbasketNotFoundException( + destinationWorkbasket.getId(), + String.format(WORKBASKET_MARKED_FOR_DELETION, destinationWorkbasket.getId())); } - BulkOperationResults bulkLog = new BulkOperationResults<>(); - List taskIds = new ArrayList<>(taskIdsToBeTransferred); - taskService.removeNonExistingTasksFromTaskIdList(taskIds, bulkLog); - - if (taskIds.isEmpty()) { - throw new InvalidArgumentException("TaskIds must not contain only invalid arguments."); - } - - List taskSummaries; - taskSummaries = taskMapper.findExistingTasks(taskIds, null); - checkIfTransferConditionsAreFulfilled(taskIds, taskSummaries, bulkLog); - updateTasksToBeTransferred(taskIds, taskSummaries, destinationWorkbasket, setTransferFlag); - return bulkLog; } - private void checkIfTransferConditionsAreFulfilled( + private void removeNotTransferableTasks( List taskIds, List taskSummaries, BulkOperationResults bulkLog) { + List sourceWorkbaskets = + getSourceWorkbasketsWithTransferPermission(taskSummaries); + + taskIds.removeIf(id -> !taskIsTransferable(id, taskSummaries, sourceWorkbaskets, bulkLog)); + taskSummaries.removeIf(task -> !taskIds.contains(task.getTaskId())); + } + + private List getSourceWorkbasketsWithTransferPermission( + List taskSummaries) { + Set workbasketIds = + taskSummaries.stream().map(MinimalTaskSummary::getWorkbasketId).collect(Collectors.toSet()); - Set workbasketIds = new HashSet<>(); - taskSummaries.forEach(t -> workbasketIds.add(t.getWorkbasketId())); WorkbasketQueryImpl query = (WorkbasketQueryImpl) workbasketService.createWorkbasketQuery(); query.setUsedToAugmentTasks(true); - List sourceWorkbaskets; - if (taskSummaries.isEmpty()) { - sourceWorkbaskets = new ArrayList<>(); - } else { - sourceWorkbaskets = + + List sourceWorkbaskets = new ArrayList<>(); + if (!workbasketIds.isEmpty()) { + sourceWorkbaskets.addAll( query .callerHasPermission(WorkbasketPermission.TRANSFER) .idIn(workbasketIds.toArray(new String[0])) - .list(); + .list()); } - checkIfTasksMatchTransferCriteria(taskIds, taskSummaries, sourceWorkbaskets, bulkLog); + return sourceWorkbaskets; } - private void checkIfTasksMatchTransferCriteria( - List taskIds, + private boolean taskIsTransferable( + String currentTaskId, List taskSummaries, List sourceWorkbaskets, BulkOperationResults bulkLog) { + if (currentTaskId == null || currentTaskId.isEmpty()) { + return false; + } + MinimalTaskSummary currentTaskSummary = + taskSummaries.stream() + .filter(t -> currentTaskId.equals(t.getTaskId())) + .findFirst() + .orElse(null); - Iterator taskIdIterator = taskIds.iterator(); - while (taskIdIterator.hasNext()) { - String currentTaskId = taskIdIterator.next(); - MinimalTaskSummary taskSummary = - taskSummaries.stream() - .filter(t -> currentTaskId.equals(t.getTaskId())) - .findFirst() - .orElse(null); - if (taskSummary == null) { - bulkLog.addError( - currentTaskId, - new TaskNotFoundException( - currentTaskId, TASK_WITH_ID + currentTaskId + WAS_NOT_FOUND2)); - taskIdIterator.remove(); - } else if (taskSummary.getTaskState().isEndState()) { - bulkLog.addError( - currentTaskId, - new InvalidStateException( - String.format(TASK_IN_END_STATE_WITH_ID_CANNOT_BE_TRANSFERRED, currentTaskId))); - taskIdIterator.remove(); - } else if (sourceWorkbaskets.stream() - .noneMatch(wb -> taskSummary.getWorkbasketId().equals(wb.getId()))) { - bulkLog.addError( - currentTaskId, - new NotAuthorizedException( - "The workbasket of this task got not TRANSFER permissions. TaskId=" + currentTaskId, - taskanaEngine.getEngine().getCurrentUserContext().getUserid())); - taskIdIterator.remove(); + if (currentTaskSummary == null) { + bulkLog.addError( + currentTaskId, + new TaskNotFoundException(currentTaskId, String.format(TASK_NOT_FOUND, currentTaskId))); + return false; + } else if (currentTaskSummary.getTaskState().isEndState()) { + bulkLog.addError( + currentTaskId, + new InvalidStateException(String.format(TASK_IN_END_STATE, currentTaskId))); + return false; + } else if (sourceWorkbaskets.stream() + .noneMatch(wb -> currentTaskSummary.getWorkbasketId().equals(wb.getId()))) { + bulkLog.addError( + currentTaskId, + new NotAuthorizedException( + String.format(WORKBASKET_WITHOUT_TRANSFER_PERMISSION, currentTaskId), + taskanaEngine.getEngine().getCurrentUserContext().getUserid())); + return false; + } + return true; + } + + private void updateTransferableTasks( + List taskIds, + List taskSummaries, + WorkbasketSummary destinationWorkbasket, + boolean setTransferFlag) { + if (!taskIds.isEmpty()) { + TaskImpl updateObject = new TaskImpl(); + modifyTaskParameters(updateObject, destinationWorkbasket, setTransferFlag); + taskMapper.updateTransfered(taskIds, updateObject); + + if (HistoryEventManager.isHistoryEnabled()) { + taskSummaries.forEach( + task -> { + updateObject.setId(task.getTaskId()); + createTransferredEvent( + updateObject, + task.getWorkbasketId(), + updateObject.getWorkbasketSummary().getId()); + }); } } } - private void createTaskTransferredEvent( - Task task, String oldWorkbasketId, String newWorkbasketId) { + private void modifyTaskParameters( + TaskImpl task, WorkbasketSummary workbasket, boolean setTransferFlag) { + task.setRead(false); + task.setTransferred(setTransferFlag); + task.setState(TaskState.READY); + task.setOwner(null); + task.setWorkbasketSummary(workbasket); + task.setDomain(workbasket.getDomain()); + task.setModified(Instant.now()); + } + + private void createTransferredEvent( + Task task, String originWorkbasketId, String destinationWorkbasketId) { historyEventManager.createEvent( new TaskTransferredEvent( IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_TASK_HISTORY_EVENT), task, - oldWorkbasketId, - newWorkbasketId, + originWorkbasketId, + destinationWorkbasketId, taskanaEngine.getEngine().getCurrentUserContext().getUserid())); } - - private void updateTasksToBeTransferred( - List taskIds, - List taskSummaries, - Workbasket destinationWorkbasket, - boolean setTransferFlag) { - - taskSummaries = - taskSummaries.stream() - .filter(ts -> taskIds.contains(ts.getTaskId())) - .collect(Collectors.toList()); - if (!taskSummaries.isEmpty()) { - Instant now = Instant.now(); - TaskSummaryImpl updateObject = new TaskSummaryImpl(); - updateObject.setRead(false); - updateObject.setTransferred(setTransferFlag); - updateObject.setWorkbasketSummary(destinationWorkbasket.asSummary()); - updateObject.setDomain(destinationWorkbasket.getDomain()); - updateObject.setModified(now); - updateObject.setState(TaskState.READY); - updateObject.setOwner(null); - taskMapper.updateTransfered(taskIds, updateObject); - if (HistoryEventManager.isHistoryEnabled()) { - createTasksTransferredEvents(taskSummaries, updateObject); - } - } - } - - private void createTasksTransferredEvents( - List taskSummaries, TaskSummaryImpl updateObject) { - taskSummaries.forEach( - task -> { - TaskImpl transferredTask = (TaskImpl) taskService.newTask(task.getWorkbasketId()); - transferredTask.setId(task.getTaskId()); - transferredTask.setRead(updateObject.isRead()); - transferredTask.setTransferred(updateObject.isTransferred()); - transferredTask.setWorkbasketSummary(updateObject.getWorkbasketSummary()); - transferredTask.setDomain(updateObject.getDomain()); - transferredTask.setModified(updateObject.getModified()); - transferredTask.setState(updateObject.getState()); - transferredTask.setOwner(updateObject.getOwner()); - createTaskTransferredEvent( - transferredTask, task.getWorkbasketId(), updateObject.getWorkbasketSummary().getId()); - }); - } } diff --git a/lib/taskana-core/src/test/java/acceptance/jobs/TaskCleanupJobAccTest.java b/lib/taskana-core/src/test/java/acceptance/jobs/TaskCleanupJobAccTest.java index b71784e91..0c8c51005 100644 --- a/lib/taskana-core/src/test/java/acceptance/jobs/TaskCleanupJobAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/jobs/TaskCleanupJobAccTest.java @@ -53,7 +53,7 @@ class TaskCleanupJobAccTest extends AbstractAccTest { taskService.completeTask(taskId); long totalTasksCount = taskService.createTaskQuery().count(); - assertThat(totalTasksCount).isEqualTo(88); + assertThat(totalTasksCount).isEqualTo(89); taskanaEngine.getConfiguration().setTaskCleanupJobAllCompletedSameParentBusiness(false); @@ -61,14 +61,14 @@ class TaskCleanupJobAccTest extends AbstractAccTest { job.run(); totalTasksCount = taskService.createTaskQuery().count(); - assertThat(totalTasksCount).isEqualTo(69); + assertThat(totalTasksCount).isEqualTo(70); } @WithAccessId(user = "admin") @Test void shouldCleanCompletedTasksUntilDateWithSameParentBussiness() throws Exception { long totalTasksCount = taskService.createTaskQuery().count(); - assertThat(totalTasksCount).isEqualTo(87); + assertThat(totalTasksCount).isEqualTo(88); taskanaEngine.getConfiguration().setTaskCleanupJobAllCompletedSameParentBusiness(true); @@ -87,7 +87,7 @@ class TaskCleanupJobAccTest extends AbstractAccTest { job.run(); totalTasksCount = taskService.createTaskQuery().count(); - assertThat(totalTasksCount).isEqualTo(67); + assertThat(totalTasksCount).isEqualTo(68); } @WithAccessId(user = "admin") diff --git a/lib/taskana-core/src/test/java/acceptance/task/CancelTaskAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/CancelTaskAccTest.java index c307976e0..c8d5b5d50 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/CancelTaskAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/CancelTaskAccTest.java @@ -47,10 +47,10 @@ class CancelTaskAccTest extends AbstractAccTest { @Test void testCancelReadyTask() throws Exception { List taskSummaries = taskService.createTaskQuery().stateIn(TaskState.READY).list(); - assertThat(taskSummaries).hasSize(47); + assertThat(taskSummaries).hasSize(48); taskService.cancelTask(taskSummaries.get(0).getId()); long numTasks = taskService.createTaskQuery().stateIn(TaskState.READY).count(); - assertThat(numTasks).isEqualTo(46); + assertThat(numTasks).isEqualTo(47); numTasks = taskService.createTaskQuery().stateIn(TaskState.CANCELLED).count(); assertThat(numTasks).isEqualTo(6); } diff --git a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksAccTest.java index 7c5a72712..ee8a5b8ad 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksAccTest.java @@ -200,17 +200,17 @@ class QueryTasksAccTest extends AbstractAccTest { void testQueryForClassificationKey() { List results = TASK_SERVICE.createTaskQuery().classificationKeyLike("L10%").list(); - assertThat(results).hasSize(77); + assertThat(results).hasSize(78); String[] ids = results.stream().map(t -> t.getClassificationSummary().getKey()).toArray(String[]::new); List result2 = TASK_SERVICE.createTaskQuery().classificationKeyIn(ids).list(); - assertThat(result2).hasSize(77); + assertThat(result2).hasSize(78); List result3 = TASK_SERVICE.createTaskQuery().classificationKeyNotIn("T2100", "T2000").list(); - assertThat(result3).hasSize(82); + assertThat(result3).hasSize(83); List result4 = TASK_SERVICE.createTaskQuery().classificationKeyNotIn("L1050", "L1060", "T2100").list(); @@ -290,7 +290,7 @@ class QueryTasksAccTest extends AbstractAccTest { new Triplet<>(TaskCustomField.CUSTOM_11, new String[] {"%"}, 3), new Triplet<>(TaskCustomField.CUSTOM_12, new String[] {"%"}, 3), new Triplet<>(TaskCustomField.CUSTOM_13, new String[] {"%"}, 3), - new Triplet<>(TaskCustomField.CUSTOM_14, new String[] {"%"}, 87), + new Triplet<>(TaskCustomField.CUSTOM_14, new String[] {"%"}, 88), new Triplet<>(TaskCustomField.CUSTOM_15, new String[] {"%"}, 3), new Triplet<>(TaskCustomField.CUSTOM_16, new String[] {"%"}, 3)); assertThat(list).hasSameSizeAs(TaskCustomField.values()); @@ -402,9 +402,9 @@ class QueryTasksAccTest extends AbstractAccTest { void testQueryAllPaged() { TaskQuery taskQuery = TASK_SERVICE.createTaskQuery(); long numberOfTasks = taskQuery.count(); - assertThat(numberOfTasks).isEqualTo(87); + assertThat(numberOfTasks).isEqualTo(88); List tasks = taskQuery.orderByDue(DESCENDING).list(); - assertThat(tasks).hasSize(87); + assertThat(tasks).hasSize(88); List tasksp = taskQuery.orderByDue(DESCENDING).listPage(4, 5); assertThat(tasksp).hasSize(5); tasksp = taskQuery.orderByDue(DESCENDING).listPage(5, 5); diff --git a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByObjectReferenceAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByObjectReferenceAccTest.java index e40677198..5efd77b74 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByObjectReferenceAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByObjectReferenceAccTest.java @@ -44,7 +44,7 @@ class QueryTasksByObjectReferenceAccTest extends AbstractAccTest { objectReference.setType("SDNR"); List results = TASK_SERVICE.createTaskQuery().primaryObjectReferenceIn(objectReference).list(); - assertThat(results).hasSize(45); + assertThat(results).hasSize(46); } @WithAccessId(user = "admin") @@ -89,7 +89,7 @@ class QueryTasksByObjectReferenceAccTest extends AbstractAccTest { .createTaskQuery() .primaryObjectReferenceIn(objectReference, objectReference1) .list(); - assertThat(results).hasSize(56); + assertThat(results).hasSize(57); } @WithAccessId(user = "admin") diff --git a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByRoleAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByRoleAccTest.java index c7bd65fbc..04e1652cb 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByRoleAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByRoleAccTest.java @@ -43,14 +43,14 @@ class QueryTasksByRoleAccTest extends AbstractAccTest { switch (taskanaEngine.getCurrentUserContext().getUserid()) { case "admin": case "taskadmin": - expectedSize = 87; + expectedSize = 88; break; case "businessadmin": case "monitor": expectedSize = 0; break; case "teamlead-1": - expectedSize = 25; + expectedSize = 26; break; case "user-1-1": expectedSize = 7; diff --git a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByTimeIntervalsAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByTimeIntervalsAccTest.java index 38e517f58..10a947685 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByTimeIntervalsAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByTimeIntervalsAccTest.java @@ -88,7 +88,7 @@ class QueryTasksByTimeIntervalsAccTest extends AbstractAccTest { List results = taskService.createTaskQuery().createdWithin(interval1).orderByCreated(asc).list(); - assertThat(results).hasSize(51); + assertThat(results).hasSize(52); TaskSummary previousSummary = null; for (TaskSummary taskSummary : results) { Instant cr = taskSummary.getCreated(); diff --git a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByWildcardSearchAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByWildcardSearchAccTest.java index 0c7a2a268..8c2cbba4b 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByWildcardSearchAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksByWildcardSearchAccTest.java @@ -95,7 +95,7 @@ class QueryTasksByWildcardSearchAccTest extends AbstractAccTest { .wildcardSearchValueLike("%wid%") .list(); - assertThat(foundTasksCaseSensitive).hasSize(80); + assertThat(foundTasksCaseSensitive).hasSize(81); assertThat(foundTasksCaseInsensitive).containsExactlyElementsOf(foundTasksCaseSensitive); } diff --git a/lib/taskana-core/src/test/java/acceptance/task/SetOwnerAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/SetOwnerAccTest.java index b56fb2dde..de50a7d08 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/SetOwnerAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/SetOwnerAccTest.java @@ -162,7 +162,7 @@ class SetOwnerAccTest extends AbstractAccTest { allTaskSummaries.stream().map(TaskSummary::getId).collect(Collectors.toList()); BulkOperationResults results = taskanaEngine.getTaskService().setOwnerOfTasks("theWorkaholic", allTaskIds); - assertThat(allTaskSummaries).hasSize(87); + assertThat(allTaskSummaries).hasSize(88); assertThat(results.containsErrors()).isTrue(); Condition invalidStateException = @@ -171,11 +171,11 @@ class SetOwnerAccTest extends AbstractAccTest { new Condition<>( c -> c.getClass() == NotAuthorizedException.class, "NotAuthorizedException"); assertThat(results.getErrorMap()) - .hasSize(85) + .hasSize(86) .extractingFromEntries(Entry::getValue) .hasOnlyElementsOfTypes(InvalidStateException.class, NotAuthorizedException.class) .areExactly(28, invalidStateException) - .areExactly(57, notAuthorizedException); + .areExactly(58, notAuthorizedException); } @WithAccessId(user = "admin") @@ -187,7 +187,7 @@ class SetOwnerAccTest extends AbstractAccTest { allTaskSummaries.stream().map(TaskSummary::getId).collect(Collectors.toList()); BulkOperationResults results = taskanaEngine.getTaskService().setOwnerOfTasks("theWorkaholic", allTaskIds); - assertThat(allTaskSummaries).hasSize(87); + assertThat(allTaskSummaries).hasSize(88); assertThat(results.containsErrors()).isTrue(); assertThat(results.getErrorMap()) .hasSize(40) diff --git a/lib/taskana-core/src/test/java/acceptance/task/TerminateTaskAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/TerminateTaskAccTest.java index ba1712fe0..f34c0a5db 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/TerminateTaskAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/TerminateTaskAccTest.java @@ -48,10 +48,10 @@ class TerminateTaskAccTest extends AbstractAccTest { @TestTemplate void should_TerminateTask_When_TaskStateIsReady() throws Exception { List taskSummaries = taskService.createTaskQuery().stateIn(TaskState.READY).list(); - assertThat(taskSummaries).hasSize(47); + assertThat(taskSummaries).hasSize(48); taskService.terminateTask(taskSummaries.get(0).getId()); long numTasks = taskService.createTaskQuery().stateIn(TaskState.READY).count(); - assertThat(numTasks).isEqualTo(46); + assertThat(numTasks).isEqualTo(47); numTasks = taskService.createTaskQuery().stateIn(TaskState.TERMINATED).count(); assertThat(numTasks).isEqualTo(6); } diff --git a/lib/taskana-core/src/test/java/acceptance/task/TransferTaskAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/TransferTaskAccTest.java index 576997b52..4fa559859 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/TransferTaskAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/TransferTaskAccTest.java @@ -139,7 +139,7 @@ class TransferTaskAccTest extends AbstractAccTest { ThrowingCallable call = () -> { - taskService.transfer("Invalid", "WBI:100000000000000000000000000000000006"); + taskService.transfer("Invalid", "WBI:100000000000000000000000000000000005"); }; assertThatThrownBy(call).isInstanceOf(TaskNotFoundException.class); } @@ -242,22 +242,21 @@ class TransferTaskAccTest extends AbstractAccTest { ArrayList taskIdList = new ArrayList<>(); taskIdList.add("TKI:000000000000000000000000000000000006"); // working taskIdList.add("TKI:000000000000000000000000000000000041"); // NotAuthorized READ - taskIdList.add("TKI:200000000000000000000000000000000006"); // NotAuthorized TRANSFER + taskIdList.add("TKI:200000000000000000000000000000000008"); // NotAuthorized TRANSFER taskIdList.add(""); // InvalidArgument - taskIdList.add(null); // InvalidArgument (added with ""), duplicate - taskIdList.add("TKI:000000000000000000000000000000000099"); // TaskNotFound + taskIdList.add(null); // InvalidArgument + taskIdList.add("TKI:000000000000000000000000000000000099"); // not existing taskIdList.add("TKI:100000000000000000000000000000000006"); // already completed BulkOperationResults results = taskService.transferTasks("WBI:100000000000000000000000000000000006", taskIdList); // check for exceptions in bulk assertThat(results.containsErrors()).isTrue(); - assertThat(results.getErrorMap().values()).hasSize(5); + assertThat(results.getErrorMap().values()).hasSize(4); assertThat(results.getErrorForId("TKI:000000000000000000000000000000000041").getClass()) .isEqualTo(NotAuthorizedException.class); - assertThat(results.getErrorForId("TKI:200000000000000000000000000000000006").getClass()) - .isEqualTo(InvalidStateException.class); - assertThat(InvalidArgumentException.class).isEqualTo(results.getErrorForId("").getClass()); + assertThat(results.getErrorForId("TKI:200000000000000000000000000000000008").getClass()) + .isEqualTo(NotAuthorizedException.class); assertThat(results.getErrorForId("TKI:000000000000000000000000000000000099").getClass()) .isEqualTo(TaskNotFoundException.class); assertThat(results.getErrorForId("TKI:100000000000000000000000000000000006").getClass()) @@ -274,15 +273,10 @@ class TransferTaskAccTest extends AbstractAccTest { assertThat(transferredTask.getModified().isBefore(before)).isFalse(); assertThat(transferredTask.getOwner()).isNull(); - transferredTask = taskService.getTask("TKI:000000000000000000000000000000000002"); + transferredTask = taskService.getTask("TKI:200000000000000000000000000000000008"); assertThat(transferredTask).isNotNull(); assertThat(transferredTask.isTransferred()).isFalse(); - assertThat(transferredTask.getWorkbasketKey()).isEqualTo("USER-1-1"); - - transferredTask = taskService.getTask("TKI:200000000000000000000000000000000006"); - assertThat(transferredTask).isNotNull(); - assertThat(transferredTask.isTransferred()).isFalse(); - assertThat(transferredTask.getWorkbasketKey()).isEqualTo("TEAMLEAD-2"); + assertThat(transferredTask.getWorkbasketKey()).isEqualTo("TPK_VIP"); transferredTask = taskService.getTask("TKI:100000000000000000000000000000000006"); assertThat(transferredTask).isNotNull(); @@ -331,24 +325,21 @@ class TransferTaskAccTest extends AbstractAccTest { () -> taskService.transferTasks("WBI:100000000000000000000000000000000006", null); assertThatThrownBy(call) .isInstanceOf(InvalidArgumentException.class) - .hasMessage("TaskIds must not be null."); + .hasMessage("TaskIds must not be null or empty."); } @WithAccessId(user = "teamlead-1", groups = GROUP_1_DN) @Test - void should_ThrowException_When_TransferringTasksWithOnlyInvalidTasksIds() { + void should_ThrowException_When_TransferringTasksWithOnlyInvalidTasksIds() throws Exception { TaskService taskService = taskanaEngine.getTaskService(); // test with list containing only invalid arguments - ThrowingCallable call = - () -> - taskService.transferTasks( - "WBI:100000000000000000000000000000000006", - /* we can't use List.of because of the null value we insert */ - Arrays.asList("", "", "", null)); - assertThatThrownBy(call) - .isInstanceOf(InvalidArgumentException.class) - .hasMessage("TaskIds must not contain only invalid arguments."); + BulkOperationResults bulklog = + taskService.transferTasks( + "WBI:100000000000000000000000000000000006", + /* we can't use List.of because of the null value we insert */ + Arrays.asList("", "", "", null)); + assertThat(bulklog.getFailedIds()).isEmpty(); } @WithAccessId(user = "teamlead-1", groups = GROUP_1_DN)