Closes #2496 : Set Owner of Tasks when Transferring
This commit is contained in:
parent
6ddb86fb89
commit
1de30e266b
|
@ -181,6 +181,90 @@ class CreateHistoryEventOnTaskTransferAccTest extends AbstractAccTest {
|
|||
return DynamicTest.stream(testCases.iterator(), Triplet::getLeft, 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 {
|
||||
|
|
|
@ -639,6 +639,100 @@ public interface TaskService {
|
|||
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}.
|
||||
*
|
||||
|
|
|
@ -631,6 +631,30 @@ public class TaskServiceImpl implements TaskService {
|
|||
taskIds, destinationWorkbasketKey, destinationWorkbasketDomain, setTransferFlag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkOperationResults<String, TaskanaException> transferTasksWithOwner(
|
||||
String destinationWorkbasketId, List<String> taskIds, String owner, boolean setTransferFlag)
|
||||
throws InvalidArgumentException,
|
||||
WorkbasketNotFoundException,
|
||||
NotAuthorizedOnWorkbasketException {
|
||||
return taskTransferrer.transferTasksWithOwner(
|
||||
taskIds, destinationWorkbasketId, owner, setTransferFlag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkOperationResults<String, TaskanaException> transferTasksWithOwner(
|
||||
String destinationWorkbasketKey,
|
||||
String destinationWorkbasketDomain,
|
||||
List<String> taskIds,
|
||||
String owner,
|
||||
boolean setTransferFlag)
|
||||
throws InvalidArgumentException,
|
||||
WorkbasketNotFoundException,
|
||||
NotAuthorizedOnWorkbasketException {
|
||||
return taskTransferrer.transferTasksWithOwner(
|
||||
taskIds, destinationWorkbasketKey, destinationWorkbasketDomain, owner, setTransferFlag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTask(String taskId)
|
||||
throws TaskNotFoundException,
|
||||
|
|
|
@ -86,7 +86,7 @@ final class TaskTransferrer {
|
|||
workbasketService.getWorkbasket(destinationWorkbasketId).asSummary();
|
||||
checkDestinationWorkbasket(destinationWorkbasket);
|
||||
|
||||
return transferMultipleTasks(taskIds, destinationWorkbasket, setTransferFlag);
|
||||
return transferMultipleTasks(taskIds, destinationWorkbasket, null, setTransferFlag);
|
||||
}
|
||||
|
||||
BulkOperationResults<String, TaskanaException> transfer(
|
||||
|
@ -101,7 +101,35 @@ final class TaskTransferrer {
|
|||
workbasketService.getWorkbasket(destinationWorkbasketKey, destinationDomain).asSummary();
|
||||
checkDestinationWorkbasket(destinationWorkbasket);
|
||||
|
||||
return transferMultipleTasks(taskIds, destinationWorkbasket, setTransferFlag);
|
||||
return transferMultipleTasks(taskIds, destinationWorkbasket, null, setTransferFlag);
|
||||
}
|
||||
|
||||
BulkOperationResults<String, TaskanaException> transferTasksWithOwner(
|
||||
List<String> taskIds, String destinationWorkbasketId, String owner, boolean setTransferFlag)
|
||||
throws WorkbasketNotFoundException,
|
||||
InvalidArgumentException,
|
||||
NotAuthorizedOnWorkbasketException {
|
||||
WorkbasketSummary destinationWorkbasket =
|
||||
workbasketService.getWorkbasket(destinationWorkbasketId).asSummary();
|
||||
checkDestinationWorkbasket(destinationWorkbasket);
|
||||
|
||||
return transferMultipleTasks(taskIds, destinationWorkbasket, owner, setTransferFlag);
|
||||
}
|
||||
|
||||
BulkOperationResults<String, TaskanaException> transferTasksWithOwner(
|
||||
List<String> taskIds,
|
||||
String destinationWorkbasketKey,
|
||||
String destinationDomain,
|
||||
String owner,
|
||||
boolean setTransferFlag)
|
||||
throws WorkbasketNotFoundException,
|
||||
InvalidArgumentException,
|
||||
NotAuthorizedOnWorkbasketException {
|
||||
WorkbasketSummary destinationWorkbasket =
|
||||
workbasketService.getWorkbasket(destinationWorkbasketKey, destinationDomain).asSummary();
|
||||
checkDestinationWorkbasket(destinationWorkbasket);
|
||||
|
||||
return transferMultipleTasks(taskIds, destinationWorkbasket, owner, setTransferFlag);
|
||||
}
|
||||
|
||||
private Task transferSingleTask(
|
||||
|
@ -120,7 +148,7 @@ final class TaskTransferrer {
|
|||
WorkbasketSummary originWorkbasket = task.getWorkbasketSummary();
|
||||
checkPreconditionsForTransferTask(task, destinationWorkbasket, originWorkbasket);
|
||||
|
||||
applyTransferValuesForTask(task, destinationWorkbasket, setTransferFlag);
|
||||
applyTransferValuesForTask(task, destinationWorkbasket, null, setTransferFlag);
|
||||
taskMapper.update(task);
|
||||
if (historyEventManager.isEnabled()) {
|
||||
createTransferredEvent(
|
||||
|
@ -136,6 +164,7 @@ final class TaskTransferrer {
|
|||
private BulkOperationResults<String, TaskanaException> transferMultipleTasks(
|
||||
List<String> taskToBeTransferred,
|
||||
WorkbasketSummary destinationWorkbasket,
|
||||
String owner,
|
||||
boolean setTransferFlag)
|
||||
throws InvalidArgumentException {
|
||||
if (taskToBeTransferred == null || taskToBeTransferred.isEmpty()) {
|
||||
|
@ -154,7 +183,7 @@ final class TaskTransferrer {
|
|||
() -> taskService.createTaskQuery().idIn(taskIds.toArray(new String[0])).list());
|
||||
taskSummaries =
|
||||
filterOutTasksWhichDoNotMatchTransferCriteria(taskIds, taskSummaries, bulkLog);
|
||||
updateTransferableTasks(taskSummaries, destinationWorkbasket, setTransferFlag);
|
||||
updateTransferableTasks(taskSummaries, destinationWorkbasket, owner, setTransferFlag);
|
||||
|
||||
return bulkLog;
|
||||
} finally {
|
||||
|
@ -254,6 +283,7 @@ final class TaskTransferrer {
|
|||
private void updateTransferableTasks(
|
||||
List<TaskSummary> taskSummaries,
|
||||
WorkbasketSummary destinationWorkbasket,
|
||||
String owner,
|
||||
boolean setTransferFlag) {
|
||||
Map<TaskState, List<TaskSummary>> summariesByState = groupTasksByState(taskSummaries);
|
||||
for (Map.Entry<TaskState, List<TaskSummary>> entry : summariesByState.entrySet()) {
|
||||
|
@ -262,7 +292,7 @@ final class TaskTransferrer {
|
|||
if (!taskSummariesWithSameGoalState.isEmpty()) {
|
||||
TaskImpl updateObject = new TaskImpl();
|
||||
updateObject.setState(goalState);
|
||||
applyTransferValuesForTask(updateObject, destinationWorkbasket, setTransferFlag);
|
||||
applyTransferValuesForTask(updateObject, destinationWorkbasket, owner, setTransferFlag);
|
||||
taskMapper.updateTransfered(
|
||||
taskSummariesWithSameGoalState.stream()
|
||||
.map(TaskSummary::getId)
|
||||
|
@ -275,7 +305,8 @@ final class TaskTransferrer {
|
|||
TaskSummaryImpl newSummary = (TaskSummaryImpl) oldSummary.copy();
|
||||
newSummary.setId(oldSummary.getId());
|
||||
newSummary.setExternalId(oldSummary.getExternalId());
|
||||
applyTransferValuesForTask(newSummary, destinationWorkbasket, setTransferFlag);
|
||||
applyTransferValuesForTask(
|
||||
newSummary, destinationWorkbasket, owner, setTransferFlag);
|
||||
|
||||
createTransferredEvent(
|
||||
oldSummary,
|
||||
|
@ -289,11 +320,11 @@ final class TaskTransferrer {
|
|||
}
|
||||
|
||||
private void applyTransferValuesForTask(
|
||||
TaskSummaryImpl task, WorkbasketSummary workbasket, boolean setTransferFlag) {
|
||||
TaskSummaryImpl task, WorkbasketSummary workbasket, String owner, boolean setTransferFlag) {
|
||||
task.setRead(false);
|
||||
task.setTransferred(setTransferFlag);
|
||||
task.setState(getStateAfterTransfer(task));
|
||||
task.setOwner(null);
|
||||
task.setOwner(owner);
|
||||
task.setWorkbasketSummary(workbasket);
|
||||
task.setDomain(workbasket.getDomain());
|
||||
task.setModified(Instant.now());
|
||||
|
|
|
@ -435,4 +435,140 @@ class TransferTaskAccTest extends AbstractAccTest {
|
|||
|
||||
assertThat(transferredTasks).extracting(TaskSummary::isTransferred).containsOnly(false);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "teamlead-1", groups = GROUP_1_DN)
|
||||
@Test
|
||||
void should_BulkTransferOnlyValidTasksAndSetOwner_When_SomeTasksToTransferCauseExceptions()
|
||||
throws Exception {
|
||||
final Workbasket wb =
|
||||
taskanaEngine
|
||||
.getWorkbasketService()
|
||||
.getWorkbasket("WBI:100000000000000000000000000000000009");
|
||||
final Instant before = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
List<String> taskIdList =
|
||||
Arrays.asList(
|
||||
"TKI:000000000000000000000000000000000007", // working
|
||||
"TKI:000000000000000000000000000000000041", // NotAuthorized READ
|
||||
"TKI:000000000000000000000000000000000041", // NotAuthorized READ
|
||||
"TKI:200000000000000000000000000000000008", // NotAuthorized TRANSFER
|
||||
"", // InvalidArgument
|
||||
null, // InvalidArgument
|
||||
"TKI:000000000000000000000000000000000099", // not existing
|
||||
"TKI:100000000000000000000000000000000006"); // already completed
|
||||
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.transferTasksWithOwner(
|
||||
"WBI:100000000000000000000000000000000009", taskIdList, "teamlead-1");
|
||||
|
||||
// check for exceptions in bulk
|
||||
assertThat(results.containsErrors()).isTrue();
|
||||
assertThat(results.getErrorMap().values()).hasSize(6);
|
||||
assertThat(results.getErrorForId("TKI:000000000000000000000000000000000041").getClass())
|
||||
.isEqualTo(NotAuthorizedOnWorkbasketException.class);
|
||||
assertThat(results.getErrorForId("TKI:200000000000000000000000000000000008").getClass())
|
||||
.isEqualTo(NotAuthorizedOnWorkbasketException.class);
|
||||
assertThat(results.getErrorForId("TKI:000000000000000000000000000000000099").getClass())
|
||||
.isEqualTo(TaskNotFoundException.class);
|
||||
assertThat(results.getErrorForId("TKI:100000000000000000000000000000000006").getClass())
|
||||
.isEqualTo(InvalidTaskStateException.class);
|
||||
assertThat(results.getErrorForId("").getClass()).isEqualTo(TaskNotFoundException.class);
|
||||
assertThat(results.getErrorForId(null).getClass()).isEqualTo(TaskNotFoundException.class);
|
||||
|
||||
// verify valid requests
|
||||
Task transferredTask = taskService.getTask("TKI:000000000000000000000000000000000007");
|
||||
assertThat(transferredTask).isNotNull();
|
||||
assertThat(transferredTask.isTransferred()).isTrue();
|
||||
assertThat(transferredTask.isRead()).isFalse();
|
||||
assertThat(transferredTask.getState()).isEqualTo(TaskState.READY);
|
||||
assertThat(transferredTask.getWorkbasketKey()).isEqualTo(wb.getKey());
|
||||
assertThat(transferredTask.getDomain()).isEqualTo(wb.getDomain());
|
||||
assertThat(transferredTask.getModified().isBefore(before)).isFalse();
|
||||
assertThat(transferredTask.getOwner()).isEqualTo("teamlead-1");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "teamlead-1", groups = GROUP_1_DN)
|
||||
@Test
|
||||
void should_BulkTransferTasksAndSetOwner_When_WorkbasketKeyAndDomainIsProvided()
|
||||
throws Exception {
|
||||
final Instant before = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
List<String> taskIdList =
|
||||
List.of(
|
||||
"TKI:000000000000000000000000000000000008", "TKI:000000000000000000000000000000000009");
|
||||
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.transferTasksWithOwner("GPK_B_KSC_1", "DOMAIN_B", taskIdList, "teamlead-1");
|
||||
assertThat(results.containsErrors()).isFalse();
|
||||
|
||||
final Workbasket wb =
|
||||
taskanaEngine.getWorkbasketService().getWorkbasket("GPK_B_KSC_1", "DOMAIN_B");
|
||||
Task transferredTask = taskService.getTask("TKI:000000000000000000000000000000000008");
|
||||
assertThat(transferredTask).isNotNull();
|
||||
assertThat(transferredTask.isTransferred()).isTrue();
|
||||
assertThat(transferredTask.isRead()).isFalse();
|
||||
assertThat(transferredTask.getState()).isEqualTo(TaskState.READY);
|
||||
assertThat(transferredTask.getWorkbasketKey()).isEqualTo(wb.getKey());
|
||||
assertThat(transferredTask.getDomain()).isEqualTo(wb.getDomain());
|
||||
assertThat(transferredTask.getModified().isBefore(before)).isFalse();
|
||||
assertThat(transferredTask.getOwner()).isEqualTo("teamlead-1");
|
||||
transferredTask = taskService.getTask("TKI:000000000000000000000000000000000009");
|
||||
assertThat(transferredTask).isNotNull();
|
||||
assertThat(transferredTask.isTransferred()).isTrue();
|
||||
assertThat(transferredTask.isRead()).isFalse();
|
||||
assertThat(transferredTask.getState()).isEqualTo(TaskState.READY);
|
||||
assertThat(transferredTask.getWorkbasketKey()).isEqualTo(wb.getKey());
|
||||
assertThat(transferredTask.getDomain()).isEqualTo(wb.getDomain());
|
||||
assertThat(transferredTask.getModified().isBefore(before)).isFalse();
|
||||
assertThat(transferredTask.getOwner()).isEqualTo("teamlead-1");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_NotSetTheTransferFlagWithinBulkTransferWithOwner_When_WorkbasketIdGiven()
|
||||
throws Exception {
|
||||
taskService.transferTasksWithOwner(
|
||||
"WBI:100000000000000000000000000000000006",
|
||||
List.of(
|
||||
"TKI:000000000000000000000000000000000010",
|
||||
"TKI:000000000000000000000000000000000011",
|
||||
"TKI:000000000000000000000000000000000012"),
|
||||
"user-1-1",
|
||||
false);
|
||||
|
||||
List<TaskSummary> transferredTasks =
|
||||
taskService
|
||||
.createTaskQuery()
|
||||
.idIn(
|
||||
"TKI:000000000000000000000000000000000010",
|
||||
"TKI:000000000000000000000000000000000011",
|
||||
"TKI:000000000000000000000000000000000012")
|
||||
.list();
|
||||
|
||||
assertThat(transferredTasks).extracting(TaskSummary::isTransferred).containsOnly(false);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_NotSetTheTransferFlagWithinBulkTransferWithOwner_When_WorkbasketKeyAndDomainGiven()
|
||||
throws Exception {
|
||||
taskService.transferTasksWithOwner(
|
||||
"USER-1-1",
|
||||
"DOMAIN_A",
|
||||
List.of(
|
||||
"TKI:000000000000000000000000000000000013",
|
||||
"TKI:000000000000000000000000000000000014",
|
||||
"TKI:000000000000000000000000000000000015"),
|
||||
"user-1-1",
|
||||
false);
|
||||
|
||||
List<TaskSummary> transferredTasks =
|
||||
taskService
|
||||
.createTaskQuery()
|
||||
.idIn(
|
||||
"TKI:000000000000000000000000000000000013",
|
||||
"TKI:000000000000000000000000000000000014",
|
||||
"TKI:000000000000000000000000000000000015")
|
||||
.list();
|
||||
|
||||
assertThat(transferredTasks).extracting(TaskSummary::isTransferred).containsOnly(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ public final class RestEndpoints {
|
|||
public static final String URL_TASKS_ID_TERMINATE = API_V1 + "tasks/{taskId}/terminate";
|
||||
public static final String URL_TASKS_ID_TRANSFER_WORKBASKET_ID =
|
||||
API_V1 + "tasks/{taskId}/transfer/{workbasketId}";
|
||||
public static final String URL_TRANSFER_WORKBASKET_ID = API_V1 + "tasks/transfer/{workbasketId}";
|
||||
public static final String URL_TASKS_ID_SET_READ = API_V1 + "tasks/{taskId}/set-read";
|
||||
|
||||
// task comment endpoints
|
||||
|
|
|
@ -55,6 +55,7 @@ import pro.taskana.task.rest.models.IsReadRepresentationModel;
|
|||
import pro.taskana.task.rest.models.TaskRepresentationModel;
|
||||
import pro.taskana.task.rest.models.TaskSummaryCollectionRepresentationModel;
|
||||
import pro.taskana.task.rest.models.TaskSummaryPagedRepresentationModel;
|
||||
import pro.taskana.task.rest.models.TransferTaskRepresentationModel;
|
||||
import pro.taskana.workbasket.api.exceptions.NotAuthorizedOnWorkbasketException;
|
||||
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
|
||||
|
||||
|
@ -555,6 +556,54 @@ public class TaskController {
|
|||
return ResponseEntity.ok(taskRepresentationModelAssembler.toModel(updatedTask));
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint transfers a list of Tasks listed in the body to a given Workbasket, if possible.
|
||||
*
|
||||
* @title Transfer Tasks to another Workbasket
|
||||
* @param workbasketId the Id of the destination Workbasket
|
||||
* @param transferTaskRepresentationModel the TaskIds, owner and setTransferFlag of tasks to be
|
||||
* transferred
|
||||
* @return the successfully transferred Task.
|
||||
* @throws WorkbasketNotFoundException if the requested Workbasket does not exist
|
||||
* @throws NotAuthorizedOnWorkbasketException if the current user has no authorization to transfer
|
||||
* the Task.
|
||||
*/
|
||||
@PostMapping(path = RestEndpoints.URL_TRANSFER_WORKBASKET_ID)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseEntity<TaskSummaryCollectionRepresentationModel> transferTasks(
|
||||
@PathVariable String workbasketId,
|
||||
@RequestBody TransferTaskRepresentationModel transferTaskRepresentationModel)
|
||||
throws NotAuthorizedOnWorkbasketException, WorkbasketNotFoundException {
|
||||
List<String> taskIds = transferTaskRepresentationModel.getTaskIds();
|
||||
BulkOperationResults<String, TaskanaException> result;
|
||||
if (transferTaskRepresentationModel.getOwner() == null) {
|
||||
result =
|
||||
taskService.transferTasks(
|
||||
workbasketId, taskIds, transferTaskRepresentationModel.getSetTransferFlag());
|
||||
} else {
|
||||
result =
|
||||
taskService.transferTasksWithOwner(
|
||||
workbasketId,
|
||||
taskIds,
|
||||
transferTaskRepresentationModel.getOwner(),
|
||||
transferTaskRepresentationModel.getSetTransferFlag());
|
||||
}
|
||||
|
||||
Set<String> failedIds = new HashSet<>(result.getFailedIds());
|
||||
List<String> successfullyTransferredTaskIds =
|
||||
taskIds.stream().filter(not(failedIds::contains)).toList();
|
||||
|
||||
List<TaskSummary> successfullyTransferredTaskSummaries =
|
||||
taskService
|
||||
.createTaskQuery()
|
||||
.idIn(successfullyTransferredTaskIds.toArray(new String[0]))
|
||||
.list();
|
||||
|
||||
return ResponseEntity.ok(
|
||||
taskSummaryRepresentationModelAssembler.toTaskanaCollectionModel(
|
||||
successfullyTransferredTaskSummaries));
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint updates a requested Task.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package pro.taskana.task.rest.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.util.List;
|
||||
|
||||
public class TransferTaskRepresentationModel {
|
||||
|
||||
/** The value to set the Task property owner. */
|
||||
@JsonProperty("owner")
|
||||
private final String owner;
|
||||
|
||||
/** The value to set the Task property setTransferFlag. */
|
||||
@JsonProperty("setTransferFlag")
|
||||
private final Boolean setTransferFlag;
|
||||
|
||||
/** The value to set the Task property taskIds. */
|
||||
@JsonProperty("taskIds")
|
||||
private final List<String> taskIds;
|
||||
|
||||
@ConstructorProperties({"setTransferFlag", "owner", "taskIds"})
|
||||
public TransferTaskRepresentationModel(
|
||||
Boolean setTransferFlag, String owner, List<String> taskIds) {
|
||||
this.setTransferFlag = setTransferFlag == null || setTransferFlag;
|
||||
this.owner = owner;
|
||||
this.taskIds = taskIds;
|
||||
}
|
||||
|
||||
public Boolean getSetTransferFlag() {
|
||||
return setTransferFlag;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public List<String> getTaskIds() {
|
||||
return taskIds;
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ import pro.taskana.task.rest.models.TaskRepresentationModel.CustomAttribute;
|
|||
import pro.taskana.task.rest.models.TaskSummaryCollectionRepresentationModel;
|
||||
import pro.taskana.task.rest.models.TaskSummaryPagedRepresentationModel;
|
||||
import pro.taskana.task.rest.models.TaskSummaryRepresentationModel;
|
||||
import pro.taskana.task.rest.models.TransferTaskRepresentationModel;
|
||||
import pro.taskana.task.rest.routing.IntegrationTestTaskRouter;
|
||||
import pro.taskana.workbasket.rest.models.WorkbasketSummaryRepresentationModel;
|
||||
|
||||
|
@ -2005,6 +2006,45 @@ class TaskControllerIntTest {
|
|||
.isEqualTo("WBI:100000000000000000000000000000000006");
|
||||
assertThat(response.getBody().isTransferred()).isTrue();
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
Stream<DynamicTest>
|
||||
should_SetTransferFlagAndOwnerDependentOnRequestBody_When_TransferringTasks() {
|
||||
|
||||
Iterator<Pair<Boolean, String>> iterator =
|
||||
Arrays.asList(Pair.of(true, "user-1-1"), Pair.of(false, "user-1-2")).iterator();
|
||||
String url =
|
||||
restHelper.toUrl(
|
||||
RestEndpoints.URL_TRANSFER_WORKBASKET_ID, "WBI:100000000000000000000000000000000006");
|
||||
|
||||
List<String> taskIds =
|
||||
Arrays.asList(
|
||||
"TKI:000000000000000000000000000000000003",
|
||||
"TKI:000000000000000000000000000000000004",
|
||||
"TKI:000000000000000000000000000000000005");
|
||||
|
||||
ThrowingConsumer<Pair<Boolean, String>> test =
|
||||
pair -> {
|
||||
HttpEntity<Object> auth =
|
||||
new HttpEntity<>(
|
||||
new TransferTaskRepresentationModel(pair.getLeft(), pair.getRight(), taskIds),
|
||||
RestHelper.generateHeadersForUser("admin"));
|
||||
ResponseEntity<TaskSummaryCollectionRepresentationModel> response =
|
||||
TEMPLATE.exchange(url, HttpMethod.POST, auth, TASK_SUMMARY_COLLECTION_MODEL_TYPE);
|
||||
|
||||
assertThat(response.getBody()).isNotNull();
|
||||
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(3);
|
||||
for (TaskSummaryRepresentationModel representationModel :
|
||||
response.getBody().getContent()) {
|
||||
assertThat(representationModel.getWorkbasketSummary().getWorkbasketId())
|
||||
.isEqualTo("WBI:100000000000000000000000000000000006");
|
||||
assertThat(representationModel.isTransferred()).isEqualTo(pair.getLeft());
|
||||
assertThat(representationModel.getOwner()).isEqualTo(pair.getRight());
|
||||
}
|
||||
};
|
||||
return DynamicTest.stream(iterator, c -> "for setTransferFlag and owner: " + c, test);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
|
|
@ -5,6 +5,7 @@ import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuild
|
|||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -18,6 +19,7 @@ import pro.taskana.task.internal.models.ObjectReferenceImpl;
|
|||
import pro.taskana.task.rest.assembler.TaskRepresentationModelAssembler;
|
||||
import pro.taskana.task.rest.models.IsReadRepresentationModel;
|
||||
import pro.taskana.task.rest.models.TaskRepresentationModel;
|
||||
import pro.taskana.task.rest.models.TransferTaskRepresentationModel;
|
||||
import pro.taskana.testapi.security.JaasExtension;
|
||||
import pro.taskana.testapi.security.WithAccessId;
|
||||
|
||||
|
@ -244,4 +246,20 @@ class TaskControllerRestDocTest extends BaseRestDocTest {
|
|||
.content(objectMapper.writeValueAsString(repModel)))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
void transferTasksDocTest() throws Exception {
|
||||
List<String> taskIds =
|
||||
List.of(
|
||||
"TKI:000000000000000000000000000000000000", "TKI:000000000000000000000000000000000001");
|
||||
TransferTaskRepresentationModel transferTaskRepresentationModel =
|
||||
new TransferTaskRepresentationModel(true, "user-1-1", taskIds);
|
||||
mockMvc
|
||||
.perform(
|
||||
post(
|
||||
RestEndpoints.URL_TRANSFER_WORKBASKET_ID,
|
||||
"WBI:100000000000000000000000000000000001")
|
||||
.content(objectMapper.writeValueAsString(transferTaskRepresentationModel)))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue