Closes #2496 : Set Owner of Tasks when Transferring

This commit is contained in:
jamesrdi 2024-02-08 13:53:24 +01:00
parent 6ddb86fb89
commit 1de30e266b
10 changed files with 525 additions and 8 deletions

View File

@ -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 {

View File

@ -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}.
*

View File

@ -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,

View File

@ -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());

View File

@ -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);
}
}

View File

@ -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

View File

@ -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.
*

View File

@ -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;
}
}

View File

@ -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

View File

@ -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());
}
}