Skip to content

Commit

Permalink
Closes Taskana#2491: Set Owner of Task when Transferring
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesrdi committed Feb 23, 2024
1 parent 6ddb86f commit 072d1e0
Show file tree
Hide file tree
Showing 10 changed files with 902 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,156 @@ Stream<DynamicTest> should_CreateTransferredHistoryEvents_When_TaskBulkTransfer(
return DynamicTest.stream(testCases.iterator(), Triplet::getLeft, test);
}

@WithAccessId(user = "admin")
@TestFactory
Stream<DynamicTest> should_CreateTransferredHistoryEvent_When_TaskIsTransferredWithOwner() {
List<Quadruple<String, String, String, Consumer<String>>> testCases =
List.of(
/*
The workbasketId of the source Workbasket is parametrized. Putting the tested Tasks
into the same Workbasket would result in changes to the test data. This would require
changing tests that already use the tested Tasks. That's why workbasketId is
parametrized.
*/
Quadruple.of(
"Using WorkbasketId; Task doesn't have an Attachment"
+ " or any secondary Object References",
"TKI:000000000000000000000000000000000005",
"WBI:100000000000000000000000000000000001",
wrap(
(String taskId) ->
taskService.transferWithOwner(
taskId, "WBI:100000000000000000000000000000000007", "USER-1-2"))),
Quadruple.of(
"Using WorkbasketId; Task has Attachment and secondary Object Reference",
"TKI:000000000000000000000000000000000001",
"WBI:100000000000000000000000000000000006",
wrap(
(String taskId) ->
taskService.transferWithOwner(
taskId, "WBI:100000000000000000000000000000000007", "USER-1-2"))),
Quadruple.of(
"Using WorkbasketKey and Domain",
"TKI:000000000000000000000000000000000006",
"WBI:100000000000000000000000000000000001",
wrap(
(String taskId) ->
taskService.transferWithOwner(
taskId, "USER-1-2", "DOMAIN_A", "USER-1-2"))));
ThrowingConsumer<Quadruple<String, String, String, Consumer<String>>> test =
q -> {
String taskId = q.getSecond();
Consumer<String> transferMethod = q.getFourth();

TaskHistoryQueryMapper taskHistoryQueryMapper = getHistoryQueryMapper();

List<TaskHistoryEvent> events =
taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId));

assertThat(events).isEmpty();

transferMethod.accept(taskId);

events =
taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId));

assertThat(events).hasSize(1);
String sourceWorkbasketId = q.getThird();
assertTransferHistoryEvent(
events.get(0).getId(),
sourceWorkbasketId,
"WBI:100000000000000000000000000000000007",
"admin");
};
return DynamicTest.stream(testCases.iterator(), Quadruple::getFirst, test);
}

@WithAccessId(user = "admin")
@TestFactory
Stream<DynamicTest> should_CreateTransferredHistoryEvents_When_TaskBulkTransferWithOwner() {
List<Triplet<String, Map<String, String>, Consumer<List<String>>>> testCases =
List.of(
/*
The workbasketId of the source Workbasket is parametrized. Putting the tested Tasks
into the same Workbasket would result in changes to the test data. This would require
changing tests that already use the tested Tasks. That's why workbasketId is
parametrized.
*/
Triplet.of(
"Using WorkbasketId",
Map.ofEntries(
Map.entry(
"TKI:000000000000000000000000000000000010",
"WBI:100000000000000000000000000000000001"),
Map.entry(
"TKI:000000000000000000000000000000000011",
"WBI:100000000000000000000000000000000001"),
Map.entry(
"TKI:000000000000000000000000000000000012",
"WBI:100000000000000000000000000000000001")),
wrap(
(List<String> taskIds) ->
taskService.transferTasksWithOwner(
"WBI:100000000000000000000000000000000007", taskIds, "user-1-2"))),
Triplet.of(
"Using WorkbasketKey and Domain",
Map.ofEntries(
Map.entry(
"TKI:000000000000000000000000000000000013",
"WBI:100000000000000000000000000000000001"),
Map.entry(
"TKI:000000000000000000000000000000000014",
"WBI:100000000000000000000000000000000001"),
Map.entry(
"TKI:000000000000000000000000000000000015",
"WBI:100000000000000000000000000000000001")),
wrap(
(List<String> taskIds) ->
taskService.transferTasksWithOwner(
"USER-1-2", "DOMAIN_A", taskIds, "USER-1-2"))));
ThrowingConsumer<Triplet<String, Map<String, String>, Consumer<List<String>>>> test =
t -> {
Map<String, String> taskIds = t.getMiddle();
Consumer<List<String>> transferMethod = t.getRight();

TaskHistoryQueryMapper taskHistoryQueryMapper = getHistoryQueryMapper();

List<TaskHistoryEvent> events =
taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl)
historyService
.createTaskHistoryQuery()
.taskIdIn(taskIds.keySet().toArray(new String[0])));

assertThat(events).isEmpty();

transferMethod.accept(new ArrayList<>(taskIds.keySet()));

events =
taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl)
historyService
.createTaskHistoryQuery()
.taskIdIn(taskIds.keySet().toArray(new String[0])));

assertThat(events)
.extracting(TaskHistoryEvent::getTaskId)
.containsExactlyInAnyOrderElementsOf(taskIds.keySet());

for (TaskHistoryEvent event : events) {
assertTransferHistoryEvent(
event.getId(),
taskIds.get(event.getTaskId()),
"WBI:100000000000000000000000000000000007",
"admin");
}
};

return DynamicTest.stream(testCases.iterator(), Triplet::getLeft, test);
}

private void assertTransferHistoryEvent(
String eventId, String expectedOldValue, String expectedNewValue, String expectedUser)
throws Exception {
Expand Down
211 changes: 211 additions & 0 deletions lib/taskana-core/src/main/java/pro/taskana/task/api/TaskService.java
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,11 @@ Task terminateTask(String taskId)
* Transfers a {@linkplain Task} to another {@linkplain Workbasket} while always setting
* {@linkplain Task#isTransferred() isTransferred} to true.
*
* @param taskId the {@linkplain Task#getId() id} of the {@linkplain Task} which should be
* transferred
* @param destinationWorkbasketId the {@linkplain Workbasket#getId() id} of the target {@linkplain
* Workbasket}
* @return the transferred {@linkplain Task}
* @see #transfer(String, String, boolean)
*/
@SuppressWarnings("checkstyle:JavadocMethod")
Expand Down Expand Up @@ -513,6 +518,13 @@ Task transfer(String taskId, String destinationWorkbasketId, boolean setTransfer
* Transfers a {@linkplain Task} to another {@linkplain Workbasket} while always setting
* {@linkplain Task#isTransferred isTransferred} .
*
* @param taskId the {@linkplain Task#getId() id} of the {@linkplain Task} which should be
* transferred
* @param workbasketKey the {@linkplain Workbasket#getKey() key} of the target {@linkplain
* Workbasket}
* @param domain the {@linkplain Workbasket#getDomain() domain} of the target {@linkplain
* Workbasket}
* @return the transferred {@linkplain Task}
* @see #transfer(String, String, String, boolean)
*/
@SuppressWarnings("checkstyle:JavadocMethod")
Expand Down Expand Up @@ -553,6 +565,111 @@ Task transfer(String taskId, String workbasketKey, String domain, boolean setTra
NotAuthorizedOnWorkbasketException,
InvalidTaskStateException;

/**
* Transfers a {@linkplain Task} to another {@linkplain Workbasket} and set owner of {@linkplain
* Task} in the new {@linkplain Workbasket} to {@param owner} while always setting {@linkplain
* Task#isTransferred() isTransferred} to true.
*
* @param taskId the {@linkplain Task#getId() id} of the {@linkplain Task} which should be
* transferred
* @param destinationWorkbasketId the {@linkplain Workbasket#getId() id} of the target {@linkplain
* Workbasket}
* @param owner the owner of the transferred {@linkplain Task} in the new workbasket
* @return the transferred {@linkplain Task}
* @see #transferWithOwner(String, String, String, boolean)
*/
@SuppressWarnings("checkstyle:JavadocMethod")
default Task transferWithOwner(String taskId, String destinationWorkbasketId, String owner)
throws TaskNotFoundException,
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException,
InvalidTaskStateException {
return transferWithOwner(taskId, destinationWorkbasketId, owner, true);
}

/**
* Transfers a {@linkplain Task} to another {@linkplain Workbasket} and set owner.
*
* <p>The transfer resets {@linkplain Task#isRead() isRead} and sets {@linkplain
* Task#isTransferred() isTransferred} if setTransferFlag is true.
*
* @param taskId the {@linkplain Task#getId() id} of the {@linkplain Task} which should be
* transferred
* @param destinationWorkbasketId the {@linkplain Workbasket#getId() id} of the target {@linkplain
* Workbasket}
* @param owner the owner of the transferred {@linkplain Task} in the new workbasket
* @param setTransferFlag controls whether to set {@linkplain Task#isTransferred() isTransferred}
* to true or not
* @return the transferred {@linkplain Task}
* @throws TaskNotFoundException if the {@linkplain Task} with taskId wasn't found
* @throws WorkbasketNotFoundException if the target {@linkplain Workbasket} was not found
* @throws NotAuthorizedOnWorkbasketException if the current user has no {@linkplain
* WorkbasketPermission#READ} for the source {@linkplain Workbasket} or no {@linkplain
* WorkbasketPermission#TRANSFER} for the target {@linkplain Workbasket}
* @throws InvalidTaskStateException if the {@linkplain Task} is in one of the {@linkplain
* TaskState#END_STATES}
*/
Task transferWithOwner(
String taskId, String destinationWorkbasketId, String owner, boolean setTransferFlag)
throws TaskNotFoundException,
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException,
InvalidTaskStateException;

/**
* Transfers a {@linkplain Task} to another {@linkplain Workbasket} and set owner of {@linkplain
* Task} in new {@linkplain Workbasket} to {@param owner} while always setting {@linkplain
* Task#isTransferred isTransferred} .
*
* @param taskId the {@linkplain Task#getId() id} of the {@linkplain Task} which should be
* transferred
* @param workbasketKey the {@linkplain Workbasket#getKey() key} of the target {@linkplain
* Workbasket}
* @param domain the {@linkplain Workbasket#getDomain() domain} of the target {@linkplain
* Workbasket}
* @param owner the owner of the transferred {@linkplain Task} in the new workbasket
* @see #transferWithOwner(String, String, String, String, boolean)
*/
@SuppressWarnings("checkstyle:JavadocMethod")
default Task transferWithOwner(String taskId, String workbasketKey, String domain, String owner)
throws TaskNotFoundException,
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException,
InvalidTaskStateException {
return transferWithOwner(taskId, workbasketKey, domain, owner, true);
}

/**
* Transfers a {@linkplain Task} to another {@linkplain Workbasket} and set owner.
*
* <p>The transfer resets {@linkplain Task#isRead() isRead} and sets {@linkplain
* Task#isTransferred() isTransferred} if setTransferFlag is true.
*
* @param taskId the {@linkplain Task#getId() id} of the {@linkplain Task} which should be
* transferred
* @param workbasketKey the {@linkplain Workbasket#getKey() key} of the target {@linkplain
* Workbasket}
* @param domain the {@linkplain Workbasket#getDomain() domain} of the target {@linkplain
* Workbasket}
* @param owner the owner of the transferred {@linkplain Task} in the new workbasket
* @param setTransferFlag controls whether to set {@linkplain Task#isTransferred() isTransferred}
* or not
* @return the transferred {@linkplain Task}
* @throws TaskNotFoundException if the {@linkplain Task} with taskId was not found
* @throws WorkbasketNotFoundException if the target {@linkplain Workbasket} was not found
* @throws NotAuthorizedOnWorkbasketException if the current user has no {@linkplain
* WorkbasketPermission#READ} for the source {@linkplain Workbasket} or no {@linkplain
* WorkbasketPermission#TRANSFER} for the target {@linkplain Workbasket}
* @throws InvalidTaskStateException if the {@linkplain Task} is in one of the {@linkplain
* TaskState#END_STATES}
*/
Task transferWithOwner(
String taskId, String workbasketKey, String domain, String owner, boolean setTransferFlag)
throws TaskNotFoundException,
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException,
InvalidTaskStateException;

/**
* Transfers a List of {@linkplain Task Tasks} to another {@linkplain Workbasket} while always
* setting {@linkplain Task#isTransferred isTransferred} to true.
Expand Down Expand Up @@ -639,6 +756,100 @@ BulkOperationResults<String, TaskanaException> transferTasks(
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException;

/**
* Transfers a List of {@linkplain Task Tasks} to another {@linkplain Workbasket} and set owner to
* {@param owner} while always setting {@linkplain Task#isTransferred isTransferred} to true.
*
* @see #transferTasksWithOwner(String, List, String, boolean)
*/
@SuppressWarnings("checkstyle:JavadocMethod")
default BulkOperationResults<String, TaskanaException> transferTasksWithOwner(
String destinationWorkbasketId, List<String> taskIds, String owner)
throws InvalidArgumentException,
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException {
return transferTasksWithOwner(destinationWorkbasketId, taskIds, owner, true);
}

/**
* Transfers a List of {@linkplain Task Tasks} to another {@linkplain Workbasket} and set the
* owner.
*
* <p>The transfer resets {@linkplain Task#isRead() isRead} and sets {@linkplain
* Task#isTransferred() isTransferred} if setTransferFlag is true. Exceptions will be thrown if
* the caller got no {@linkplain WorkbasketPermission} on the target or if the target {@linkplain
* Workbasket} doesn't exist. Other Exceptions will be stored and returned in the end.
*
* @param destinationWorkbasketId {@linkplain Workbasket#getId() id} of the target {@linkplain
* Workbasket}
* @param taskIds List of source {@linkplain Task Tasks} which will be moved
* @param owner the new owner of the transferred tasks
* @param setTransferFlag controls whether to set {@linkplain Task#isTransferred() isTransferred}
* or not
* @return Bulkresult with {@linkplain Task#getId() ids} and Error for each failed transactions
* @throws NotAuthorizedOnWorkbasketException if the current user has no {@linkplain
* WorkbasketPermission#READ} for the source {@linkplain Workbasket} or no {@linkplain
* WorkbasketPermission#TRANSFER} for the target {@linkplain Workbasket}
* @throws InvalidArgumentException if the method parameters are empty or NULL
* @throws WorkbasketNotFoundException if the target {@linkplain Workbasket} can't be found
*/
BulkOperationResults<String, TaskanaException> transferTasksWithOwner(
String destinationWorkbasketId, List<String> taskIds, String owner, boolean setTransferFlag)
throws InvalidArgumentException,
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException;

/**
* Transfers a List of {@linkplain Task Tasks} to another {@linkplain Workbasket} and set owner
* while always setting {@linkplain Task#isTransferred() isTransferred} to true.
*
* @see #transferTasksWithOwner(String, String, List, String, boolean)
*/
@SuppressWarnings("checkstyle:JavadocMethod")
default BulkOperationResults<String, TaskanaException> transferTasksWithOwner(
String destinationWorkbasketKey,
String destinationWorkbasketDomain,
List<String> taskIds,
String owner)
throws InvalidArgumentException,
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException {
return transferTasksWithOwner(
destinationWorkbasketKey, destinationWorkbasketDomain, taskIds, owner, true);
}

/**
* Transfers a List of {@linkplain Task Tasks} to another {@linkplain Workbasket} and set owner.
*
* <p>The transfer resets {@linkplain Task#isRead() isRead} and sets {@linkplain
* Task#isTransferred() isTransferred} if setTransferFlag is true. Exceptions will be thrown if
* the caller got no {@linkplain WorkbasketPermission} on the target {@linkplain Workbasket} or if
* it doesn't exist. Other Exceptions will be stored and returned in the end.
*
* @param destinationWorkbasketKey target {@linkplain Workbasket#getKey() key}
* @param destinationWorkbasketDomain target {@linkplain Workbasket#getDomain() domain}
* @param taskIds List of {@linkplain Task#getId() ids} of source {@linkplain Task Tasks} which
* will be moved
* @param owner the new owner of the transferred tasks
* @param setTransferFlag controls whether to set {@linkplain Task#isTransferred() isTransferred}
* or not
* @return BulkResult with {@linkplain Task#getId() ids} and Error for each failed transactions
* @throws NotAuthorizedOnWorkbasketException if the current user has no {@linkplain
* WorkbasketPermission#READ} for the source {@linkplain Workbasket} or no {@linkplain
* WorkbasketPermission#TRANSFER} for the target {@linkplain Workbasket}
* @throws InvalidArgumentException if the method parameters are empty or NULL
* @throws WorkbasketNotFoundException if the target {@linkplain Workbasket} can't be found
*/
BulkOperationResults<String, TaskanaException> transferTasksWithOwner(
String destinationWorkbasketKey,
String destinationWorkbasketDomain,
List<String> taskIds,
String owner,
boolean setTransferFlag)
throws InvalidArgumentException,
WorkbasketNotFoundException,
NotAuthorizedOnWorkbasketException;

/**
* Update a {@linkplain Task}.
*
Expand Down
Loading

0 comments on commit 072d1e0

Please sign in to comment.