TSK-1802: add manual priority to task in taskana-core

This commit is contained in:
ryzheboka 2022-02-08 16:20:18 +01:00 committed by Elena Mokeeva
parent 16cad397d8
commit f70d845793
14 changed files with 469 additions and 17 deletions

View File

@ -34,8 +34,16 @@ public class PriorityServiceManager {
}
public OptionalInt calculatePriorityOfTask(TaskSummary task) {
if (task.isManualPriorityActive()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"Skip using PriorityServiceProviders because the Task is prioritised manually: {}",
task);
}
return OptionalInt.empty();
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Sending task to PriorityServiceProviders: {}", task);
LOGGER.debug("Sending Task to PriorityServiceProviders: {}", task);
}
Set<OptionalInt> priorities =

View File

@ -72,6 +72,15 @@ public interface Task extends TaskSummary {
*/
void setClassificationKey(String classificationKey);
/**
* Sets the manualPriority of the Task. If the value of manualPriority is zero or greater, the
* priority is automatically set to manualPriority. In this case, all computations of priority are
* disabled. If the value of manualPriority is negative, Tasks are not prioritized manually.
*
* @param manualPriority the value for manualPriority of the Task
*/
void setManualPriority(int manualPriority);
/**
* Returns the key of the Workbasket where the Task is stored in.
*

View File

@ -113,6 +113,15 @@ public interface TaskSummary {
*/
int getPriority();
/**
* Gets the manualPriority of the Task. If the value of manualPriority is zero or greater, the
* priority is automatically set to manualPriority. In this case, all computations of priority are
* disabled. If the value of manualPriority is negative, Tasks are not prioritized manually.
*
* @return the manualPriority of the Task
*/
int getManualPriority();
/**
* Gets the state of the Task.
*
@ -240,6 +249,14 @@ public interface TaskSummary {
*/
boolean isTransferred();
/**
* Returns whether the Task is prioritized manually. That means that the priority is set to the
* value of the manualPriority of the Task.
*
* @return true, if Tasks are prioritized manually; false otherwise
*/
boolean isManualPriorityActive();
/**
* Gets the custom attribute of the Task.
*

View File

@ -70,7 +70,10 @@ class ServiceLevelHandler {
tasks, attachments, allInvolvedClassificationsWithDuration);
}
if (priorityChanged) {
updateTaskPriorityOnClassificationUpdate(tasks, attachments, allInvolvedClassifications);
List<MinimalTaskSummary> tasksWithoutManualPriority =
tasks.stream().filter(t -> !t.isManualPriorityActive()).collect(Collectors.toList());
updateTaskPriorityOnClassificationUpdate(
tasksWithoutManualPriority, attachments, allInvolvedClassifications);
}
}
@ -121,7 +124,11 @@ class ServiceLevelHandler {
}
DurationPrioHolder durationPrioHolder = determineTaskPrioDuration(newTaskImpl, onlyPriority);
newTaskImpl.setPriority(durationPrioHolder.getPriority());
if (newTaskImpl.isManualPriorityActive()) {
newTaskImpl.setPriority(newTaskImpl.getManualPriority());
} else {
newTaskImpl.setPriority(durationPrioHolder.getPriority());
}
if (onlyPriority) {
return newTaskImpl;
}
@ -173,7 +180,6 @@ class ServiceLevelHandler {
List<MinimalTaskSummary> existingTasks,
List<AttachmentSummaryImpl> attachments,
List<ClassificationSummary> allInvolvedClassifications) {
Map<Integer, List<String>> priorityToTaskIdsMap =
getPriorityToTasksIdsMap(existingTasks, attachments, allInvolvedClassifications);
TaskImpl referenceTask = new TaskImpl();
@ -588,7 +594,8 @@ class ServiceLevelHandler {
|| !newTaskImpl
.getClassificationKey()
.equals(oldTaskImpl.getClassificationKey()));
final boolean isManualPriorityChanged =
newTaskImpl.getManualPriority() != oldTaskImpl.getManualPriority();
final boolean isClassificationIdChanged =
newTaskImpl.getClassificationId() != null
&& (oldTaskImpl.getClassificationId() == null
@ -598,6 +605,7 @@ class ServiceLevelHandler {
&& oldTaskImpl.getDue().equals(newTaskImpl.getDue())
&& !isClassificationKeyChanged
&& !isClassificationIdChanged
&& !isManualPriorityChanged
&& areAttachmentsUnchanged(newTaskImpl, oldTaskImpl);
} else {
return false;

View File

@ -26,7 +26,7 @@ import pro.taskana.task.internal.models.TaskImpl;
public interface TaskMapper {
@Select(
"<script>SELECT ID, EXTERNAL_ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, RECEIVED, DUE, NAME, CREATOR, DESCRIPTION, NOTE, PRIORITY, STATE, CLASSIFICATION_CATEGORY, CLASSIFICATION_KEY, CLASSIFICATION_ID, WORKBASKET_ID, WORKBASKET_KEY, DOMAIN, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, POR_COMPANY, POR_SYSTEM, POR_INSTANCE, POR_TYPE, POR_VALUE, IS_READ, IS_TRANSFERRED, CALLBACK_INFO, CALLBACK_STATE, CUSTOM_ATTRIBUTES, "
"<script>SELECT ID, EXTERNAL_ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, RECEIVED, DUE, NAME, CREATOR, DESCRIPTION, NOTE, PRIORITY, MANUAL_PRIORITY, STATE, CLASSIFICATION_CATEGORY, CLASSIFICATION_KEY, CLASSIFICATION_ID, WORKBASKET_ID, WORKBASKET_KEY, DOMAIN, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, POR_COMPANY, POR_SYSTEM, POR_INSTANCE, POR_TYPE, POR_VALUE, IS_READ, IS_TRANSFERRED, CALLBACK_INFO, CALLBACK_STATE, CUSTOM_ATTRIBUTES, "
+ "CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, CUSTOM_8, CUSTOM_9, CUSTOM_10, CUSTOM_11, CUSTOM_12, CUSTOM_13, CUSTOM_14, CUSTOM_15, CUSTOM_16 "
+ "FROM TASK "
+ "WHERE ID = #{id} "
@ -46,6 +46,7 @@ public interface TaskMapper {
@Result(property = "description", column = "DESCRIPTION")
@Result(property = "note", column = "NOTE")
@Result(property = "priority", column = "PRIORITY")
@Result(property = "manualPriority", column = "MANUAL_PRIORITY")
@Result(property = "state", column = "STATE")
@Result(property = "workbasketSummaryImpl.id", column = "WORKBASKET_ID")
@Result(property = "workbasketSummaryImpl.key", column = "WORKBASKET_KEY")
@ -93,10 +94,10 @@ public interface TaskMapper {
TaskImpl findById(@Param("id") String id);
@Insert(
"INSERT INTO TASK(ID, EXTERNAL_ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, RECEIVED, DUE, NAME, CREATOR, DESCRIPTION, NOTE, PRIORITY, STATE, CLASSIFICATION_CATEGORY, CLASSIFICATION_KEY, CLASSIFICATION_ID, WORKBASKET_ID, WORKBASKET_KEY, DOMAIN, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, POR_COMPANY, "
"INSERT INTO TASK(ID, EXTERNAL_ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, RECEIVED, DUE, NAME, CREATOR, DESCRIPTION, NOTE, PRIORITY, MANUAL_PRIORITY, STATE, CLASSIFICATION_CATEGORY, CLASSIFICATION_KEY, CLASSIFICATION_ID, WORKBASKET_ID, WORKBASKET_KEY, DOMAIN, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, POR_COMPANY, "
+ "POR_SYSTEM, POR_INSTANCE, POR_TYPE, POR_VALUE, IS_READ, IS_TRANSFERRED, CALLBACK_INFO, CALLBACK_STATE, CUSTOM_ATTRIBUTES, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, CUSTOM_8, "
+ "CUSTOM_9, CUSTOM_10, CUSTOM_11, CUSTOM_12, CUSTOM_13, CUSTOM_14, CUSTOM_15, CUSTOM_16 ) "
+ "VALUES(#{id},#{externalId}, #{created}, #{claimed}, #{completed}, #{modified}, #{planned}, #{received}, #{due}, #{name}, #{creator}, #{description}, #{note}, #{priority}, #{state}, #{classificationSummary.category}, "
+ "VALUES(#{id},#{externalId}, #{created}, #{claimed}, #{completed}, #{modified}, #{planned}, #{received}, #{due}, #{name}, #{creator}, #{description}, #{note}, #{priority}, #{manualPriority}, #{state}, #{classificationSummary.category}, "
+ "#{classificationSummary.key}, #{classificationSummary.id}, #{workbasketSummary.id}, #{workbasketSummary.key}, #{workbasketSummary.domain}, #{businessProcessId}, "
+ "#{parentBusinessProcessId}, #{owner}, #{primaryObjRef.company}, #{primaryObjRef.system}, #{primaryObjRef.systemInstance}, #{primaryObjRef.type}, #{primaryObjRef.value}, "
+ "#{isRead}, #{isTransferred}, #{callbackInfo,jdbcType=CLOB,javaType=java.util.Map,typeHandler=pro.taskana.common.internal.persistence.MapTypeHandler}, #{callbackState}, "
@ -108,7 +109,7 @@ public interface TaskMapper {
@Update(
"UPDATE TASK SET CLAIMED = #{claimed}, COMPLETED = #{completed}, MODIFIED = #{modified}, PLANNED = #{planned}, RECEIVED = #{received}, DUE = #{due}, NAME = #{name}, DESCRIPTION = #{description}, NOTE = #{note}, "
+ " PRIORITY = #{priority}, STATE = #{state}, CLASSIFICATION_CATEGORY = #{classificationSummary.category}, CLASSIFICATION_KEY = #{classificationSummary.key}, CLASSIFICATION_ID = #{classificationSummary.id}, "
+ " PRIORITY = #{priority}, MANUAL_PRIORITY = #{manualPriority}, STATE = #{state}, CLASSIFICATION_CATEGORY = #{classificationSummary.category}, CLASSIFICATION_KEY = #{classificationSummary.key}, CLASSIFICATION_ID = #{classificationSummary.id}, "
+ "WORKBASKET_ID = #{workbasketSummary.id}, WORKBASKET_KEY = #{workbasketSummary.key}, DOMAIN = #{workbasketSummary.domain}, "
+ "BUSINESS_PROCESS_ID = #{businessProcessId}, PARENT_BUSINESS_PROCESS_ID = #{parentBusinessProcessId}, OWNER = #{owner}, POR_COMPANY = #{primaryObjRef.company}, POR_SYSTEM = #{primaryObjRef.system}, "
+ "POR_INSTANCE = #{primaryObjRef.systemInstance}, POR_TYPE = #{primaryObjRef.type}, POR_VALUE = #{primaryObjRef.value}, IS_READ = #{isRead}, IS_TRANSFERRED = #{isTransferred}, "
@ -167,7 +168,7 @@ public interface TaskMapper {
@Select(
"<script>SELECT ID, EXTERNAL_ID, STATE, WORKBASKET_ID, OWNER, MODIFIED, CLASSIFICATION_ID, "
+ "PLANNED, DUE, CALLBACK_STATE FROM TASK "
+ "PLANNED, DUE, CALLBACK_STATE, MANUAL_PRIORITY FROM TASK "
+ "<where> "
+ "<if test='taskIds != null'>ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>)</if> "
+ "<if test='externalIds != null'>EXTERNAL_ID IN(<foreach item='item' collection='externalIds' separator=',' >#{item}</foreach>)</if> "
@ -184,6 +185,7 @@ public interface TaskMapper {
@Result(property = "due", column = "DUE")
@Result(property = "planned", column = "PLANNED")
@Result(property = "callbackState", column = "CALLBACK_STATE")
@Result(property = "manualPriority", column = "MANUAL_PRIORITY")
List<MinimalTaskSummary> findExistingTasks(
@Param("taskIds") Collection<String> taskIds, @Param("externalIds") List<String> externalIds);

View File

@ -24,6 +24,7 @@ public interface TaskQueryMapper {
@Result(property = "note", column = "NOTE")
@Result(property = "description", column = "DESCRIPTION")
@Result(property = "priority", column = "PRIORITY")
@Result(property = "manualPriority", column = "MANUAL_PRIORITY")
@Result(property = "state", column = "STATE")
@Result(property = "workbasketSummaryImpl.domain", column = "DOMAIN")
@Result(property = "workbasketSummaryImpl.key", column = "WORKBASKET_KEY")
@ -76,6 +77,7 @@ public interface TaskQueryMapper {
@Result(property = "note", column = "NOTE")
@Result(property = "description", column = "DESCRIPTION")
@Result(property = "priority", column = "PRIORITY")
@Result(property = "manualPriority", column = "MANUAL_PRIORITY")
@Result(property = "state", column = "STATE")
@Result(property = "workbasketSummaryImpl.domain", column = "DOMAIN")
@Result(property = "workbasketSummaryImpl.key", column = "WORKBASKET_KEY")

View File

@ -199,6 +199,11 @@ public class TaskBuilder {
return this;
}
public TaskBuilder manualPriority(Integer manualPriority) {
testTask.setManualPriority(manualPriority);
return this;
}
public Task buildAndStore(TaskService taskService)
throws TaskAlreadyExistException, InvalidArgumentException, WorkbasketNotFoundException,
ClassificationNotFoundException, NotAuthorizedException, AttachmentPersistenceException,

View File

@ -20,6 +20,7 @@ public class MinimalTaskSummary {
private Instant due;
private Instant modified;
private CallbackState callbackState;
private int manualPriority;
MinimalTaskSummary() {}
@ -103,6 +104,18 @@ public class MinimalTaskSummary {
this.callbackState = callbackState;
}
public int getManualPriority() {
return manualPriority;
}
public void setManualPriority(int manualPriority) {
this.manualPriority = manualPriority;
}
public boolean isManualPriorityActive() {
return manualPriority >= 0;
}
@Override
public int hashCode() {
return Objects.hash(
@ -115,7 +128,8 @@ public class MinimalTaskSummary {
planned,
due,
modified,
callbackState);
callbackState,
manualPriority);
}
@Override
@ -136,7 +150,8 @@ public class MinimalTaskSummary {
&& Objects.equals(planned, other.planned)
&& Objects.equals(due, other.due)
&& Objects.equals(modified, other.modified)
&& callbackState == other.callbackState;
&& callbackState == other.callbackState
&& manualPriority == other.manualPriority;
}
@Override
@ -161,6 +176,8 @@ public class MinimalTaskSummary {
+ modified
+ ", callbackState="
+ callbackState
+ ", manualPriority="
+ manualPriority
+ "]";
}
}

View File

@ -245,6 +245,7 @@ public class TaskImpl extends TaskSummaryImpl implements Task {
taskSummary.setReceived(received);
taskSummary.setPrimaryObjRef(primaryObjRef);
taskSummary.setPriority(priority);
taskSummary.setManualPriority(manualPriority);
taskSummary.setRead(isRead);
taskSummary.setState(state);
taskSummary.setTransferred(isTransferred);
@ -350,6 +351,8 @@ public class TaskImpl extends TaskSummaryImpl implements Task {
+ description
+ ", priority="
+ priority
+ ", manualPriority="
+ manualPriority
+ ", state="
+ state
+ ", classificationSummary="

View File

@ -21,6 +21,8 @@ import pro.taskana.workbasket.internal.models.WorkbasketSummaryImpl;
/** Entity which contains the most important information about a Task. */
public class TaskSummaryImpl implements TaskSummary {
private static final int DEFAULT_MANUAL_PRIORITY = -1;
protected String id;
protected String externalId;
protected Instant received;
@ -35,6 +37,7 @@ public class TaskSummaryImpl implements TaskSummary {
protected String note;
protected String description;
protected int priority;
protected int manualPriority = DEFAULT_MANUAL_PRIORITY;
protected TaskState state;
protected ClassificationSummary classificationSummary;
protected WorkbasketSummary workbasketSummary;
@ -80,6 +83,7 @@ public class TaskSummaryImpl implements TaskSummary {
note = copyFrom.note;
description = copyFrom.description;
priority = copyFrom.priority;
manualPriority = copyFrom.manualPriority;
state = copyFrom.state;
classificationSummary = copyFrom.classificationSummary;
workbasketSummary = copyFrom.workbasketSummary;
@ -239,6 +243,18 @@ public class TaskSummaryImpl implements TaskSummary {
this.priority = priority;
}
@Override
public int getManualPriority() {
return manualPriority;
}
public void setManualPriority(int manualPriority) {
this.manualPriority = manualPriority;
if (isManualPriorityActive()) {
this.priority = manualPriority;
}
}
@Override
public TaskState getState() {
return state;
@ -411,6 +427,11 @@ public class TaskSummaryImpl implements TaskSummary {
}
}
@Override
public boolean isManualPriorityActive() {
return manualPriority >= 0;
}
@Override
public TaskSummaryImpl copy() {
return new TaskSummaryImpl(this);
@ -662,6 +683,7 @@ public class TaskSummaryImpl implements TaskSummary {
note,
description,
priority,
manualPriority,
state,
classificationSummary,
workbasketSummary,
@ -705,6 +727,7 @@ public class TaskSummaryImpl implements TaskSummary {
return false;
}
return priority == other.priority
&& manualPriority == other.manualPriority
&& isRead == other.isRead
&& isTransferred == other.isTransferred
&& Objects.equals(id, other.id)
@ -778,6 +801,8 @@ public class TaskSummaryImpl implements TaskSummary {
+ description
+ ", priority="
+ priority
+ ", manualPriority="
+ manualPriority
+ ", state="
+ state
+ ", classificationSummary="

View File

@ -15,6 +15,7 @@ import com.tngtech.archunit.core.domain.JavaClass.Predicates;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.domain.JavaField;
import com.tngtech.archunit.core.domain.JavaMethod;
import com.tngtech.archunit.core.domain.JavaModifier;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ArchRule;
@ -24,6 +25,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -334,7 +336,7 @@ class ArchitectureTest {
.that()
.areAnnotatedWith(TaskanaIntegrationTest.class)
.or(areNestedTaskanaIntegrationTestClasses())
.should(onlyHaveFieldsWithNoModifier());
.should(onlyHaveFieldsWithNoModifierAndPrivateConstants());
rule.check(importedClasses);
}
@ -428,16 +430,24 @@ class ArchitectureTest {
};
}
private ArchCondition<JavaClass> onlyHaveFieldsWithNoModifier() {
return new ArchCondition<JavaClass>("only have fields with no modifier") {
private ArchCondition<JavaClass> onlyHaveFieldsWithNoModifierAndPrivateConstants() {
return new ArchCondition<>("only have fields with no modifier") {
final Set<JavaModifier> modifiersForConstants =
Set.of(JavaModifier.PRIVATE, JavaModifier.STATIC, JavaModifier.FINAL);
@Override
public void check(JavaClass item, ConditionEvents events) {
for (JavaField field : item.getAllFields()) {
if (!field.reflect().isSynthetic() && !field.getModifiers().isEmpty()) {
if (!field.reflect().isSynthetic()
&& !(field.getModifiers().isEmpty()
|| field.getModifiers().equals(modifiersForConstants))) {
events.add(
SimpleConditionEvent.violated(
item,
String.format("Field '%s' should not have any modifier", field.getFullName())));
String.format(
"Field '%s' should not have any modifier "
+ "except for static fields, which have to be private",
field.getFullName())));
}
}
}

View File

@ -130,6 +130,7 @@ class TaskBuilderTest {
.parentBusinessProcessId("BPI:ParentIsCool")
.owner("hanspeter")
.primaryObjRef(defaultTestObjectReference().build())
.manualPriority(7)
.read(true)
.transferred(true)
.attachments(attachment)
@ -172,6 +173,7 @@ class TaskBuilderTest {
expectedTask.setParentBusinessProcessId("BPI:ParentIsCool");
expectedTask.setOwner("hanspeter");
expectedTask.setPrimaryObjRef(defaultTestObjectReference().build());
expectedTask.setManualPriority(7);
expectedTask.setRead(true);
expectedTask.setTransferred(true);
expectedTask.setCreator("user-1-1");

View File

@ -0,0 +1,176 @@
package acceptance.task;
import static acceptance.DefaultTestEntities.defaultTestClassification;
import static acceptance.DefaultTestEntities.defaultTestObjectReference;
import static acceptance.DefaultTestEntities.defaultTestWorkbasket;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import testapi.TaskanaInject;
import testapi.TaskanaIntegrationTest;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.Classification;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.classification.internal.builder.ClassificationBuilder;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.internal.jobs.JobRunner;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.internal.builder.TaskBuilder;
import pro.taskana.workbasket.api.WorkbasketPermission;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
import pro.taskana.workbasket.internal.builder.WorkbasketAccessItemBuilder;
@TaskanaIntegrationTest
class UpdateManualPriorityAccTest {
private static final int CLASSIFICATION_PRIORITY = 9;
@TaskanaInject TaskanaEngine taskanaEngine;
@TaskanaInject TaskService taskService;
@TaskanaInject ClassificationService classificationService;
@TaskanaInject WorkbasketService workbasketService;
ClassificationSummary defaultClassificationSummary;
WorkbasketSummary defaultWorkbasketSummary;
ObjectReference defaultObjectReference;
@WithAccessId(user = "businessadmin")
@BeforeAll
void setup() throws Exception {
defaultClassificationSummary =
defaultTestClassification()
.priority(CLASSIFICATION_PRIORITY)
.buildAndStoreAsSummary(classificationService);
defaultWorkbasketSummary = defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
.workbasketId(defaultWorkbasketSummary.getId())
.accessId("user-1-1")
.permission(WorkbasketPermission.OPEN)
.permission(WorkbasketPermission.READ)
.permission(WorkbasketPermission.APPEND)
.buildAndStore(workbasketService);
defaultObjectReference = defaultTestObjectReference().build();
}
@WithAccessId(user = "user-1-1")
@Test
void should_setPriorityToManualPriority_When_PositiveManualPriority() throws Exception {
Task task = taskService.newTask(defaultWorkbasketSummary.getId());
task.setClassificationKey(defaultClassificationSummary.getKey());
task.setPrimaryObjRef(defaultObjectReference);
task.setManualPriority(123);
Task result = taskService.createTask(task);
assertThat(result.getPriority()).isEqualTo(result.getManualPriority()).isEqualTo(123);
}
@WithAccessId(user = "user-1-1")
@Test
void should_setPriorityAccordingToClassification_When_NegativeManualPriority() throws Exception {
Task task = taskService.newTask(defaultWorkbasketSummary.getId());
task.setClassificationKey(defaultClassificationSummary.getKey());
task.setPrimaryObjRef(defaultObjectReference);
task.setManualPriority(-5);
Task result = taskService.createTask(task);
assertThat(result.getPriority()).isEqualTo(CLASSIFICATION_PRIORITY);
}
@WithAccessId(user = "admin")
@Test
void should_NotUpdatePriorityAccordingToClassification_When_PositiveManualPriority()
throws Exception {
Classification classification =
ClassificationBuilder.newClassification()
.key("Key")
.domain(defaultWorkbasketSummary.getDomain())
.buildAndStore(classificationService);
Task task =
TaskBuilder.newTask()
.classificationSummary(classification.asSummary())
.workbasketSummary(defaultWorkbasketSummary)
.primaryObjRef(defaultObjectReference)
.manualPriority(123)
.buildAndStore(taskService);
classification.setPriority(1000);
updateClassificationAndRunAssociatedJobs(classification);
Task result = taskService.getTask(task.getId());
assertThat(result.getPriority()).isEqualTo(result.getManualPriority()).isEqualTo(123);
}
@WithAccessId(user = "admin")
@Test
void should_UpdatePriorityAccordingToClassification_When_UpdatedTaskHasNegativeManualPriority()
throws Exception {
Task task = createDefaultTask().manualPriority(123).buildAndStore(taskService);
task.setManualPriority(-5);
Task result = taskService.updateTask(task);
assertThat(result.getPriority()).isEqualTo(CLASSIFICATION_PRIORITY);
}
@WithAccessId(user = "user-1-1")
@Test
void should_NotUpdatePriorityAccordingToClassification_When_UpdatedTaskHasZeroManualPriority()
throws Exception {
Task task = createDefaultTask().manualPriority(123).buildAndStore(taskService);
task.setManualPriority(0);
Task result = taskService.updateTask(task);
assertThat(result.getPriority()).isZero();
}
@WithAccessId(user = "user-1-1")
@Test
void should_UpdateManualPriority_When_UpdatedTaskHasNewPositiveManualPriority() throws Exception {
Task task = createDefaultTask().manualPriority(123).buildAndStore(taskService);
task.setManualPriority(42);
Task result = taskService.updateTask(task);
assertThat(result.getPriority()).isEqualTo(result.getManualPriority()).isEqualTo(42);
}
@WithAccessId(user = "user-1-1")
@Test
void should_UpdateManualPriority_When_TaskWithoutManualPriorityHasManualPriorityAfterUpdate()
throws Exception {
Task task = createDefaultTask().manualPriority(-1).buildAndStore(taskService);
task.setManualPriority(42);
Task result = taskService.updateTask(task);
assertThat(result.getPriority()).isEqualTo(result.getManualPriority()).isEqualTo(42);
}
private TaskBuilder createDefaultTask() {
return TaskBuilder.newTask()
.classificationSummary(defaultClassificationSummary)
.workbasketSummary(defaultWorkbasketSummary)
.primaryObjRef(defaultObjectReference);
}
private void updateClassificationAndRunAssociatedJobs(Classification classification)
throws Exception {
classificationService.updateClassification(classification);
Thread.sleep(10);
// run the ClassificationChangedJob
JobRunner runner = new JobRunner(taskanaEngine);
// run the TaskRefreshJob that was scheduled by the ClassificationChangedJob.
runner.runJobs();
Thread.sleep(10); // otherwise the next runJobs call intermittently doesn't find the Job created
// by the previous step (it searches with DueDate < CurrentTime)
runner.runJobs();
}
}

View File

@ -0,0 +1,168 @@
package acceptance.task;
import static acceptance.DefaultTestEntities.defaultTestClassification;
import static acceptance.DefaultTestEntities.defaultTestObjectReference;
import static acceptance.DefaultTestEntities.defaultTestWorkbasket;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import java.util.OptionalInt;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import testapi.TaskanaInject;
import testapi.TaskanaIntegrationTest;
import testapi.WithServiceProvider;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.spi.priority.api.PriorityServiceProvider;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.models.ObjectReference;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.api.models.TaskSummary;
import pro.taskana.task.internal.builder.TaskBuilder;
import pro.taskana.task.internal.jobs.helper.TaskUpdatePriorityWorker;
import pro.taskana.workbasket.api.WorkbasketPermission;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
import pro.taskana.workbasket.internal.builder.WorkbasketAccessItemBuilder;
@TaskanaIntegrationTest
@WithServiceProvider(
serviceProviderInterface = PriorityServiceProvider.class,
serviceProviders =
UpdateManualPriorityWithSpiAccTest.TestStaticValuePriorityServiceProvider.class)
class UpdateManualPriorityWithSpiAccTest {
private static final int SPI_PRIORITY = 5;
@TaskanaInject TaskanaEngine taskanaEngine;
@TaskanaInject TaskService taskService;
@TaskanaInject ClassificationService classificationService;
@TaskanaInject WorkbasketService workbasketService;
public static class TestStaticValuePriorityServiceProvider implements PriorityServiceProvider {
@Override
public OptionalInt calculatePriority(TaskSummary taskSummary) {
return OptionalInt.of(UpdateManualPriorityWithSpiAccTest.SPI_PRIORITY);
}
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class UpdateManualPriorityTest {
ClassificationSummary defaultClassificationSummary;
WorkbasketSummary defaultWorkbasketSummary;
ObjectReference defaultObjectReference;
TaskUpdatePriorityWorker worker;
@WithAccessId(user = "businessadmin")
@BeforeAll
void setup() throws Exception {
worker = new TaskUpdatePriorityWorker(taskanaEngine);
defaultClassificationSummary =
defaultTestClassification().buildAndStoreAsSummary(classificationService);
defaultWorkbasketSummary = defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
.workbasketId(defaultWorkbasketSummary.getId())
.accessId("user-1-1")
.permission(WorkbasketPermission.OPEN)
.permission(WorkbasketPermission.READ)
.permission(WorkbasketPermission.APPEND)
.buildAndStore(workbasketService);
defaultObjectReference = defaultTestObjectReference().build();
}
@WithAccessId(user = "user-1-1")
@Test
void should_setPriorityToManualAndNotUpdateAccordingToSpi_When_ManualPriorityPositive()
throws Exception {
Task task = taskService.newTask(defaultWorkbasketSummary.getId());
task.setClassificationKey(defaultClassificationSummary.getKey());
task.setPrimaryObjRef(defaultObjectReference);
task.setManualPriority(123);
taskService.createTask(task);
worker.executeBatch(List.of(task.getId()));
Task result = taskService.getTask(task.getId());
assertThat(result.getPriority()).isEqualTo(result.getManualPriority()).isEqualTo(123);
}
@WithAccessId(user = "user-1-1")
@Test
void should_setPriorityUsingSpi_When_ManualPriorityNegative() throws Exception {
Task task = taskService.newTask(defaultWorkbasketSummary.getId());
task.setClassificationKey(defaultClassificationSummary.getKey());
task.setPrimaryObjRef(defaultObjectReference);
task.setManualPriority(-1);
Task result = taskService.createTask(task);
assertThat(result.getPriority()).isEqualTo(UpdateManualPriorityWithSpiAccTest.SPI_PRIORITY);
}
@WithAccessId(user = "user-1-1")
@Test
void should_UpdatePriorityAccordingToSpi_When_UpdatedTaskHasNegativeManualPriority()
throws Exception {
Task task = createDefaultTask().manualPriority(123).buildAndStore(taskService);
task.setManualPriority(-3);
Task result = taskService.updateTask(task);
assertThat(result.getPriority()).isEqualTo(UpdateManualPriorityWithSpiAccTest.SPI_PRIORITY);
}
@WithAccessId(user = "user-1-1")
@Test
void should_UpdateManualPriorityAnd_When_UpdatedTaskHasZeroManualPriority() throws Exception {
Task task = createDefaultTask().manualPriority(123).buildAndStore(taskService);
task.setManualPriority(0);
Task result = taskService.updateTask(task);
assertThat(result.getPriority()).isZero();
}
@WithAccessId(user = "user-1-1")
@Test
void should_UpdateManualPriority_When_UpdatedTaskHasNewPositiveManualPriority()
throws Exception {
Task task = createDefaultTask().manualPriority(123).buildAndStore(taskService);
task.setManualPriority(42);
Task result = taskService.updateTask(task);
assertThat(result.getPriority()).isEqualTo(result.getManualPriority()).isEqualTo(42);
}
@WithAccessId(user = "user-1-1")
@Test
void
should_NotUpdatePriorityWithSpi_When_TaskWithoutManualPriorityHasManualPriorityAfterUpdate()
throws Exception {
Task task = createDefaultTask().manualPriority(-1).buildAndStore(taskService);
task.setManualPriority(123);
taskService.updateTask(task);
worker.executeBatch(List.of(task.getId()));
Task result = taskService.getTask(task.getId());
assertThat(result.getPriority()).isEqualTo(result.getManualPriority()).isEqualTo(123);
}
private TaskBuilder createDefaultTask() {
return TaskBuilder.newTask()
.classificationSummary(defaultClassificationSummary)
.workbasketSummary(defaultWorkbasketSummary)
.primaryObjRef(defaultObjectReference);
}
}
}