Closes #2347: Configuration to enable working day calculation instead of working time calculation
* added configuration property for detailed working time calculation * added WorkingDayCalculatorImpl to replicate pre 6.0.0 behaviour * bugfix ServiceLevelHandler comparing classificationKeys --------- Co-authored-by: arolfes <arolfes@users.noreply.github.com>
This commit is contained in:
parent
61b8ba08bf
commit
fbd388e6d4
|
@ -29,6 +29,7 @@ INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000021', 'ETI:0000000
|
|||
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000022', 'ETI:000000000000000000000000000000000022', '2018-01-29 15:55:22', null , null , '2018-01-29 15:55:22', null , '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000022' , 'DOC_0000000000000000022' , null , '00' , 'PASystem' , '00' , 'SDNR' , '11223344' , false , false , null , 'NONE' , null , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , 'abc' , '' , '' , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
|
||||
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000023', 'ETI:000000000000000000000000000000000023', '2018-01-29 15:55:23', null , null , '2018-01-29 15:55:23', null , '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000023' , 'DOC_0000000000000000023' , null , '00' , 'PASystem' , '00' , 'SDNR' , '11223344' , false , false , null , 'NONE' , null , '' , '' , '' , '' , '' , '' , '' , 'lnp' , '' , '' , '' , '' , '' , 'abc' , '' , '' , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
|
||||
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000024', 'ETI:000000000000000000000000000000000024', '2018-01-29 15:55:24', null , null , '2018-01-29 15:55:24', null , '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000024' , 'DOC_0000000000000000024' , null , '00' , 'PASystem' , '00' , 'SDNR' , '11223344' , false , false , null , 'NONE' , null , '' , '' , '' , '' , '' , '' , '' , '' , null , '' , '' , '' , '' , 'abc' , '' , '' , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
|
||||
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000201', 'ETI:000000000000000000000000000000000201', '2023-07-31 15:55:01', '2023-07-31 15:55:00', null , '2023-07-31 15:55:01', null , '2023-07-31 15:55:00', '2023-08-02 15:55:00', 'Task201' , 'creator_user_id' , 'Lorem ipsum was n Quatsch dolor sit amet.', 'Some custom Note' , 2 , -1 , 'READY' , 'EXTERN' , 'L110102' , 'CLI:100000000000000000000000000000000002', 'WBI:100000000000000000000000000000000006' , 'USER-1-1' , 'DOMAIN_A', 'BPI21' , 'PBPI21' , 'user-1-1' , 'MyCompany1', 'MySystem1', 'MyInstance1' , 'MyType1', 'MyValue1' , true , false , null , 'NONE' , null , 'pqr' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , 'abc' , '' , '' , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
|
||||
-- TASK TABLE (ID , EXTERNAL_ID , CREATED , CLAIMED , COMPLETED , modified , received , planned , 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_system_instance, por_type , por_value , is_read, is_transferred,callback_info , callback_state , custom_attributes ,custom1 ,custom2, ,custom3, ,custom4 ,custom5 ,custom6 ,custom7 ,custom8 ,custom9 ,custom10 ,custom11, ,custom12 ,custom13 ,custom14 ,custom15 ,custom16 , custom-int-1, custom-int-2, custom-int-3, custom-int-4, custom-int-5, custom-int-6, custom-int-7, custom-int-8
|
||||
-- Tasks for WorkOnTaskAccTest
|
||||
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000025', 'ETI:000000000000000000000000000000000025', '2018-01-29 15:55:24', null , null , '2018-01-29 15:55:24', '2018-01-29 15:55:24', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000007' , 'USER-1-2' , 'DOMAIN_A', 'PI_0000000000025' , 'DOC_0000000000000000025' , null , 'abcd00' , 'PASystem' , '00' , 'SDNR' , '98765432' , false , false , null , 'NONE' , null , '' , '' , '' , '' , '' , '' , '' , '' , '' , 'ert' , 'ert' , 'ert' , 'ert' , 'abc' , 'ert' , 'ert' , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
package pro.taskana.common.internal.workingtime;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.stream.LongStream;
|
||||
import pro.taskana.common.api.WorkingTimeCalculator;
|
||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||
import pro.taskana.common.api.exceptions.SystemException;
|
||||
|
||||
public class WorkingDayCalculatorImpl implements WorkingTimeCalculator {
|
||||
|
||||
private final ZoneId zoneId;
|
||||
private final HolidaySchedule holidaySchedule;
|
||||
|
||||
public WorkingDayCalculatorImpl(HolidaySchedule holidaySchedule, ZoneId zoneId) {
|
||||
this.holidaySchedule = holidaySchedule;
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant subtractWorkingTime(Instant workStart, Duration workingTime)
|
||||
throws InvalidArgumentException {
|
||||
long days = convertWorkingDaysToDays(workStart, -workingTime.toDays(), ZeroDirection.SUB_DAYS);
|
||||
return workStart.plus(Duration.ofDays(days));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant addWorkingTime(Instant workStart, Duration workingTime)
|
||||
throws InvalidArgumentException {
|
||||
long days = convertWorkingDaysToDays(workStart, workingTime.toDays(), ZeroDirection.ADD_DAYS);
|
||||
return workStart.plus(Duration.ofDays(days));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration workingTimeBetween(Instant first, Instant second)
|
||||
throws InvalidArgumentException {
|
||||
long days = Duration.between(first, second).abs().toDays();
|
||||
Instant firstInstant = first.isBefore(second) ? first : second;
|
||||
|
||||
long workingDaysBetween =
|
||||
LongStream.range(1, days)
|
||||
.mapToObj(day -> isWorkingDay(firstInstant.plus(day, ChronoUnit.DAYS)))
|
||||
.filter(t -> t)
|
||||
.count();
|
||||
return Duration.ofDays(workingDaysBetween);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWorkingDay(Instant instant) {
|
||||
return !isWeekend(instant) && !isHoliday(instant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWeekend(Instant instant) {
|
||||
DayOfWeek dayOfWeek = toDayOfWeek(instant);
|
||||
return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHoliday(Instant instant) {
|
||||
return holidaySchedule.isHoliday(toLocalDate(instant));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGermanHoliday(Instant instant) {
|
||||
return holidaySchedule.isGermanHoliday(toLocalDate(instant));
|
||||
}
|
||||
|
||||
private long convertWorkingDaysToDays(
|
||||
final Instant startTime, long numberOfDays, ZeroDirection zeroDirection) {
|
||||
if (startTime == null) {
|
||||
throw new SystemException(
|
||||
"Internal Error: convertWorkingDaysToDays was called with a null startTime");
|
||||
}
|
||||
int direction = calculateDirection(numberOfDays, zeroDirection);
|
||||
long limit = Math.abs(numberOfDays);
|
||||
return LongStream.iterate(0, i -> i + direction)
|
||||
.filter(day -> isWorkingDay(startTime.plus(day, ChronoUnit.DAYS)))
|
||||
.skip(limit)
|
||||
.findFirst()
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
private int calculateDirection(long numberOfDays, ZeroDirection zeroDirection) {
|
||||
if (numberOfDays == 0) {
|
||||
return zeroDirection.getDirection();
|
||||
} else {
|
||||
return numberOfDays >= 0 ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
private LocalDate toLocalDate(Instant instant) {
|
||||
return LocalDate.ofInstant(instant, zoneId);
|
||||
}
|
||||
|
||||
private DayOfWeek toDayOfWeek(Instant instant) {
|
||||
return toLocalDate(instant).getDayOfWeek();
|
||||
}
|
||||
|
||||
private enum ZeroDirection {
|
||||
SUB_DAYS(-1),
|
||||
ADD_DAYS(1);
|
||||
|
||||
private final int direction;
|
||||
|
||||
ZeroDirection(int direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public int getDirection() {
|
||||
return direction;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@ import org.junit.jupiter.params.ParameterizedTest;
|
|||
import org.junit.platform.commons.support.AnnotationSupport;
|
||||
import pro.taskana.TaskanaConfiguration;
|
||||
import pro.taskana.common.api.TaskanaEngine;
|
||||
import pro.taskana.common.api.WorkingTimeCalculator;
|
||||
import pro.taskana.common.api.exceptions.ErrorCode;
|
||||
import pro.taskana.common.api.exceptions.TaskanaException;
|
||||
import pro.taskana.common.api.exceptions.TaskanaRuntimeException;
|
||||
|
@ -71,7 +72,6 @@ import pro.taskana.common.internal.TaskanaEngineImpl;
|
|||
import pro.taskana.common.internal.jobs.JobScheduler;
|
||||
import pro.taskana.common.internal.logging.LoggingAspect;
|
||||
import pro.taskana.common.internal.workingtime.HolidaySchedule;
|
||||
import pro.taskana.common.internal.workingtime.WorkingTimeCalculatorImpl;
|
||||
import pro.taskana.testapi.TaskanaIntegrationTest;
|
||||
|
||||
/**
|
||||
|
@ -437,7 +437,7 @@ class ArchitectureTest {
|
|||
.that()
|
||||
.areNotAssignableFrom(ArchitectureTest.class)
|
||||
.and()
|
||||
.areNotAssignableTo(WorkingTimeCalculatorImpl.class)
|
||||
.areNotAssignableTo(WorkingTimeCalculator.class)
|
||||
.and()
|
||||
.areNotAssignableTo(TaskanaEngineImpl.class)
|
||||
.and()
|
||||
|
|
|
@ -251,6 +251,7 @@ class TaskanaConfigurationTest {
|
|||
Map<String, List<String>> expectedClassificationCategories =
|
||||
Map.of("TYPE_A", List.of("CATEGORY_A"), "TYPE_B", List.of("CATEGORY_B"));
|
||||
// working time configuration
|
||||
boolean expectedUseDetailedWorkingTimeCalculation = false;
|
||||
Map<DayOfWeek, Set<LocalTimeInterval>> expectedWorkingTimeSchedule =
|
||||
Map.of(DayOfWeek.MONDAY, Set.of(new LocalTimeInterval(LocalTime.MIN, LocalTime.NOON)));
|
||||
ZoneId expectedWorkingTimeScheduleTimeZone = ZoneId.ofOffset("UTC", ZoneOffset.ofHours(4));
|
||||
|
@ -308,6 +309,7 @@ class TaskanaConfigurationTest {
|
|||
.classificationTypes(expectedClassificationTypes)
|
||||
.classificationCategoriesByType(expectedClassificationCategories)
|
||||
// working time configuration
|
||||
.useWorkingTimeCalculation(expectedUseDetailedWorkingTimeCalculation)
|
||||
.workingTimeSchedule(expectedWorkingTimeSchedule)
|
||||
.workingTimeScheduleTimeZone(expectedWorkingTimeScheduleTimeZone)
|
||||
.customHolidays(expectedCustomHolidays)
|
||||
|
@ -368,6 +370,8 @@ class TaskanaConfigurationTest {
|
|||
assertThat(configuration.getClassificationCategoriesByType())
|
||||
.isEqualTo(expectedClassificationCategories);
|
||||
// working time configuration
|
||||
assertThat(configuration.isUseWorkingTimeCalculation())
|
||||
.isEqualTo(expectedUseDetailedWorkingTimeCalculation);
|
||||
assertThat(configuration.getWorkingTimeSchedule()).isEqualTo(expectedWorkingTimeSchedule);
|
||||
assertThat(configuration.getWorkingTimeScheduleTimeZone())
|
||||
.isEqualTo(expectedWorkingTimeScheduleTimeZone);
|
||||
|
@ -442,6 +446,7 @@ class TaskanaConfigurationTest {
|
|||
.classificationCategoriesByType(
|
||||
Map.of("typeA", List.of("categoryA"), "typeB", List.of("categoryB")))
|
||||
// working time configuration
|
||||
.useWorkingTimeCalculation(false)
|
||||
.workingTimeSchedule(
|
||||
Map.of(
|
||||
DayOfWeek.MONDAY,
|
||||
|
|
|
@ -46,6 +46,7 @@ import pro.taskana.task.api.models.Task;
|
|||
import pro.taskana.task.internal.models.TaskImpl;
|
||||
import pro.taskana.testapi.TaskanaInject;
|
||||
import pro.taskana.testapi.TaskanaIntegrationTest;
|
||||
import pro.taskana.testapi.builder.TaskBuilder;
|
||||
import pro.taskana.testapi.builder.WorkbasketAccessItemBuilder;
|
||||
import pro.taskana.testapi.security.WithAccessId;
|
||||
import pro.taskana.workbasket.api.WorkbasketPermission;
|
||||
|
@ -185,6 +186,50 @@ class UpdateClassificationAccTest {
|
|||
@Nested
|
||||
class UpdatePriorityAndServiceLevelTest {
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_ChangeDueDate_When_ServiceLevelOfClassificationHasChanged() throws Exception {
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P1D")
|
||||
.buildAndStore(classificationService);
|
||||
WorkbasketSummary workbasketSummary =
|
||||
defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
|
||||
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
|
||||
.workbasketId(workbasketSummary.getId())
|
||||
.accessId(currentUserContext.getUserid())
|
||||
.permission(WorkbasketPermission.OPEN)
|
||||
.permission(WorkbasketPermission.READ)
|
||||
.permission(WorkbasketPermission.READTASKS)
|
||||
.permission(WorkbasketPermission.APPEND)
|
||||
.buildAndStore(workbasketService, "businessadmin");
|
||||
|
||||
Task task = new TaskBuilder()
|
||||
.classificationSummary(classification.asSummary())
|
||||
.workbasketSummary(workbasketSummary)
|
||||
.primaryObjRef(defaultTestObjectReference().build())
|
||||
.planned(Instant.parse("2021-04-27T15:34:00.000Z"))
|
||||
.due(null)
|
||||
.buildAndStore(taskService);
|
||||
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
// read again the task from DB
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getClassificationSummary().getServiceLevel()).isEqualTo("P1D");
|
||||
assertThat(task.getDue()).isAfterOrEqualTo("2021-04-28T15:33:59.999Z");
|
||||
|
||||
classification.setServiceLevel("P3D");
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
// read again the task from DB
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getClassificationSummary().getServiceLevel()).isEqualTo("P3D");
|
||||
assertThat(task.getDue()).isEqualTo("2021-04-30T15:33:59.999Z");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_NotThrowException_When_UpdatingClassificationWithEmptyServiceLevel()
|
||||
|
|
|
@ -0,0 +1,933 @@
|
|||
package acceptance.classification.update;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static pro.taskana.testapi.DefaultTestEntities.defaultTestClassification;
|
||||
import static pro.taskana.testapi.DefaultTestEntities.defaultTestObjectReference;
|
||||
import static pro.taskana.testapi.DefaultTestEntities.defaultTestWorkbasket;
|
||||
import static pro.taskana.testapi.builder.TaskBuilder.newTask;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||
import org.junit.jupiter.api.TestTemplate;
|
||||
import org.junit.jupiter.api.function.ThrowingConsumer;
|
||||
import pro.taskana.TaskanaConfiguration.Builder;
|
||||
import pro.taskana.classification.api.ClassificationCustomField;
|
||||
import pro.taskana.classification.api.ClassificationService;
|
||||
import pro.taskana.classification.api.exceptions.ClassificationNotFoundException;
|
||||
import pro.taskana.classification.api.models.Classification;
|
||||
import pro.taskana.classification.api.models.ClassificationSummary;
|
||||
import pro.taskana.classification.internal.models.ClassificationImpl;
|
||||
import pro.taskana.common.api.TaskanaEngine;
|
||||
import pro.taskana.common.api.TaskanaRole;
|
||||
import pro.taskana.common.api.WorkingTimeCalculator;
|
||||
import pro.taskana.common.api.exceptions.ConcurrencyException;
|
||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||
import pro.taskana.common.api.exceptions.NotAuthorizedException;
|
||||
import pro.taskana.common.api.security.CurrentUserContext;
|
||||
import pro.taskana.common.internal.jobs.JobRunner;
|
||||
import pro.taskana.common.internal.util.Pair;
|
||||
import pro.taskana.task.api.TaskService;
|
||||
import pro.taskana.task.api.models.Attachment;
|
||||
import pro.taskana.task.api.models.Task;
|
||||
import pro.taskana.task.internal.models.TaskImpl;
|
||||
import pro.taskana.testapi.TaskanaConfigurationModifier;
|
||||
import pro.taskana.testapi.TaskanaInject;
|
||||
import pro.taskana.testapi.TaskanaIntegrationTest;
|
||||
import pro.taskana.testapi.builder.TaskBuilder;
|
||||
import pro.taskana.testapi.builder.WorkbasketAccessItemBuilder;
|
||||
import pro.taskana.testapi.security.WithAccessId;
|
||||
import pro.taskana.workbasket.api.WorkbasketPermission;
|
||||
import pro.taskana.workbasket.api.WorkbasketService;
|
||||
import pro.taskana.workbasket.api.models.WorkbasketSummary;
|
||||
|
||||
@TaskanaIntegrationTest
|
||||
public class UpdateClassificationWithWorkingDayCalculatorAccTest
|
||||
implements TaskanaConfigurationModifier {
|
||||
|
||||
@TaskanaInject ClassificationService classificationService;
|
||||
@TaskanaInject TaskanaEngine taskanaEngine;
|
||||
@TaskanaInject TaskService taskService;
|
||||
@TaskanaInject WorkbasketService workbasketService;
|
||||
@TaskanaInject WorkingTimeCalculator workingTimeCalculator;
|
||||
@TaskanaInject CurrentUserContext currentUserContext;
|
||||
|
||||
@Override
|
||||
public Builder modify(Builder builder) {
|
||||
return builder
|
||||
.workingTimeScheduleTimeZone(ZoneId.of("UTC"))
|
||||
.useWorkingTimeCalculation(false); // switch to WorkingDayCalculatorImpl
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_SetFieldsCorrectly_When_TryingToUpdateClassification() throws Exception {
|
||||
Classification parentClassification =
|
||||
defaultTestClassification().buildAndStore(classificationService);
|
||||
Classification classification =
|
||||
defaultTestClassification().type("TASK").buildAndStore(classificationService);
|
||||
final Instant createdBefore = classification.getCreated();
|
||||
final Instant modifiedBefore = classification.getModified();
|
||||
|
||||
classification.setApplicationEntryPoint("newEntrypoint");
|
||||
classification.setCategory("PROCESS");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_1, "newCustom1");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_2, "newCustom2");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_3, "newCustom3");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_4, "newCustom4");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_5, "newCustom5");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_6, "newCustom6");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_7, "newCustom7");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_8, "newCustom8");
|
||||
classification.setDescription("newDescription");
|
||||
classification.setIsValidInDomain(false);
|
||||
classification.setName("newName");
|
||||
classification.setParentId(parentClassification.getId());
|
||||
classification.setParentKey(parentClassification.getKey());
|
||||
classification.setPriority(1000);
|
||||
classification.setServiceLevel("P3D");
|
||||
classificationService.updateClassification(classification);
|
||||
|
||||
Classification updatedClassification =
|
||||
classificationService.getClassification(classification.getKey(), "DOMAIN_A");
|
||||
ClassificationImpl expectedClassification =
|
||||
(ClassificationImpl)
|
||||
defaultTestClassification()
|
||||
.type("TASK")
|
||||
.applicationEntryPoint("newEntrypoint")
|
||||
.category("PROCESS")
|
||||
.customAttribute(ClassificationCustomField.CUSTOM_1, "newCustom1")
|
||||
.customAttribute(ClassificationCustomField.CUSTOM_2, "newCustom2")
|
||||
.customAttribute(ClassificationCustomField.CUSTOM_3, "newCustom3")
|
||||
.customAttribute(ClassificationCustomField.CUSTOM_4, "newCustom4")
|
||||
.customAttribute(ClassificationCustomField.CUSTOM_5, "newCustom5")
|
||||
.customAttribute(ClassificationCustomField.CUSTOM_6, "newCustom6")
|
||||
.customAttribute(ClassificationCustomField.CUSTOM_7, "newCustom7")
|
||||
.customAttribute(ClassificationCustomField.CUSTOM_8, "newCustom8")
|
||||
.description("newDescription")
|
||||
.isValidInDomain(false)
|
||||
.name("newName")
|
||||
.parentId(parentClassification.getId())
|
||||
.parentKey(parentClassification.getKey())
|
||||
.priority(1000)
|
||||
.serviceLevel("P3D")
|
||||
.created(createdBefore)
|
||||
.modified(updatedClassification.getModified())
|
||||
.buildAndStore(classificationService);
|
||||
expectedClassification.setKey(updatedClassification.getKey());
|
||||
expectedClassification.setId(updatedClassification.getId());
|
||||
|
||||
assertThat(expectedClassification).hasNoNullFieldsOrProperties();
|
||||
assertThat(modifiedBefore).isBefore(classification.getModified());
|
||||
assertThat(updatedClassification).isEqualTo(expectedClassification);
|
||||
}
|
||||
|
||||
private String createTaskWithExistingClassification(ClassificationSummary classificationSummary)
|
||||
throws Exception {
|
||||
|
||||
WorkbasketSummary workbasketSummary =
|
||||
defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
|
||||
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
|
||||
.workbasketId(workbasketSummary.getId())
|
||||
.accessId(currentUserContext.getUserid())
|
||||
.permission(WorkbasketPermission.OPEN)
|
||||
.permission(WorkbasketPermission.READ)
|
||||
.permission(WorkbasketPermission.READTASKS)
|
||||
.permission(WorkbasketPermission.APPEND)
|
||||
.buildAndStore(workbasketService, "businessadmin");
|
||||
|
||||
return newTask()
|
||||
.classificationSummary(classificationSummary)
|
||||
.workbasketSummary(workbasketSummary)
|
||||
.primaryObjRef(defaultTestObjectReference().build())
|
||||
.buildAndStore(taskService)
|
||||
.getId();
|
||||
}
|
||||
|
||||
private List<String> createTasksWithExistingClassificationInAttachment(
|
||||
ClassificationSummary classificationSummary, String serviceLevel, int priority, int amount)
|
||||
throws Exception {
|
||||
List<String> taskList = new ArrayList<>();
|
||||
WorkbasketSummary workbasketSummary =
|
||||
defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
|
||||
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
|
||||
.workbasketId(workbasketSummary.getId())
|
||||
.accessId(currentUserContext.getUserid())
|
||||
.permission(WorkbasketPermission.OPEN)
|
||||
.permission(WorkbasketPermission.READ)
|
||||
.permission(WorkbasketPermission.READTASKS)
|
||||
.permission(WorkbasketPermission.APPEND)
|
||||
.buildAndStore(workbasketService, "businessadmin");
|
||||
ClassificationSummary classificationSummaryWithSpecifiedServiceLevel =
|
||||
defaultTestClassification()
|
||||
.serviceLevel(serviceLevel)
|
||||
.priority(priority)
|
||||
.buildAndStoreAsSummary(classificationService);
|
||||
for (int i = 0; i < amount; i++) {
|
||||
Attachment attachment = taskService.newAttachment();
|
||||
attachment.setClassificationSummary(classificationSummary);
|
||||
attachment.setObjectReference(defaultTestObjectReference().build());
|
||||
taskList.add(
|
||||
newTask()
|
||||
.classificationSummary(classificationSummaryWithSpecifiedServiceLevel)
|
||||
.workbasketSummary(workbasketSummary)
|
||||
.primaryObjRef(defaultTestObjectReference().build())
|
||||
.attachments(attachment)
|
||||
.buildAndStore(taskService)
|
||||
.getId());
|
||||
}
|
||||
return taskList;
|
||||
}
|
||||
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
@Nested
|
||||
class UpdatePriorityAndServiceLevelTest {
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_ChangeDueDate_When_ClassificationOfTaskHasChanged() throws Exception {
|
||||
|
||||
final Instant plannedDate = Instant.parse("2021-04-27T15:34:00.000Z");
|
||||
final String expectedDue1 = plannedDate.plus(1, ChronoUnit.DAYS).toString();
|
||||
final String expectedDue3 = plannedDate.plus(3, ChronoUnit.DAYS).toString();
|
||||
|
||||
final Classification classificationWithSL1 =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P1D")
|
||||
.buildAndStore(classificationService);
|
||||
final Classification classificationWithSL3 =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P3D")
|
||||
.buildAndStore(classificationService);
|
||||
|
||||
WorkbasketSummary workbasketSummary =
|
||||
defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
|
||||
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
|
||||
.workbasketId(workbasketSummary.getId())
|
||||
.accessId(currentUserContext.getUserid())
|
||||
.permission(WorkbasketPermission.OPEN)
|
||||
.permission(WorkbasketPermission.READ)
|
||||
.permission(WorkbasketPermission.READTASKS)
|
||||
.permission(WorkbasketPermission.EDITTASKS)
|
||||
.permission(WorkbasketPermission.APPEND)
|
||||
.buildAndStore(workbasketService, "businessadmin");
|
||||
|
||||
Task task =
|
||||
new TaskBuilder()
|
||||
.classificationSummary(classificationWithSL1.asSummary())
|
||||
.workbasketSummary(workbasketSummary)
|
||||
.primaryObjRef(defaultTestObjectReference().build())
|
||||
.planned(plannedDate)
|
||||
.due(null)
|
||||
.buildAndStore(taskService);
|
||||
|
||||
classificationService.updateClassification(classificationWithSL1);
|
||||
runAssociatedJobs();
|
||||
// read again the task from DB
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getClassificationSummary().getServiceLevel()).isEqualTo("P1D");
|
||||
assertThat(task.getDue()).isAfterOrEqualTo(expectedDue1);
|
||||
|
||||
task.setClassificationKey(classificationWithSL3.getKey());
|
||||
taskService.updateTask(task);
|
||||
|
||||
// read again the task from DB
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getClassificationSummary().getServiceLevel()).isEqualTo("P3D");
|
||||
assertThat(task.getDue()).isEqualTo(expectedDue3);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_ChangeDueDate_When_ServiceLevelOfClassificationHasChanged() throws Exception {
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P1D")
|
||||
.buildAndStore(classificationService);
|
||||
WorkbasketSummary workbasketSummary =
|
||||
defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
|
||||
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
|
||||
.workbasketId(workbasketSummary.getId())
|
||||
.accessId(currentUserContext.getUserid())
|
||||
.permission(WorkbasketPermission.OPEN)
|
||||
.permission(WorkbasketPermission.READ)
|
||||
.permission(WorkbasketPermission.READTASKS)
|
||||
.permission(WorkbasketPermission.APPEND)
|
||||
.buildAndStore(workbasketService, "businessadmin");
|
||||
|
||||
Task task =
|
||||
new TaskBuilder()
|
||||
.classificationSummary(classification.asSummary())
|
||||
.workbasketSummary(workbasketSummary)
|
||||
.primaryObjRef(defaultTestObjectReference().build())
|
||||
.planned(Instant.parse("2021-04-27T15:34:00.000Z"))
|
||||
.due(null)
|
||||
.buildAndStore(taskService);
|
||||
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
// read again the task from DB
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getClassificationSummary().getServiceLevel()).isEqualTo("P1D");
|
||||
assertThat(task.getDue()).isAfterOrEqualTo("2021-04-28T15:34:00.000Z");
|
||||
|
||||
classification.setServiceLevel("P3D");
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
// read again the task from DB
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getClassificationSummary().getServiceLevel()).isEqualTo("P3D");
|
||||
assertThat(task.getDue()).isEqualTo("2021-04-30T15:34:00.000Z");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_NotThrowException_When_UpdatingClassificationWithEmptyServiceLevel()
|
||||
throws Exception {
|
||||
Classification classification =
|
||||
defaultTestClassification().serviceLevel("P1D").buildAndStore(classificationService);
|
||||
classification.setServiceLevel("");
|
||||
assertThatCode(() -> classificationService.updateClassification(classification))
|
||||
.doesNotThrowAnyException();
|
||||
assertThat(classificationService.getClassification(classification.getId()).getServiceLevel())
|
||||
.isEqualTo("P0D");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@TestFactory
|
||||
Stream<DynamicTest>
|
||||
should_SetDefaultServiceLevel_When_TryingToUpdateClassificationWithMissingServiceLevel()
|
||||
throws Exception {
|
||||
Classification classification =
|
||||
defaultTestClassification().serviceLevel("P1D").buildAndStore(classificationService);
|
||||
List<Pair<Classification, String>> inputList =
|
||||
List.of(Pair.of(classification, null), Pair.of(classification, ""));
|
||||
|
||||
ThrowingConsumer<Pair<Classification, String>> test =
|
||||
input -> {
|
||||
input.getLeft().setServiceLevel(input.getRight());
|
||||
classificationService.updateClassification(input.getLeft());
|
||||
assertThat(
|
||||
classificationService
|
||||
.getClassification(input.getLeft().getId())
|
||||
.getServiceLevel())
|
||||
.isEqualTo("P0D");
|
||||
};
|
||||
|
||||
return DynamicTest.stream(
|
||||
inputList.iterator(), i -> String.format("for %s", i.getRight()), test);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_UpdateTaskServiceLevel_When_UpdateClassificationInTask() throws Exception {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P13D")
|
||||
.buildAndStore(classificationService);
|
||||
final List<String> directLinkedTask =
|
||||
List.of(createTaskWithExistingClassification(classification.asSummary()));
|
||||
|
||||
classification.setServiceLevel("P15D");
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(before, directLinkedTask, taskService, workingTimeCalculator, 15, 1);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_UpdateTaskPriority_When_UpdateClassificationInTask() throws Exception {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P13D")
|
||||
.buildAndStore(classificationService);
|
||||
final List<String> directLinkedTask =
|
||||
List.of(createTaskWithExistingClassification(classification.asSummary()));
|
||||
|
||||
classification.setPriority(1000);
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(
|
||||
before, directLinkedTask, taskService, workingTimeCalculator, 13, 1000);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_UpdateTaskPriorityAndServiceLevel_When_UpdateClassificationInTask()
|
||||
throws Exception {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P13D")
|
||||
.buildAndStore(classificationService);
|
||||
final List<String> directLinkedTask =
|
||||
List.of(createTaskWithExistingClassification(classification.asSummary()));
|
||||
|
||||
classification.setServiceLevel("P15D");
|
||||
classification.setPriority(1000);
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(
|
||||
before, directLinkedTask, taskService, workingTimeCalculator, 15, 1000);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@TestFactory
|
||||
Stream<DynamicTest> should_UpdateTaskServiceLevel_When_UpdateClassificationInAttachment() {
|
||||
List<Pair<String, Integer>> inputs =
|
||||
List.of(Pair.of("P5D", 2), Pair.of("P8D", 3), Pair.of("P16D", 4));
|
||||
|
||||
List<Pair<Integer, Integer>> outputs = List.of(Pair.of(1, 2), Pair.of(1, 3), Pair.of(1, 4));
|
||||
|
||||
List<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> zippedTestInputList =
|
||||
IntStream.range(0, inputs.size())
|
||||
.mapToObj(i -> Pair.of(inputs.get(i), outputs.get(i)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ThrowingConsumer<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> test =
|
||||
input -> {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P15D")
|
||||
.buildAndStore(classificationService);
|
||||
ClassificationSummary classificationSummary = classification.asSummary();
|
||||
final List<String> indirectLinkedTasks =
|
||||
createTasksWithExistingClassificationInAttachment(
|
||||
classificationSummary,
|
||||
input.getLeft().getLeft(),
|
||||
input.getLeft().getRight(),
|
||||
5);
|
||||
|
||||
classification.setServiceLevel("P1D");
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(
|
||||
before,
|
||||
indirectLinkedTasks,
|
||||
taskService,
|
||||
workingTimeCalculator,
|
||||
input.getRight().getLeft(),
|
||||
input.getRight().getRight());
|
||||
};
|
||||
|
||||
return DynamicTest.stream(
|
||||
zippedTestInputList.iterator(),
|
||||
i ->
|
||||
String.format(
|
||||
"for Task with ServiceLevel %s and Priority %s",
|
||||
i.getLeft().getLeft(), i.getLeft().getRight()),
|
||||
test);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@TestFactory
|
||||
Stream<DynamicTest> should_NotUpdateTaskServiceLevel_When_UpdateClassificationInAttachment() {
|
||||
List<Pair<String, Integer>> inputs =
|
||||
List.of(Pair.of("P5D", 2), Pair.of("P8D", 3), Pair.of("P14D", 4));
|
||||
|
||||
List<Pair<Integer, Integer>> outputs = List.of(Pair.of(5, 2), Pair.of(8, 3), Pair.of(14, 4));
|
||||
|
||||
List<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> zippedTestInputList =
|
||||
IntStream.range(0, inputs.size())
|
||||
.mapToObj(i -> Pair.of(inputs.get(i), outputs.get(i)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ThrowingConsumer<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> test =
|
||||
input -> {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P1D")
|
||||
.buildAndStore(classificationService);
|
||||
ClassificationSummary classificationSummary = classification.asSummary();
|
||||
final List<String> indirectLinkedTasks =
|
||||
createTasksWithExistingClassificationInAttachment(
|
||||
classificationSummary,
|
||||
input.getLeft().getLeft(),
|
||||
input.getLeft().getRight(),
|
||||
5);
|
||||
|
||||
classification.setServiceLevel("P15D");
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(
|
||||
before,
|
||||
indirectLinkedTasks,
|
||||
taskService,
|
||||
workingTimeCalculator,
|
||||
input.getRight().getLeft(),
|
||||
input.getRight().getRight());
|
||||
};
|
||||
|
||||
return DynamicTest.stream(
|
||||
zippedTestInputList.iterator(),
|
||||
i ->
|
||||
String.format(
|
||||
"for Task with ServiceLevel %s and Priority %s",
|
||||
i.getLeft().getLeft(), i.getLeft().getRight()),
|
||||
test);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@TestFactory
|
||||
Stream<DynamicTest> should_UpdateTaskPriority_When_UpdateClassificationInAttachment() {
|
||||
List<Pair<String, Integer>> inputs =
|
||||
List.of(Pair.of("P1D", 1), Pair.of("P8D", 2), Pair.of("P14D", 999));
|
||||
|
||||
List<Pair<Integer, Integer>> outputs =
|
||||
List.of(Pair.of(1, 1000), Pair.of(8, 1000), Pair.of(14, 1000));
|
||||
|
||||
List<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> zippedTestInputList =
|
||||
IntStream.range(0, inputs.size())
|
||||
.mapToObj(i -> Pair.of(inputs.get(i), outputs.get(i)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ThrowingConsumer<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> test =
|
||||
input -> {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P13D")
|
||||
.buildAndStore(classificationService);
|
||||
ClassificationSummary classificationSummary = classification.asSummary();
|
||||
final List<String> indirectLinkedTasks =
|
||||
createTasksWithExistingClassificationInAttachment(
|
||||
classificationSummary,
|
||||
input.getLeft().getLeft(),
|
||||
input.getLeft().getRight(),
|
||||
5);
|
||||
|
||||
classification.setServiceLevel("P15D");
|
||||
classification.setPriority(1000);
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(
|
||||
before,
|
||||
indirectLinkedTasks,
|
||||
taskService,
|
||||
workingTimeCalculator,
|
||||
input.getRight().getLeft(),
|
||||
input.getRight().getRight());
|
||||
};
|
||||
|
||||
return DynamicTest.stream(
|
||||
zippedTestInputList.iterator(),
|
||||
i ->
|
||||
String.format(
|
||||
"for Task with ServiceLevel %s and Priority %s",
|
||||
i.getLeft().getLeft(), i.getLeft().getRight()),
|
||||
test);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@TestFactory
|
||||
Stream<DynamicTest> should_NotUpdateTaskPriority_When_UpdateClassificationInAttachment() {
|
||||
List<Pair<String, Integer>> inputs =
|
||||
List.of(Pair.of("P1D", 2), Pair.of("P8D", 3), Pair.of("P14D", 999));
|
||||
|
||||
List<Pair<Integer, Integer>> outputs =
|
||||
List.of(Pair.of(1, 2), Pair.of(8, 3), Pair.of(14, 999));
|
||||
|
||||
List<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> zippedTestInputList =
|
||||
IntStream.range(0, inputs.size())
|
||||
.mapToObj(i -> Pair.of(inputs.get(i), outputs.get(i)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ThrowingConsumer<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> test =
|
||||
input -> {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1000)
|
||||
.serviceLevel("P13D")
|
||||
.buildAndStore(classificationService);
|
||||
ClassificationSummary classificationSummary = classification.asSummary();
|
||||
final List<String> indirectLinkedTasks =
|
||||
createTasksWithExistingClassificationInAttachment(
|
||||
classificationSummary,
|
||||
input.getLeft().getLeft(),
|
||||
input.getLeft().getRight(),
|
||||
5);
|
||||
|
||||
classification.setServiceLevel("P15D");
|
||||
classification.setPriority(1);
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(
|
||||
before,
|
||||
indirectLinkedTasks,
|
||||
taskService,
|
||||
workingTimeCalculator,
|
||||
input.getRight().getLeft(),
|
||||
input.getRight().getRight());
|
||||
};
|
||||
|
||||
return DynamicTest.stream(
|
||||
zippedTestInputList.iterator(),
|
||||
i ->
|
||||
String.format(
|
||||
"for Task with ServiceLevel %s and Priority %s",
|
||||
i.getLeft().getLeft(), i.getLeft().getRight()),
|
||||
test);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@TestFactory
|
||||
Stream<DynamicTest>
|
||||
should_UpdateTaskPriorityAndServiceLevel_When_UpdateClassificationInAttachment() {
|
||||
List<Pair<String, Integer>> inputs = List.of(Pair.of("P1D", 5), Pair.of("P14D", 98));
|
||||
|
||||
List<Pair<Integer, Integer>> outputs = List.of(Pair.of(1, 99), Pair.of(1, 99));
|
||||
|
||||
List<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> zippedTestInputList =
|
||||
IntStream.range(0, inputs.size())
|
||||
.mapToObj(i -> Pair.of(inputs.get(i), outputs.get(i)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ThrowingConsumer<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> test =
|
||||
input -> {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1)
|
||||
.serviceLevel("P13D")
|
||||
.buildAndStore(classificationService);
|
||||
ClassificationSummary classificationSummary = classification.asSummary();
|
||||
final List<String> indirectLinkedTasks =
|
||||
createTasksWithExistingClassificationInAttachment(
|
||||
classificationSummary,
|
||||
input.getLeft().getLeft(),
|
||||
input.getLeft().getRight(),
|
||||
3);
|
||||
|
||||
classification.setServiceLevel("P1D");
|
||||
classification.setPriority(99);
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(
|
||||
before,
|
||||
indirectLinkedTasks,
|
||||
taskService,
|
||||
workingTimeCalculator,
|
||||
input.getRight().getLeft(),
|
||||
input.getRight().getRight());
|
||||
};
|
||||
|
||||
return DynamicTest.stream(
|
||||
zippedTestInputList.iterator(),
|
||||
i ->
|
||||
String.format(
|
||||
"for Task with ServiceLevel %s and Priority %s",
|
||||
i.getLeft().getLeft(), i.getLeft().getRight()),
|
||||
test);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@TestFactory
|
||||
Stream<DynamicTest>
|
||||
should_NotUpdateTaskPriorityAndServiceLevel_When_UpdateClassificationInAttachment() {
|
||||
List<Pair<String, Integer>> inputs = List.of(Pair.of("P1D", 5), Pair.of("P14D", 98));
|
||||
|
||||
List<Pair<Integer, Integer>> outputs = List.of(Pair.of(1, 5), Pair.of(14, 98));
|
||||
|
||||
List<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> zippedTestInputList =
|
||||
IntStream.range(0, inputs.size())
|
||||
.mapToObj(i -> Pair.of(inputs.get(i), outputs.get(i)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ThrowingConsumer<Pair<Pair<String, Integer>, Pair<Integer, Integer>>> test =
|
||||
input -> {
|
||||
final Instant before = Instant.now();
|
||||
Classification classification =
|
||||
defaultTestClassification()
|
||||
.priority(1000)
|
||||
.serviceLevel("P1D")
|
||||
.buildAndStore(classificationService);
|
||||
ClassificationSummary classificationSummary = classification.asSummary();
|
||||
final List<String> indirectLinkedTasks =
|
||||
createTasksWithExistingClassificationInAttachment(
|
||||
classificationSummary,
|
||||
input.getLeft().getLeft(),
|
||||
input.getLeft().getRight(),
|
||||
3);
|
||||
|
||||
classification.setServiceLevel("P15D");
|
||||
classification.setPriority(1);
|
||||
classificationService.updateClassification(classification);
|
||||
runAssociatedJobs();
|
||||
|
||||
validateTaskProperties(
|
||||
before,
|
||||
indirectLinkedTasks,
|
||||
taskService,
|
||||
workingTimeCalculator,
|
||||
input.getRight().getLeft(),
|
||||
input.getRight().getRight());
|
||||
};
|
||||
|
||||
return DynamicTest.stream(
|
||||
zippedTestInputList.iterator(),
|
||||
i ->
|
||||
String.format(
|
||||
"for Task with ServiceLevel %s and Priority %s",
|
||||
i.getLeft().getLeft(), i.getLeft().getRight()),
|
||||
test);
|
||||
}
|
||||
|
||||
private void runAssociatedJobs() throws Exception {
|
||||
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();
|
||||
}
|
||||
|
||||
private void validateTaskProperties(
|
||||
Instant before,
|
||||
List<String> tasksUpdated,
|
||||
TaskService taskService,
|
||||
WorkingTimeCalculator workingTimeCalculator,
|
||||
int serviceLevel,
|
||||
int priority)
|
||||
throws Exception {
|
||||
for (String taskId : tasksUpdated) {
|
||||
Task task = taskService.getTask(taskId);
|
||||
|
||||
Instant expDue =
|
||||
workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(serviceLevel));
|
||||
assertThat(task.getModified())
|
||||
.describedAs("Task " + task.getId() + " has not been refreshed.")
|
||||
.isAfter(before);
|
||||
assertThat(task.getDue()).isEqualTo(expDue);
|
||||
assertThat(task.getPriority()).isEqualTo(priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
@Nested
|
||||
class UpdateClassificationExceptionTest {
|
||||
/**
|
||||
* This BeforeAll method is needed for this {@linkplain
|
||||
* #should_ThrowException_When_UserIsNotAuthorized test} and {@linkplain
|
||||
* #should_ThrowException_When_UserRoleIsNotAdminOrBusinessAdmin test} since it can't create an
|
||||
* own classification.
|
||||
*
|
||||
* @throws Exception for errors in the building or reading process of entities.
|
||||
*/
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@BeforeAll
|
||||
void createClassifications() throws Exception {
|
||||
defaultTestClassification()
|
||||
.key("BeforeAllClassification")
|
||||
.buildAndStore(classificationService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_ThrowException_When_UserIsNotAuthorized() throws Exception {
|
||||
Classification classification =
|
||||
classificationService.getClassification("BeforeAllClassification", "DOMAIN_A");
|
||||
classification.setCustomField(ClassificationCustomField.CUSTOM_1, "newCustom1");
|
||||
|
||||
NotAuthorizedException expectedException =
|
||||
new NotAuthorizedException(
|
||||
currentUserContext.getUserid(), TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN);
|
||||
assertThatThrownBy(() -> classificationService.updateClassification(classification))
|
||||
.usingRecursiveComparison()
|
||||
.isEqualTo(expectedException);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "taskadmin")
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@TestTemplate
|
||||
void should_ThrowException_When_UserRoleIsNotAdminOrBusinessAdmin() throws Exception {
|
||||
Classification classification =
|
||||
classificationService.getClassification("BeforeAllClassification", "DOMAIN_A");
|
||||
|
||||
classification.setApplicationEntryPoint("updated EntryPoint");
|
||||
classification.setName("updated Name");
|
||||
|
||||
NotAuthorizedException expectedException =
|
||||
new NotAuthorizedException(
|
||||
currentUserContext.getUserid(), TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN);
|
||||
assertThatThrownBy(() -> classificationService.updateClassification(classification))
|
||||
.usingRecursiveComparison()
|
||||
.isEqualTo(expectedException);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_ThrowException_When_UpdatingClassificationConcurrently() throws Exception {
|
||||
Classification classification =
|
||||
defaultTestClassification().buildAndStore(classificationService);
|
||||
final Classification classificationSecondUpdate =
|
||||
classificationService.getClassification(
|
||||
classification.getKey(), classification.getDomain());
|
||||
|
||||
classification.setApplicationEntryPoint("Application Entry Point");
|
||||
classification.setDescription("Description");
|
||||
classification.setName("Name");
|
||||
Thread.sleep(20); // to avoid identity of modified timestamps between classification and base
|
||||
classificationService.updateClassification(classification);
|
||||
classificationSecondUpdate.setName("Name again");
|
||||
classificationSecondUpdate.setDescription("Description again");
|
||||
|
||||
ConcurrencyException expectedException =
|
||||
new ConcurrencyException(classificationSecondUpdate.getId());
|
||||
assertThatThrownBy(
|
||||
() -> classificationService.updateClassification(classificationSecondUpdate))
|
||||
.usingRecursiveComparison()
|
||||
.isEqualTo(expectedException);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_ThrowException_When_TryingToUpdateClassificationWithInvalidParentId()
|
||||
throws Exception {
|
||||
Classification classification =
|
||||
defaultTestClassification().buildAndStore(classificationService);
|
||||
|
||||
classification.setParentId("NON EXISTING ID");
|
||||
|
||||
ClassificationNotFoundException expectedException =
|
||||
new ClassificationNotFoundException("NON EXISTING ID");
|
||||
assertThatThrownBy(() -> classificationService.updateClassification(classification))
|
||||
.usingRecursiveComparison()
|
||||
.isEqualTo(expectedException);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_ThrowException_When_TryingToUpdateClassificationWithInvalidParentKey()
|
||||
throws Exception {
|
||||
Classification classification =
|
||||
defaultTestClassification().buildAndStore(classificationService);
|
||||
|
||||
classification.setParentKey("NON EXISTING KEY");
|
||||
|
||||
ClassificationNotFoundException expectedException =
|
||||
new ClassificationNotFoundException("NON EXISTING KEY", "DOMAIN_A");
|
||||
assertThatThrownBy(() -> classificationService.updateClassification(classification))
|
||||
.usingRecursiveComparison()
|
||||
.isEqualTo(expectedException);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_ThrowException_When_TryingToUpdateClassificationWithOwnKeyAsParentKey()
|
||||
throws Exception {
|
||||
Classification classification =
|
||||
defaultTestClassification().buildAndStore(classificationService);
|
||||
|
||||
classification.setParentKey(classification.getKey());
|
||||
|
||||
InvalidArgumentException expectedException =
|
||||
new InvalidArgumentException(
|
||||
String.format(
|
||||
"The Classification '%s' has the same key and parent key",
|
||||
classification.getName()));
|
||||
assertThatThrownBy(() -> classificationService.updateClassification(classification))
|
||||
.usingRecursiveComparison()
|
||||
.isEqualTo(expectedException);
|
||||
}
|
||||
}
|
||||
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
@Nested
|
||||
class UpdateClassificationCategoryTest {
|
||||
Classification classification;
|
||||
Task task;
|
||||
Instant createdBefore;
|
||||
Instant modifiedBefore;
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@BeforeEach
|
||||
void createClassificationAndTask() throws Exception {
|
||||
classification =
|
||||
defaultTestClassification()
|
||||
.category("MANUAL")
|
||||
.type("TASK")
|
||||
.buildAndStore(classificationService);
|
||||
createdBefore = classification.getCreated();
|
||||
modifiedBefore = classification.getModified();
|
||||
String taskId = createTaskWithExistingClassification(classification.asSummary());
|
||||
task = taskService.getTask(taskId);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_UpdateTask_When_UpdatingClassificationCategory() throws Exception {
|
||||
classification.setCategory("PROCESS");
|
||||
classificationService.updateClassification(classification);
|
||||
final Task updatedTask = taskService.getTask(task.getId());
|
||||
|
||||
TaskImpl expectedUpdatedTask = (TaskImpl) task.copy();
|
||||
expectedUpdatedTask.setId(task.getId());
|
||||
expectedUpdatedTask.setClassificationCategory("PROCESS");
|
||||
expectedUpdatedTask.setClassificationSummary(
|
||||
classificationService.getClassification(classification.getId()).asSummary());
|
||||
expectedUpdatedTask.setExternalId(task.getExternalId());
|
||||
assertThat(expectedUpdatedTask)
|
||||
.usingRecursiveComparison()
|
||||
.ignoringFields("modified")
|
||||
.isEqualTo(updatedTask);
|
||||
assertThat(expectedUpdatedTask.getModified()).isAfterOrEqualTo(modifiedBefore);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void should_UpdateClassification_When_UpdatingClassificationCategory() throws Exception {
|
||||
classification.setCategory("PROCESS");
|
||||
classificationService.updateClassification(classification);
|
||||
|
||||
Classification updatedClassification =
|
||||
classificationService.getClassification(classification.getId());
|
||||
assertThat(updatedClassification)
|
||||
.usingRecursiveComparison()
|
||||
.ignoringFields("modified")
|
||||
.isEqualTo(classification);
|
||||
assertThat(updatedClassification.getModified()).isAfterOrEqualTo(modifiedBefore);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,18 +5,26 @@ import static pro.taskana.testapi.DefaultTestEntities.defaultTestClassification;
|
|||
import static pro.taskana.testapi.DefaultTestEntities.defaultTestObjectReference;
|
||||
import static pro.taskana.testapi.DefaultTestEntities.defaultTestWorkbasket;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
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 pro.taskana.TaskanaConfiguration.Builder;
|
||||
import pro.taskana.classification.api.ClassificationService;
|
||||
import pro.taskana.classification.api.models.ClassificationSummary;
|
||||
import pro.taskana.common.api.BulkOperationResults;
|
||||
import pro.taskana.common.api.TaskanaEngine;
|
||||
import pro.taskana.common.api.WorkingTimeCalculator;
|
||||
import pro.taskana.common.api.exceptions.TaskanaException;
|
||||
import pro.taskana.task.api.TaskService;
|
||||
import pro.taskana.task.api.models.Attachment;
|
||||
import pro.taskana.task.api.models.ObjectReference;
|
||||
import pro.taskana.task.api.models.TaskSummary;
|
||||
import pro.taskana.testapi.TaskanaConfigurationModifier;
|
||||
import pro.taskana.testapi.TaskanaInject;
|
||||
import pro.taskana.testapi.TaskanaIntegrationTest;
|
||||
import pro.taskana.testapi.builder.TaskAttachmentBuilder;
|
||||
|
@ -37,6 +45,9 @@ class ServiceLevelOfAllTasksAccTest {
|
|||
private static final String SMALL_CLASSIFICATION_SERVICE_LEVEL = "P2D";
|
||||
private static final String GREAT_CLASSIFICATION_SERVICE_LEVEL = "P7D";
|
||||
|
||||
@Nested
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class WithWorkingTimeCalculation {
|
||||
@TaskanaInject TaskService taskService;
|
||||
@TaskanaInject WorkbasketService workbasketService;
|
||||
@TaskanaInject ClassificationService classificationService;
|
||||
|
@ -205,4 +216,193 @@ class ServiceLevelOfAllTasksAccTest {
|
|||
.workbasketSummary(defaultWorkbasketSummary)
|
||||
.primaryObjRef(defaultObjectReference));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class WithWorkingDaysCalculation implements TaskanaConfigurationModifier {
|
||||
|
||||
@TaskanaInject TaskanaEngine taskanaEngine;
|
||||
@TaskanaInject TaskService taskService;
|
||||
@TaskanaInject WorkbasketService workbasketService;
|
||||
@TaskanaInject ClassificationService classificationService;
|
||||
ClassificationSummary classificationSummarySmallServiceLevel;
|
||||
ClassificationSummary classificationSummaryGreatServiceLevel;
|
||||
Attachment attachmentSummarySmallServiceLevel;
|
||||
Attachment attachmentSummaryGreatServiceLevel;
|
||||
WorkbasketSummary defaultWorkbasketSummary;
|
||||
ObjectReference defaultObjectReference;
|
||||
WorkingTimeCalculator converter;
|
||||
|
||||
@Override
|
||||
public Builder modify(Builder builder) {
|
||||
return builder.useWorkingTimeCalculation(false);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@BeforeAll
|
||||
void setup() throws Exception {
|
||||
classificationSummarySmallServiceLevel =
|
||||
defaultTestClassification()
|
||||
.serviceLevel(SMALL_CLASSIFICATION_SERVICE_LEVEL)
|
||||
.buildAndStoreAsSummary(classificationService);
|
||||
classificationSummaryGreatServiceLevel =
|
||||
defaultTestClassification()
|
||||
.serviceLevel(GREAT_CLASSIFICATION_SERVICE_LEVEL)
|
||||
.buildAndStoreAsSummary(classificationService);
|
||||
|
||||
defaultObjectReference = defaultTestObjectReference().build();
|
||||
|
||||
attachmentSummarySmallServiceLevel =
|
||||
TaskAttachmentBuilder.newAttachment()
|
||||
.classificationSummary(classificationSummarySmallServiceLevel)
|
||||
.objectReference(defaultObjectReference)
|
||||
.build();
|
||||
attachmentSummaryGreatServiceLevel =
|
||||
TaskAttachmentBuilder.newAttachment()
|
||||
.classificationSummary(classificationSummaryGreatServiceLevel)
|
||||
.objectReference(defaultObjectReference)
|
||||
.build();
|
||||
|
||||
defaultWorkbasketSummary = defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
|
||||
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
|
||||
.workbasketId(defaultWorkbasketSummary.getId())
|
||||
.accessId("user-1-1")
|
||||
.permission(WorkbasketPermission.OPEN)
|
||||
.permission(WorkbasketPermission.READ)
|
||||
.permission(WorkbasketPermission.READTASKS)
|
||||
.permission(WorkbasketPermission.APPEND)
|
||||
.buildAndStore(workbasketService);
|
||||
converter = taskanaEngine.getWorkingTimeCalculator();
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_SetPlannedOnMultipleTasks() throws Exception {
|
||||
Instant planned = Instant.parse("2020-05-03T07:00:00.000Z");
|
||||
TaskSummary task1 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummarySmallServiceLevel)
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
TaskSummary task2 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummarySmallServiceLevel)
|
||||
.attachments(attachmentSummaryGreatServiceLevel.copy())
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
TaskSummary task3 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummaryGreatServiceLevel)
|
||||
.attachments(attachmentSummarySmallServiceLevel.copy())
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
List<String> taskIds = List.of(task1.getId(), task2.getId(), task3.getId());
|
||||
|
||||
BulkOperationResults<String, TaskanaException> bulkLog =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
|
||||
assertThat(bulkLog.containsErrors()).isFalse();
|
||||
List<TaskSummary> result =
|
||||
taskService.createTaskQuery().idIn(task1.getId(), task2.getId(), task3.getId()).list();
|
||||
assertThat(result).extracting(TaskSummary::getPlanned).containsOnly(planned);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ChangeDue_When_SettingPlannedAndClassificationHasSmallerServiceLevel()
|
||||
throws Exception {
|
||||
Instant planned = Instant.parse("2020-05-03T07:00:00.000Z");
|
||||
TaskSummary task1 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummarySmallServiceLevel)
|
||||
.attachments(attachmentSummaryGreatServiceLevel.copy())
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
TaskSummary task2 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummarySmallServiceLevel)
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
List<String> taskIds = List.of(task1.getId(), task2.getId());
|
||||
|
||||
BulkOperationResults<String, TaskanaException> bulkLog =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
|
||||
assertThat(bulkLog.containsErrors()).isFalse();
|
||||
List<TaskSummary> result =
|
||||
taskService.createTaskQuery().idIn(task1.getId(), task2.getId()).list();
|
||||
assertThat(result)
|
||||
.extracting(TaskSummary::getDue)
|
||||
.containsOnly(
|
||||
converter.addWorkingTime(
|
||||
planned, Duration.parse(SMALL_CLASSIFICATION_SERVICE_LEVEL)));
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ChangeDue_When_SettingPlannedAndAttachmentHasSmallerOrEqualServiceLevel()
|
||||
throws Exception {
|
||||
Instant planned = Instant.parse("2020-05-03T07:00:00.000Z");
|
||||
TaskSummary task1 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummaryGreatServiceLevel)
|
||||
.attachments(attachmentSummarySmallServiceLevel.copy())
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
TaskSummary task2 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummarySmallServiceLevel)
|
||||
.attachments(attachmentSummarySmallServiceLevel.copy())
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
List<String> taskIds = List.of(task1.getId(), task2.getId());
|
||||
|
||||
BulkOperationResults<String, TaskanaException> bulkLog =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
|
||||
assertThat(bulkLog.containsErrors()).isFalse();
|
||||
List<TaskSummary> result =
|
||||
taskService.createTaskQuery().idIn(task1.getId(), task2.getId()).list();
|
||||
assertThat(result)
|
||||
.extracting(TaskSummary::getDue)
|
||||
.containsOnly(
|
||||
converter.addWorkingTime(
|
||||
planned, Duration.parse(SMALL_CLASSIFICATION_SERVICE_LEVEL)));
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ChangeDue_When_SettingPlannedAndUsingDifferentServiceLevels() throws Exception {
|
||||
Instant planned = Instant.parse("2020-05-03T07:00:00.000Z");
|
||||
TaskSummary task1 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummaryGreatServiceLevel)
|
||||
.attachments(attachmentSummarySmallServiceLevel.copy())
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
TaskSummary task2 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummarySmallServiceLevel)
|
||||
.attachments(attachmentSummaryGreatServiceLevel.copy())
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
TaskSummary task3 =
|
||||
createDefaultTask()
|
||||
.classificationSummary(classificationSummaryGreatServiceLevel)
|
||||
.attachments(attachmentSummaryGreatServiceLevel.copy())
|
||||
.buildAndStoreAsSummary(taskService);
|
||||
List<String> taskIds = List.of(task1.getId(), task2.getId(), task3.getId());
|
||||
|
||||
BulkOperationResults<String, TaskanaException> bulkLog =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
|
||||
assertThat(bulkLog.containsErrors()).isFalse();
|
||||
List<TaskSummary> result =
|
||||
taskService.createTaskQuery().idIn(task1.getId(), task2.getId(), task3.getId()).list();
|
||||
assertThat(result)
|
||||
.extracting(TaskSummary::getDue)
|
||||
.containsOnly(
|
||||
converter.addWorkingTime(planned, Duration.parse(SMALL_CLASSIFICATION_SERVICE_LEVEL)),
|
||||
converter.addWorkingTime(
|
||||
planned, Duration.parse(GREAT_CLASSIFICATION_SERVICE_LEVEL)));
|
||||
}
|
||||
|
||||
private TaskBuilder createDefaultTask() {
|
||||
return (TaskBuilder.newTask()
|
||||
.workbasketSummary(defaultWorkbasketSummary)
|
||||
.primaryObjRef(defaultObjectReference));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ taskana.classification.types=TASK | document
|
|||
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
|
||||
taskana.classification.categories.document=EXTERNAL
|
||||
# working time configuration
|
||||
taskana.workingTime.useWorkingTimeCalculation=false
|
||||
taskana.workingTime.schedule.MONDAY=09:00-18:00
|
||||
taskana.workingTime.schedule.TUESDAY=09:00-18:00
|
||||
taskana.workingTime.schedule.WEDNESDAY=09:00-18:00
|
||||
|
|
|
@ -73,6 +73,7 @@ public class TaskanaConfiguration {
|
|||
// endregion
|
||||
|
||||
// region working time configuration
|
||||
private final boolean useWorkingTimeCalculation;
|
||||
private final Map<DayOfWeek, Set<LocalTimeInterval>> workingTimeSchedule;
|
||||
private final ZoneId workingTimeScheduleTimeZone;
|
||||
private final Set<CustomHoliday> customHolidays;
|
||||
|
@ -153,6 +154,7 @@ public class TaskanaConfiguration {
|
|||
Collectors.toUnmodifiableMap(
|
||||
Entry::getKey, e -> Collections.unmodifiableList(e.getValue())));
|
||||
// working time configuration
|
||||
this.useWorkingTimeCalculation = builder.useWorkingTimeCalculation;
|
||||
this.workingTimeSchedule =
|
||||
builder.workingTimeSchedule.entrySet().stream()
|
||||
.collect(
|
||||
|
@ -262,6 +264,10 @@ public class TaskanaConfiguration {
|
|||
return classificationTypes;
|
||||
}
|
||||
|
||||
public boolean isUseWorkingTimeCalculation() {
|
||||
return useWorkingTimeCalculation;
|
||||
}
|
||||
|
||||
public Map<DayOfWeek, Set<LocalTimeInterval>> getWorkingTimeSchedule() {
|
||||
return workingTimeSchedule;
|
||||
}
|
||||
|
@ -424,6 +430,7 @@ public class TaskanaConfiguration {
|
|||
roleMap,
|
||||
classificationTypes,
|
||||
classificationCategoriesByType,
|
||||
useWorkingTimeCalculation,
|
||||
workingTimeSchedule,
|
||||
workingTimeScheduleTimeZone,
|
||||
customHolidays,
|
||||
|
@ -473,6 +480,7 @@ public class TaskanaConfiguration {
|
|||
return useManagedTransactions == other.useManagedTransactions
|
||||
&& securityEnabled == other.securityEnabled
|
||||
&& enforceServiceLevel == other.enforceServiceLevel
|
||||
&& useWorkingTimeCalculation == other.useWorkingTimeCalculation
|
||||
&& germanPublicHolidaysEnabled == other.germanPublicHolidaysEnabled
|
||||
&& germanPublicHolidaysCorpusChristiEnabled
|
||||
== other.germanPublicHolidaysCorpusChristiEnabled
|
||||
|
@ -542,6 +550,8 @@ public class TaskanaConfiguration {
|
|||
+ classificationTypes
|
||||
+ ", classificationCategoriesByType="
|
||||
+ classificationCategoriesByType
|
||||
+ ", useWorkingTimeCalculation="
|
||||
+ useWorkingTimeCalculation
|
||||
+ ", workingTimeSchedule="
|
||||
+ workingTimeSchedule
|
||||
+ ", workingTimeScheduleTimeZone="
|
||||
|
@ -650,6 +660,10 @@ public class TaskanaConfiguration {
|
|||
// endregion
|
||||
|
||||
// region working time configuration
|
||||
|
||||
@TaskanaProperty("taskana.workingTime.useWorkingTimeCalculation")
|
||||
private boolean useWorkingTimeCalculation = true;
|
||||
|
||||
@TaskanaProperty("taskana.workingTime.schedule")
|
||||
private Map<DayOfWeek, Set<LocalTimeInterval>> workingTimeSchedule =
|
||||
initDefaultWorkingTimeSchedule();
|
||||
|
@ -826,6 +840,7 @@ public class TaskanaConfiguration {
|
|||
this.classificationTypes = conf.classificationTypes;
|
||||
this.classificationCategoriesByType = conf.classificationCategoriesByType;
|
||||
// working time configuration
|
||||
this.useWorkingTimeCalculation = conf.useWorkingTimeCalculation;
|
||||
this.workingTimeSchedule = conf.workingTimeSchedule;
|
||||
this.workingTimeScheduleTimeZone = conf.workingTimeScheduleTimeZone;
|
||||
this.customHolidays = conf.customHolidays;
|
||||
|
@ -964,6 +979,11 @@ public class TaskanaConfiguration {
|
|||
|
||||
// region working time configuration
|
||||
|
||||
public Builder useWorkingTimeCalculation(boolean useWorkingTimeCalculation) {
|
||||
this.useWorkingTimeCalculation = useWorkingTimeCalculation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder workingTimeSchedule(Map<DayOfWeek, Set<LocalTimeInterval>> workingTimeSchedule) {
|
||||
this.workingTimeSchedule = workingTimeSchedule;
|
||||
return this;
|
||||
|
|
|
@ -51,6 +51,7 @@ import pro.taskana.common.internal.persistence.MapTypeHandler;
|
|||
import pro.taskana.common.internal.persistence.StringTypeHandler;
|
||||
import pro.taskana.common.internal.security.CurrentUserContextImpl;
|
||||
import pro.taskana.common.internal.workingtime.HolidaySchedule;
|
||||
import pro.taskana.common.internal.workingtime.WorkingDayCalculatorImpl;
|
||||
import pro.taskana.common.internal.workingtime.WorkingTimeCalculatorImpl;
|
||||
import pro.taskana.monitor.api.MonitorService;
|
||||
import pro.taskana.monitor.internal.MonitorMapper;
|
||||
|
@ -128,11 +129,18 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
taskanaConfiguration.isGermanPublicHolidaysEnabled(),
|
||||
taskanaConfiguration.isGermanPublicHolidaysCorpusChristiEnabled(),
|
||||
taskanaConfiguration.getCustomHolidays());
|
||||
if (taskanaConfiguration.isUseWorkingTimeCalculation()) {
|
||||
workingTimeCalculator =
|
||||
new WorkingTimeCalculatorImpl(
|
||||
holidaySchedule,
|
||||
taskanaConfiguration.getWorkingTimeSchedule(),
|
||||
taskanaConfiguration.getWorkingTimeScheduleTimeZone());
|
||||
} else {
|
||||
workingTimeCalculator =
|
||||
new WorkingDayCalculatorImpl(
|
||||
holidaySchedule, taskanaConfiguration.getWorkingTimeScheduleTimeZone());
|
||||
}
|
||||
|
||||
currentUserContext =
|
||||
new CurrentUserContextImpl(TaskanaConfiguration.shouldUseLowerCaseForAccessIds());
|
||||
createTransactionFactory(taskanaConfiguration.isUseManagedTransactions());
|
||||
|
|
|
@ -303,7 +303,8 @@ class ServiceLevelHandler {
|
|||
|
||||
private Instant calculateDue(Instant planned, Duration duration) {
|
||||
Instant dueExclusive = workingTimeCalculator.addWorkingTime(planned, duration);
|
||||
if (!planned.equals(dueExclusive)) {
|
||||
if (taskanaEngine.getEngine().getConfiguration().isUseWorkingTimeCalculation()
|
||||
&& !planned.equals(dueExclusive)) {
|
||||
// Calculation is exclusive, but we want due date to be inclusive. Hence, we subtract a
|
||||
// millisecond
|
||||
// If planned and dueExclusive are the same values, we don't want due to be before planned.
|
||||
|
@ -320,7 +321,11 @@ class ServiceLevelHandler {
|
|||
return due;
|
||||
} else {
|
||||
// due is inclusive, but calculation happens exclusive.
|
||||
return workingTimeCalculator.subtractWorkingTime(due.plusMillis(1), duration);
|
||||
Instant normalize =
|
||||
taskanaEngine.getEngine().getConfiguration().isUseWorkingTimeCalculation()
|
||||
? due.plusMillis(1)
|
||||
: due;
|
||||
return workingTimeCalculator.subtractWorkingTime(normalize, duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,11 +333,15 @@ class ServiceLevelHandler {
|
|||
// plusMillis since due is inclusive, but calculation happens exclusive.
|
||||
// minusMillis since we calculated a due date
|
||||
// Without that some edge case fail (e.g. due is exactly the start of weekend)
|
||||
if (taskanaEngine.getEngine().getConfiguration().isUseWorkingTimeCalculation()) {
|
||||
return workingTimeCalculator
|
||||
.subtractWorkingTime(due.plusMillis(1), Duration.ZERO)
|
||||
.minusMillis(1);
|
||||
}
|
||||
|
||||
return workingTimeCalculator.subtractWorkingTime(due, Duration.ZERO);
|
||||
}
|
||||
|
||||
private Instant normalizePlanned(Instant instant) {
|
||||
return workingTimeCalculator.addWorkingTime(instant, Duration.ZERO);
|
||||
}
|
||||
|
@ -625,9 +634,9 @@ class ServiceLevelHandler {
|
|||
}
|
||||
// TODO Do we need to compare Key and Id or could we simply compare ClassificationSummary only?
|
||||
final boolean isClassificationKeyChanged =
|
||||
Objects.equals(newTaskImpl.getClassificationKey(), oldTaskImpl.getClassificationKey());
|
||||
!Objects.equals(newTaskImpl.getClassificationKey(), oldTaskImpl.getClassificationKey());
|
||||
final boolean isClassificationIdChanged =
|
||||
Objects.equals(newTaskImpl.getClassificationId(), oldTaskImpl.getClassificationId());
|
||||
!Objects.equals(newTaskImpl.getClassificationId(), oldTaskImpl.getClassificationId());
|
||||
|
||||
final boolean isManualPriorityChanged =
|
||||
newTaskImpl.getManualPriority() != oldTaskImpl.getManualPriority();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package acceptance;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
|
@ -56,6 +57,14 @@ public abstract class AbstractAccTest {
|
|||
.ifPresent(JobScheduler::stop);
|
||||
}
|
||||
|
||||
protected static void initTaskanaEngine(TaskanaConfiguration configuration) throws SQLException {
|
||||
taskanaConfiguration = configuration;
|
||||
taskanaEngine =
|
||||
TaskanaEngine.buildTaskanaEngine(taskanaConfiguration, ConnectionManagementMode.AUTOCOMMIT);
|
||||
taskService = (TaskServiceImpl) taskanaEngine.getTaskService();
|
||||
workingTimeCalculator = taskanaEngine.getWorkingTimeCalculator();
|
||||
}
|
||||
|
||||
protected static void resetDb(boolean dropTables) throws Exception {
|
||||
|
||||
DataSource dataSource = DataSourceGenerator.getDataSource();
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
package acceptance.persistence;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static pro.taskana.common.api.SharedConstants.MASTER_DOMAIN;
|
||||
|
||||
import acceptance.AbstractAccTest;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import pro.taskana.TaskanaConfiguration;
|
||||
import pro.taskana.TaskanaConfiguration.Builder;
|
||||
import pro.taskana.classification.api.ClassificationService;
|
||||
import pro.taskana.classification.api.models.Classification;
|
||||
import pro.taskana.common.api.JobService;
|
||||
import pro.taskana.common.api.ScheduledJob;
|
||||
import pro.taskana.common.internal.JobServiceImpl;
|
||||
import pro.taskana.common.test.security.JaasExtension;
|
||||
import pro.taskana.common.test.security.WithAccessId;
|
||||
import pro.taskana.task.api.TaskCustomField;
|
||||
import pro.taskana.task.api.TaskService;
|
||||
import pro.taskana.task.api.models.Task;
|
||||
import pro.taskana.task.internal.jobs.TaskCleanupJob;
|
||||
import pro.taskana.task.internal.models.TaskImpl;
|
||||
import pro.taskana.workbasket.api.WorkbasketCustomField;
|
||||
import pro.taskana.workbasket.api.WorkbasketPermission;
|
||||
import pro.taskana.workbasket.api.WorkbasketService;
|
||||
import pro.taskana.workbasket.api.WorkbasketType;
|
||||
import pro.taskana.workbasket.api.models.Workbasket;
|
||||
import pro.taskana.workbasket.api.models.WorkbasketAccessItem;
|
||||
|
||||
@ExtendWith(JaasExtension.class)
|
||||
public class UpdateObjectsUseUtcTimeStampsWithWorkingDaysCalculationAccTest
|
||||
extends AbstractAccTest {
|
||||
|
||||
@BeforeAll
|
||||
protected static void setupTest() throws Exception {
|
||||
resetDb(false);
|
||||
|
||||
TaskanaConfiguration config =
|
||||
new Builder(taskanaConfiguration).useWorkingTimeCalculation(false).build();
|
||||
|
||||
initTaskanaEngine(config);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void testTimestampsOnTaskUpdate() throws Exception {
|
||||
TaskService taskService = taskanaEngine.getTaskService();
|
||||
Task task = taskService.getTask("TKI:000000000000000000000000000000000000");
|
||||
Instant now = Instant.now();
|
||||
|
||||
task.setPlanned(now.plus(Duration.ofHours(17)));
|
||||
|
||||
// associated Classification has ServiceLevel 'P1D'
|
||||
task.setDue(workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1)));
|
||||
|
||||
TaskImpl ti = (TaskImpl) task;
|
||||
ti.setCompleted(now.plus(Duration.ofHours(27)));
|
||||
TimeZone originalZone = TimeZone.getDefault();
|
||||
Task updatedTask = taskService.updateTask(task);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
|
||||
Task retrievedTask = taskService.getTask(updatedTask.getId());
|
||||
TimeZone.setDefault(originalZone);
|
||||
assertThat(retrievedTask).isEqualTo(updatedTask);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void testCreatedTaskObjectEqualsReadTaskObjectInNewTimezone() throws Exception {
|
||||
|
||||
TaskService taskService = taskanaEngine.getTaskService();
|
||||
Task newTask = taskService.newTask("USER-1-1", "DOMAIN_A");
|
||||
newTask.setClassificationKey("T2100");
|
||||
newTask.setPrimaryObjRef(
|
||||
createObjectReference("COMPANY_A", "SYSTEM_A", "INSTANCE_A", "VNR", "1234567"));
|
||||
for (TaskCustomField taskCustomField : TaskCustomField.values()) {
|
||||
newTask.setCustomField(taskCustomField, taskCustomField.name());
|
||||
}
|
||||
newTask.setCustomAttributeMap(createSimpleCustomPropertyMap(5));
|
||||
newTask.setDescription("Description of test task");
|
||||
newTask.setNote("My note");
|
||||
newTask.addAttachment(
|
||||
createExampleAttachment(
|
||||
"DOCTYPE_DEFAULT",
|
||||
createObjectReference(
|
||||
"COMPANY_A",
|
||||
"SYSTEM_B",
|
||||
"INSTANCE_B",
|
||||
"ArchiveId",
|
||||
"12345678901234567890123456789012345678901234567890"),
|
||||
"E-MAIL",
|
||||
Instant.parse("2018-01-15T00:00:00Z"),
|
||||
createSimpleCustomPropertyMap(3)));
|
||||
|
||||
TimeZone originalZone = TimeZone.getDefault();
|
||||
Task createdTask = taskService.createTask(newTask);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
|
||||
Task readTask = taskService.getTask(createdTask.getId());
|
||||
TimeZone.setDefault(originalZone);
|
||||
assertThat(readTask).isEqualTo(createdTask);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void testTimestampsOnClassificationUpdate() throws Exception {
|
||||
ClassificationService classificationService = taskanaEngine.getClassificationService();
|
||||
Classification classification =
|
||||
classificationService.getClassification("CLI:000000000000000000000000000000000001");
|
||||
classification.setPriority(17);
|
||||
|
||||
TimeZone originalZone = TimeZone.getDefault();
|
||||
Classification updatedClassification =
|
||||
classificationService.updateClassification(classification);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
|
||||
Classification retrievedClassification =
|
||||
classificationService.getClassification(updatedClassification.getId());
|
||||
TimeZone.setDefault(originalZone);
|
||||
assertThat(retrievedClassification).isEqualTo(updatedClassification);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void testTimestampsOnCreateMasterClassification() throws Exception {
|
||||
ClassificationService classificationService = taskanaEngine.getClassificationService();
|
||||
final long amountOfClassificationsBefore =
|
||||
classificationService.createClassificationQuery().count();
|
||||
Classification classification =
|
||||
classificationService.newClassification("Key0", MASTER_DOMAIN, "TASK");
|
||||
classification.setIsValidInDomain(true);
|
||||
classification.setServiceLevel("P1D");
|
||||
classification = classificationService.createClassification(classification);
|
||||
|
||||
// check only 1 created
|
||||
long amountOfClassificationsAfter = classificationService.createClassificationQuery().count();
|
||||
assertThat(amountOfClassificationsAfter).isEqualTo(amountOfClassificationsBefore + 1);
|
||||
|
||||
TimeZone originalZone = TimeZone.getDefault();
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
|
||||
Classification retrievedClassification =
|
||||
classificationService.getClassification(classification.getId());
|
||||
TimeZone.setDefault(originalZone);
|
||||
|
||||
assertThat(retrievedClassification).isEqualTo(classification);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void testTimestampsOnWorkbasketUpdate() throws Exception {
|
||||
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
|
||||
Workbasket workbasket =
|
||||
workbasketService.getWorkbasket("WBI:100000000000000000000000000000000001");
|
||||
workbasket.setCustomField(WorkbasketCustomField.CUSTOM_1, "bla");
|
||||
|
||||
TimeZone originalZone = TimeZone.getDefault();
|
||||
Workbasket updatedWorkbasket = workbasketService.updateWorkbasket(workbasket);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
|
||||
Workbasket retrievedWorkbasket = workbasketService.getWorkbasket(updatedWorkbasket.getId());
|
||||
TimeZone.setDefault(originalZone);
|
||||
assertThat(retrievedWorkbasket).isEqualTo(updatedWorkbasket);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "businessadmin")
|
||||
@Test
|
||||
void testTimestampsOnCreateWorkbasket() throws Exception {
|
||||
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
|
||||
final int before = workbasketService.createWorkbasketQuery().domainIn("DOMAIN_A").list().size();
|
||||
|
||||
Workbasket workbasket = workbasketService.newWorkbasket("NT1234", "DOMAIN_A");
|
||||
workbasket.setName("Megabasket");
|
||||
workbasket.setType(WorkbasketType.GROUP);
|
||||
workbasket.setOrgLevel1("company");
|
||||
workbasket = workbasketService.createWorkbasket(workbasket);
|
||||
WorkbasketAccessItem wbai =
|
||||
workbasketService.newWorkbasketAccessItem(workbasket.getId(), "user-1-2");
|
||||
wbai.setPermission(WorkbasketPermission.READ, true);
|
||||
workbasketService.createWorkbasketAccessItem(wbai);
|
||||
|
||||
int after = workbasketService.createWorkbasketQuery().domainIn("DOMAIN_A").list().size();
|
||||
assertThat(after).isEqualTo(before + 1);
|
||||
|
||||
TimeZone originalZone = TimeZone.getDefault();
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
|
||||
Workbasket retrievedWorkbasket = workbasketService.getWorkbasket("NT1234", "DOMAIN_A");
|
||||
TimeZone.setDefault(originalZone);
|
||||
assertThat(retrievedWorkbasket).isEqualTo(workbasket);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-2")
|
||||
@Test
|
||||
void testTimestampsOnCreateScheduledJob() throws Exception {
|
||||
resetDb(true);
|
||||
ScheduledJob job = new ScheduledJob();
|
||||
job.setArguments(Map.of("keyBla", "valueBla"));
|
||||
job.setType(TaskCleanupJob.class.getName());
|
||||
job.setDue(Instant.now().minus(Duration.ofHours(5)));
|
||||
job.setLockExpires(Instant.now().minus(Duration.ofHours(5)));
|
||||
JobService jobService = taskanaEngine.getJobService();
|
||||
job = jobService.createJob(job);
|
||||
TimeZone originalZone = TimeZone.getDefault();
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
|
||||
|
||||
JobServiceImpl jobServiceImpl = (JobServiceImpl) jobService;
|
||||
List<ScheduledJob> jobs = jobServiceImpl.findJobsToRun();
|
||||
final ScheduledJob jobForLambda = job;
|
||||
ScheduledJob retrievedJob =
|
||||
jobs.stream()
|
||||
.filter(
|
||||
j ->
|
||||
j.getJobId().equals(jobForLambda.getJobId())
|
||||
&& j.getArguments() != null
|
||||
&& "valueBla".equals(j.getArguments().get("keyBla")))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
TimeZone.setDefault(originalZone);
|
||||
assertThat(retrievedJob).isEqualTo(job);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,616 @@
|
|||
package acceptance.task;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import acceptance.AbstractAccTest;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.assertj.core.data.TemporalUnitWithinOffset;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import pro.taskana.TaskanaConfiguration;
|
||||
import pro.taskana.TaskanaConfiguration.Builder;
|
||||
import pro.taskana.classification.api.ClassificationService;
|
||||
import pro.taskana.classification.api.models.Classification;
|
||||
import pro.taskana.common.api.BulkOperationResults;
|
||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||
import pro.taskana.common.api.exceptions.TaskanaException;
|
||||
import pro.taskana.common.test.security.JaasExtension;
|
||||
import pro.taskana.common.test.security.WithAccessId;
|
||||
import pro.taskana.task.api.TaskService;
|
||||
import pro.taskana.task.api.exceptions.TaskNotFoundException;
|
||||
import pro.taskana.task.api.models.Task;
|
||||
import pro.taskana.workbasket.api.exceptions.NotAuthorizedOnWorkbasketException;
|
||||
|
||||
@ExtendWith(JaasExtension.class)
|
||||
public class ServiceLevelPriorityWithWorkingDaysCalculationAccTest extends AbstractAccTest {
|
||||
|
||||
private static ClassificationService classificationService;
|
||||
|
||||
@BeforeAll
|
||||
protected static void setupTest() throws Exception {
|
||||
resetDb(false);
|
||||
|
||||
TaskanaConfiguration config =
|
||||
new Builder(taskanaConfiguration).useWorkingTimeCalculation(false).build();
|
||||
|
||||
initTaskanaEngine(config);
|
||||
classificationService = taskanaEngine.getClassificationService();
|
||||
}
|
||||
|
||||
/* CREATE TASK */
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_CalculatePlannedDateAtCreate() throws Exception {
|
||||
|
||||
// P16D
|
||||
Classification classification = classificationService.getClassification("L110105", "DOMAIN_A");
|
||||
long serviceLevelDays = Duration.parse(classification.getServiceLevel()).toDays();
|
||||
assertThat(serviceLevelDays).isEqualTo(16);
|
||||
|
||||
Task newTask = taskService.newTask("USER-1-1", classification.getDomain());
|
||||
newTask.setClassificationKey(classification.getKey());
|
||||
newTask.setPrimaryObjRef(
|
||||
createObjectReference("COMPANY_A", "SYSTEM_A", "INSTANCE_A", "VNR", "1234567"));
|
||||
|
||||
Instant due =
|
||||
moveBackToWorkingDay(
|
||||
Instant.now().truncatedTo(ChronoUnit.MILLIS).plus(40, ChronoUnit.DAYS));
|
||||
newTask.setDue(due);
|
||||
Task createdTask = taskService.createTask(newTask);
|
||||
assertThat(createdTask.getId()).isNotNull();
|
||||
|
||||
Task readTask = taskService.getTask(createdTask.getId());
|
||||
assertThat(readTask).isNotNull();
|
||||
assertThat(readTask.getDue()).isEqualTo(due);
|
||||
|
||||
Instant expectedPlanned =
|
||||
workingTimeCalculator.subtractWorkingTime(due, Duration.ofDays(serviceLevelDays));
|
||||
assertThat(readTask.getPlanned()).isEqualTo(expectedPlanned);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_CalculateDueDateAtCreate() throws Exception {
|
||||
|
||||
// P16D
|
||||
Classification classification = classificationService.getClassification("L110105", "DOMAIN_A");
|
||||
long serviceLevelDays = Duration.parse(classification.getServiceLevel()).toDays();
|
||||
assertThat(serviceLevelDays).isEqualTo(16);
|
||||
|
||||
Task newTask = taskService.newTask("USER-1-1", classification.getDomain());
|
||||
newTask.setClassificationKey(classification.getKey());
|
||||
newTask.setPrimaryObjRef(
|
||||
createObjectReference("COMPANY_A", "SYSTEM_A", "INSTANCE_A", "VNR", "1234567"));
|
||||
|
||||
Instant planned = moveForwardToWorkingDay(Instant.now().truncatedTo(ChronoUnit.MILLIS));
|
||||
newTask.setPlanned(planned);
|
||||
Task createdTask = taskService.createTask(newTask);
|
||||
assertThat(createdTask.getId()).isNotNull();
|
||||
|
||||
Task readTask = taskService.getTask(createdTask.getId());
|
||||
assertThat(readTask).isNotNull();
|
||||
assertThat(readTask.getPlanned()).isEqualTo(planned);
|
||||
|
||||
Instant expectedDue =
|
||||
workingTimeCalculator.addWorkingTime(
|
||||
readTask.getPlanned(), Duration.ofDays(serviceLevelDays));
|
||||
|
||||
assertThat(readTask.getDue()).isEqualTo(expectedDue);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_NotThrowException_When_DueAndPlannedAreConsistent() throws Exception {
|
||||
|
||||
Classification classification = classificationService.getClassification("T2100", "DOMAIN_A");
|
||||
long duration = Duration.parse(classification.getServiceLevel()).toDays();
|
||||
|
||||
Task newTask = taskService.newTask("USER-1-1", "DOMAIN_A");
|
||||
newTask.setPlanned(moveForwardToWorkingDay(Instant.now()));
|
||||
newTask.setClassificationKey(classification.getKey());
|
||||
newTask.setPrimaryObjRef(
|
||||
createObjectReference("COMPANY_A", "SYSTEM_A", "INSTANCE_A", "VNR", "1234567"));
|
||||
newTask.setOwner("user-1-1");
|
||||
|
||||
// due date according to service level
|
||||
Instant expectedDue =
|
||||
workingTimeCalculator.addWorkingTime(newTask.getPlanned(), Duration.ofDays(duration));
|
||||
|
||||
newTask.setDue(expectedDue);
|
||||
ThrowingCallable call = () -> taskService.createTask(newTask);
|
||||
assertThatCode(call).doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowException_When_DueAndPlannedAreInconsistent() {
|
||||
|
||||
Task newTask = taskService.newTask("USER-1-1", "DOMAIN_A");
|
||||
Instant planned = moveForwardToWorkingDay(Instant.now().plus(2, ChronoUnit.HOURS));
|
||||
newTask.setClassificationKey("T2100"); // P10D
|
||||
newTask.setPrimaryObjRef(
|
||||
createObjectReference("COMPANY_A", "SYSTEM_A", "INSTANCE_A", "VNR", "1234567"));
|
||||
newTask.setOwner("user-1-1");
|
||||
|
||||
newTask.setPlanned(planned);
|
||||
newTask.setDue(planned); // due date not according to service level
|
||||
ThrowingCallable call = () -> taskService.createTask(newTask);
|
||||
assertThatThrownBy(call).isInstanceOf(InvalidArgumentException.class);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_VerifyThatCreateAndPlannedAreClose() throws Exception {
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
Instant inTwoHours = now.plus(2, ChronoUnit.HOURS);
|
||||
|
||||
Task newTask = taskService.newTask("USER-1-1", "DOMAIN_A");
|
||||
Instant planned = moveForwardToWorkingDay(inTwoHours);
|
||||
newTask.setClassificationKey("T2100");
|
||||
newTask.setPrimaryObjRef(
|
||||
createObjectReference("COMPANY_A", "SYSTEM_A", "INSTANCE_A", "VNR", "1234567"));
|
||||
newTask.setOwner("user-1-1");
|
||||
newTask.setPlanned(planned);
|
||||
Task createdTask = taskService.createTask(newTask);
|
||||
|
||||
assertThat(createdTask).isNotNull();
|
||||
assertThat(createdTask.getPlanned()).isEqualTo(planned);
|
||||
assertThat(createdTask.getCreated()).isBefore(createdTask.getPlanned());
|
||||
|
||||
assertThat(createdTask.getPlanned())
|
||||
.isCloseTo(
|
||||
moveForwardToWorkingDay(createdTask.getCreated()),
|
||||
new TemporalUnitWithinOffset(2L, ChronoUnit.HOURS));
|
||||
}
|
||||
|
||||
/* UPDATE TASK */
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowException_When_DueAndPlannedAreChangedInconsistently() throws Exception {
|
||||
TaskService taskService = taskanaEngine.getTaskService();
|
||||
Task task = taskService.getTask("TKI:000000000000000000000000000000000000"); // P1D
|
||||
task.setDue(Instant.parse("2020-07-02T00:00:00Z"));
|
||||
task.setPlanned(Instant.parse("2020-07-07T00:00:00Z"));
|
||||
assertThatThrownBy(() -> taskService.updateTask(task))
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessage(
|
||||
"Cannot update a task with given planned 2020-07-07T00:00:00Z and due "
|
||||
+ "date 2020-07-02T00:00:00Z not matching the service level PT24H.");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-b-2")
|
||||
@Test
|
||||
void should_SetPlanned_When_SetPlannedRequestContainsDuplicateTaskIds() throws Exception {
|
||||
|
||||
// This test works with the following tasks (w/o attachments) and classifications
|
||||
//
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// | TaskId | ClassificationId | SL |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// |TKI:000000000000000000000000000000000058 | CLI:200000000000000000000000000000000017 | P1D |
|
||||
// |TKI:000000000000000000000000000000000059 | CLI:200000000000000000000000000000000017 | P1D |
|
||||
// |TKI:000000000000000000000000000000000060 | CLI:200000000000000000000000000000000017 | P1D |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
String tkId1 = "TKI:000000000000000000000000000000000058";
|
||||
String tkId2 = "TKI:000000000000000000000000000000000059";
|
||||
String tkId3 = "TKI:000000000000000000000000000000000058";
|
||||
String tkId4 = "TKI:000000000000000000000000000000000060";
|
||||
|
||||
List<String> taskIds = List.of(tkId1, tkId2, tkId3, tkId4);
|
||||
|
||||
Instant planned = getInstant("2020-02-11T07:00:00");
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
assertThat(results.containsErrors()).isFalse();
|
||||
Instant dueExpected = getInstant("2020-02-12T07:00:00");
|
||||
|
||||
Instant due1 = taskService.getTask(tkId1).getDue();
|
||||
assertThat(due1).isEqualTo(dueExpected);
|
||||
Instant due2 = taskService.getTask(tkId2).getDue();
|
||||
assertThat(due2).isEqualTo(dueExpected);
|
||||
Instant due3 = taskService.getTask(tkId3).getDue();
|
||||
assertThat(due3).isEqualTo(dueExpected);
|
||||
Instant due4 = taskService.getTask(tkId4).getDue();
|
||||
assertThat(due4).isEqualTo(dueExpected);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-b-2")
|
||||
@Test
|
||||
void should_SetPlanned_When_RequestContainsDuplicatesAndNotExistingTaskIds() throws Exception {
|
||||
|
||||
String tkId1 = "TKI:000000000000000000000000000000000058";
|
||||
String tkId2 = "TKI:000000000000000000000000000047110059";
|
||||
String tkId3 = "TKI:000000000000000000000000000000000059";
|
||||
String tkId4 = "TKI:000000000000000000000000000000000058";
|
||||
String tkId5 = "TKI:000000000000000000000000000000000060";
|
||||
List<String> taskIds = List.of(tkId1, tkId2, tkId3, tkId4, tkId5);
|
||||
Instant planned = getInstant("2020-04-20T07:00:00");
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
assertThat(results.containsErrors()).isTrue();
|
||||
assertThat(results.getErrorMap()).hasSize(1);
|
||||
assertThat(results.getErrorForId("TKI:000000000000000000000000000047110059"))
|
||||
.isInstanceOf(TaskNotFoundException.class);
|
||||
Instant dueExpected = getInstant("2020-04-21T07:00:00");
|
||||
Instant due1 = taskService.getTask(tkId1).getDue();
|
||||
assertThat(due1).isEqualTo(dueExpected);
|
||||
Instant due3 = taskService.getTask(tkId3).getDue();
|
||||
assertThat(due3).isEqualTo(dueExpected);
|
||||
Instant due5 = taskService.getTask(tkId5).getDue();
|
||||
assertThat(due5).isEqualTo(dueExpected);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_SetPlanned_When_RequestContainsTasksWithAttachments() throws Exception {
|
||||
|
||||
// This test works with the following tasks, attachments and classifications
|
||||
//
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// | Task / associated attachment | Classification | SL |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// |TKI:000000000000000000000000000000000000 | CLI:100000000000000000000000000000000016 | P1D |
|
||||
// |TAI:000000000000000000000000000000000000 | CLI:100000000000000000000000000000000003 | P13D |
|
||||
// |TAI:000000000000000000000000000000000009 | CLI:100000000000000000000000000000000003 | P13D |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// |TKI:000000000000000000000000000000000001 | CLI:100000000000000000000000000000000005 | P15D |
|
||||
// |TAI:000000000000000000000000000000000001 | CLI:100000000000000000000000000000000002 | P2D |
|
||||
// |TAI:000000000000000000000000000000000002 | CLI:000000000000000000000000000000000003 | P3D |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// |TKI:000000000000000000000000000000000002 | CLI:100000000000000000000000000000000016 | P1D |
|
||||
// |TAI:000000000000000000000000000000000003 | CLI:000000000000000000000000000000000004 | P4D |
|
||||
// |TAI:000000000000000000000000000000000004 | CLI:000000000000000000000000000000000005 | P5D |
|
||||
// |TAI:000000000000000000000000000000000005 | CLI:000000000000000000000000000000000006 | P5D |
|
||||
// |TAI:000000000000000000000000000000000006 | CLI:000000000000000000000000000000000007 | P6D |
|
||||
// |TAI:000000000000000000000000000000000007 | CLI:100000000000000000000000000000000008 | P1D |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
|
||||
String tkId0 = "TKI:000000000000000000000000000000000000";
|
||||
String tkId1 = "TKI:000000000000000000000000000000000001";
|
||||
String tkId2 = "TKI:000000000000000000000000000000000002";
|
||||
|
||||
// get due dates by updating the tasks individually
|
||||
Task task0 = taskService.getTask(tkId0);
|
||||
Task task1 = taskService.getTask(tkId1);
|
||||
Task task2 = taskService.getTask(tkId2);
|
||||
|
||||
Instant planned = getInstant("2020-04-21T13:00:00");
|
||||
task0.setPlanned(planned);
|
||||
task1.setPlanned(planned);
|
||||
task2.setPlanned(planned);
|
||||
|
||||
final Instant due0 = taskService.updateTask(task0).getDue();
|
||||
final Instant due1 = taskService.updateTask(task1).getDue();
|
||||
final Instant due2 = taskService.updateTask(task2).getDue();
|
||||
|
||||
// now check that bulk update gives the same due dates
|
||||
|
||||
List<String> taskIds = List.of(tkId0, tkId1, tkId2);
|
||||
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
Instant dueBulk0 = taskService.getTask(tkId0).getDue();
|
||||
Instant dueBulk1 = taskService.getTask(tkId1).getDue();
|
||||
Instant dueBulk2 = taskService.getTask(tkId2).getDue();
|
||||
|
||||
assertThat(dueBulk0).isEqualTo(planned.plus(1, ChronoUnit.DAYS));
|
||||
assertThat(dueBulk1).isEqualTo(planned.plus(2, ChronoUnit.DAYS));
|
||||
assertThat(dueBulk2).isEqualTo(planned.plus(1, ChronoUnit.DAYS));
|
||||
|
||||
assertThat(results.containsErrors()).isFalse();
|
||||
assertThat(dueBulk0).isEqualTo(due0);
|
||||
assertThat(dueBulk1).isEqualTo(due1);
|
||||
assertThat(dueBulk2).isEqualTo(due2);
|
||||
}
|
||||
|
||||
// the following tests use these tasks, attachments and classifications
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// | Task / associated attachment | Classification | SL |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// |TKI:000000000000000000000000000000000008 | CLI:100000000000000000000000000000000003 | P13D |
|
||||
// |TAI:000000000000000000000000000000000008 | CLI:000000000000000000000000000000000009 | P8D |
|
||||
// +---------------------------------------- + -----------------------------------------+ -----+
|
||||
// |TKI:000000000000000000000000000000000009 | CLI:100000000000000000000000000000000003 | P13D |
|
||||
// +---------------------------------------- + -----------------------------------------+ -----+
|
||||
// |TKI:000000000000000000000000000000000010 | CLI:100000000000000000000000000000000003 | P13D |
|
||||
// |TAI:000000000000000000000000000000000014 | CLI:100000000000000000000000000000000004,| P14D |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
|
||||
@WithAccessId(user = "user-b-2")
|
||||
@Test
|
||||
void should_ReturnBulkLog_When_UserIsNotAuthorizedForTasks() {
|
||||
String tkId1 = "TKI:000000000000000000000000000000000008";
|
||||
String tkId2 = "TKI:000000000000000000000000000000000009";
|
||||
String tkId3 = "TKI:000000000000000000000000000000000008";
|
||||
String tkId4 = "TKI:000000000000000000000000000000000010";
|
||||
List<String> taskIds = List.of(tkId1, tkId2, tkId3, tkId4);
|
||||
Instant planned = getInstant("2020-02-25T07:00:00");
|
||||
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
|
||||
assertThat(results.containsErrors()).isTrue();
|
||||
assertThat(results.getFailedIds()).hasSize(3).containsAnyElementsOf(taskIds);
|
||||
assertThat(results.getErrorMap().values())
|
||||
.hasOnlyElementsOfType(NotAuthorizedOnWorkbasketException.class);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_SetPlannedPropertyOfTasks_When_RequestedByAdminUser() throws Exception {
|
||||
String tkId1 = "TKI:000000000000000000000000000000000008";
|
||||
String tkId2 = "TKI:000000000000000000000000000000000009";
|
||||
String tkId3 = "TKI:000000000000000000000000000000000008";
|
||||
String tkId4 = "TKI:000000000000000000000000000000000010"; // all three have P13D
|
||||
|
||||
List<String> taskIds = List.of(tkId1, tkId2, tkId3, tkId4);
|
||||
Instant planned = getInstant("2020-05-03T07:00:00");
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.setPlannedPropertyOfTasks(planned, taskIds);
|
||||
assertThat(results.containsErrors()).isFalse();
|
||||
|
||||
Instant dueBulk1 = taskService.getTask(tkId1).getDue();
|
||||
Instant dueBulk2 = taskService.getTask(tkId2).getDue();
|
||||
Instant dueBulk3 = taskService.getTask(tkId3).getDue();
|
||||
Instant dueBulk4 = taskService.getTask(tkId4).getDue();
|
||||
assertThat(dueBulk1).isEqualTo(getInstant("2020-05-14T07:00:00"));
|
||||
assertThat(dueBulk2).isEqualTo(getInstant("2020-05-22T07:00:00"));
|
||||
assertThat(dueBulk3).isEqualTo(getInstant("2020-05-14T07:00:00"));
|
||||
assertThat(dueBulk4).isEqualTo(getInstant("2020-05-22T07:00:00"));
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_DoNothing_When_SetPlannedIsCalledWithEmptyTasksList() {
|
||||
Instant planned = getInstant("2020-05-03T07:00:00");
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.setPlannedPropertyOfTasks(planned, new ArrayList<>());
|
||||
assertThat(results.containsErrors()).isFalse();
|
||||
}
|
||||
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
// |TKI:000000000000000000000000000000000002 | CLI:100000000000000000000000000000000016 | P1D |
|
||||
// |TAI:000000000000000000000000000000000003 | CLI:000000000000000000000000000000000004 | P4D |
|
||||
// |TAI:000000000000000000000000000000000004 | CLI:000000000000000000000000000000000005 | P5D |
|
||||
// |TAI:000000000000000000000000000000000005 | CLI:000000000000000000000000000000000006 | P5D |
|
||||
// |TAI:000000000000000000000000000000000006 | CLI:000000000000000000000000000000000007 | P6D |
|
||||
// |TAI:000000000000000000000000000000000007 | CLI:100000000000000000000000000000000008 | P1D |
|
||||
// |TKI:000000000000000000000000000000000066 | CLI:100000000000000000000000000000000024 | P0D |
|
||||
// +-----------------------------------------+------------------------------------------+------+
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_SetPlannedPropertyWithBulkUpdate_When_RequestContainsASingleTask() throws Exception {
|
||||
String taskId = "TKI:000000000000000000000000000000000002";
|
||||
Instant planned = getInstant("2020-05-03T07:00:00");
|
||||
// test bulk operation setPlanned...
|
||||
BulkOperationResults<String, TaskanaException> results =
|
||||
taskService.setPlannedPropertyOfTasks(planned, List.of(taskId));
|
||||
Task task = taskService.getTask(taskId);
|
||||
assertThat(results.containsErrors()).isFalse();
|
||||
Instant expectedDue =
|
||||
workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1));
|
||||
assertThat(task.getDue()).isEqualTo(expectedDue);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_SetPlannedPropertyOnSingle_When_UpdateTaskWasCalled() throws Exception {
|
||||
String taskId = "TKI:000000000000000000000000000000000002";
|
||||
Task task = taskService.getTask(taskId);
|
||||
// test update of planned date via updateTask()
|
||||
task.setPlanned(task.getPlanned().plus(Duration.ofDays(3)));
|
||||
task = taskService.updateTask(task);
|
||||
Instant expectedDue =
|
||||
workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1));
|
||||
assertThat(task.getDue()).isEqualTo(expectedDue);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_SetPlanned_When_OnlyDueWasChanged() throws Exception {
|
||||
String taskId = "TKI:000000000000000000000000000000000002"; // P1D
|
||||
Instant planned = getInstant("2020-05-03T07:00:00");
|
||||
Task task = taskService.getTask(taskId);
|
||||
|
||||
// test update of due with unchanged planned
|
||||
task.setDue(planned.plus(Duration.ofDays(8))); // Monday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-05-08T07:00:00")); // Friday
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_SetDue_When_OnlyPlannedWasChanged() throws Exception {
|
||||
String taskId = "TKI:000000000000000000000000000000000002"; // P1D ServiceLevel
|
||||
Task task = taskService.getTask(taskId);
|
||||
Instant planned = getInstant("2020-05-10T07:00:00"); // Sunday
|
||||
task.setPlanned(planned);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-05-11T07:00:00")); // Monday
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-05-12T07:00:00")); // Tuesday
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_SetPlanned_When_DueIsChangedAndPlannedIsNulled() throws Exception {
|
||||
String taskId = "TKI:000000000000000000000000000000000002";
|
||||
Instant due = getInstant("2020-05-06T07:00:00");
|
||||
Task task = taskService.getTask(taskId);
|
||||
task.setDue(due);
|
||||
task.setPlanned(null);
|
||||
task = taskService.updateTask(task);
|
||||
|
||||
String serviceLevel = task.getClassificationSummary().getServiceLevel();
|
||||
Instant expPlanned =
|
||||
workingTimeCalculator.subtractWorkingTime(task.getDue(), Duration.parse(serviceLevel));
|
||||
assertThat(task.getPlanned()).isEqualTo(expPlanned);
|
||||
assertThat(task.getDue()).isEqualTo(due);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
@Test
|
||||
void should_SetDue_When_TaskUpdateIsCalled() throws Exception {
|
||||
String taskId = "TKI:000000000000000000000000000000000002";
|
||||
final Instant planned = getInstant("2020-05-03T07:00:00"); // Sunday
|
||||
Task task = taskService.getTask(taskId);
|
||||
|
||||
task.setPlanned(null);
|
||||
task = taskService.updateTask(task);
|
||||
Instant expectedDue =
|
||||
workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1));
|
||||
assertThat(task.getDue()).isEqualTo(expectedDue);
|
||||
|
||||
task.setDue(null);
|
||||
task = taskService.updateTask(task);
|
||||
expectedDue = workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1));
|
||||
assertThat(task.getDue()).isEqualTo(expectedDue);
|
||||
|
||||
task.setPlanned(planned.plus(Duration.ofDays(13))); // Saturday
|
||||
task.setDue(null);
|
||||
task = taskService.updateTask(task);
|
||||
expectedDue = workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1));
|
||||
assertThat(task.getDue()).isEqualTo(expectedDue);
|
||||
|
||||
task.setDue(planned.plus(Duration.ofDays(13))); // Saturday
|
||||
task.setPlanned(null);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-05-14T07:00:00"));
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-05-15T07:00:00"));
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-2")
|
||||
@Test
|
||||
void should_UpdateTaskPlannedOrDue_When_PlannedOrDueAreWeekendDays() throws Exception {
|
||||
Task task = taskService.getTask("TKI:000000000000000000000000000000000030"); // SL=P13D
|
||||
task.setPlanned(getInstant("2020-03-21T07:00:00")); // planned = saturday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-04-09T07:00:00"));
|
||||
|
||||
task.setDue(getInstant("2020-04-11T07:00:00")); // due = saturday
|
||||
task.setPlanned(null);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-23T07:00:00"));
|
||||
|
||||
task.setDue(getInstant("2020-04-12T07:00:00")); // due = sunday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-23T07:00:00"));
|
||||
|
||||
task.setPlanned(getInstant("2020-03-21T07:00:00")); // planned = saturday
|
||||
task.setDue(getInstant("2020-04-09T07:00:00")); // thursday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-23T07:00:00"));
|
||||
|
||||
task.setPlanned(getInstant("2020-03-03T07:00:00")); // planned on tuesday
|
||||
task.setDue(getInstant("2020-03-22T07:00:00")); // due = sunday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-03-20T07:00:00")); // friday
|
||||
|
||||
task.setPlanned(getInstant("2024-03-29T07:00:00")); // Good Friday
|
||||
task.setDue(null);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2024-04-02T07:00:00")); // Tuesday
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2024-04-19T07:00:00")); // Friday
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_UpdateTaskPlannedAndDueDate_When_PlannedDateIsNotWorkingDay() throws Exception {
|
||||
Task task = taskService.getTask("TKI:000000000000000000000000000000000201"); // SL=P2D
|
||||
assertThat(task.getClassificationSummary().getServiceLevel()).isEqualTo("P2D");
|
||||
task.setPlanned(getInstant("2024-03-29T07:00:00")); // planned = Good Friday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2024-04-02T07:00:00")); // Tuesday
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2024-04-04T07:00:00")); // Thursday
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_UpdateTaskPlannedOrDue_When_PlannedOrDueAreOnWeekends_ServiceLevel_P0D()
|
||||
throws Exception {
|
||||
Task task = taskService.getTask("TKI:000000000000000000000000000000000066"); // P0D
|
||||
|
||||
// nothing changed
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2018-01-29T15:55:00")); // Monday
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2018-01-29T15:55:00")); // Monday
|
||||
|
||||
// planned changed, due did not change
|
||||
task.setPlanned(getInstant("2020-03-21T07:00:00")); // Saturday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
|
||||
// due changed, planned did not change
|
||||
task.setDue(getInstant("2020-04-12T07:00:00")); // Sunday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned())
|
||||
.isEqualTo(getInstant("2020-04-09T07:00:00")); // Thursday (skip Good Friday)
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-04-09T07:00:00"));
|
||||
|
||||
// due changed, planned is null
|
||||
task.setDue(getInstant("2020-04-11T07:00:00")); // Saturday
|
||||
task.setPlanned(null);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned())
|
||||
.isEqualTo(getInstant("2020-04-09T07:00:00")); // Thursday (skip Good Friday)
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-04-09T07:00:00"));
|
||||
|
||||
// planned changed, due is null
|
||||
task.setPlanned(getInstant("2020-03-22T07:00:00")); // Sunday
|
||||
task.setDue(null);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
|
||||
// both changed, not null (due at weekend)
|
||||
task.setPlanned(getInstant("2020-03-20T07:00:00")); // Friday
|
||||
task.setDue(getInstant("2020-03-22T07:00:00")); // Sunday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-20T07:00:00")); // Friday
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-03-20T07:00:00")); // Friday
|
||||
|
||||
// both changed, not null (planned at weekend)
|
||||
task.setPlanned(getInstant("2020-03-22T07:00:00")); // Sunday
|
||||
task.setDue(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
|
||||
// both changed, not null (both at weekend) within SLA
|
||||
task.setPlanned(getInstant("2020-03-22T07:00:00")); // Sunday
|
||||
task.setDue(getInstant("2020-03-22T07:00:00")); // Sunday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-03-20T07:00:00")); // Friday
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-20T07:00:00")); // Friday
|
||||
|
||||
// both changed, not null (planned > due)
|
||||
task.setPlanned(getInstant("2020-03-24T07:00:00")); // Tuesday
|
||||
task.setDue(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-03-23T07:00:00")); // Monday
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_NotThrowServiceLevelViolation_IfWeekendOrHolidaysBetweenDates() throws Exception {
|
||||
Task task = taskService.getTask("TKI:000000000000000000000000000000000002"); // P1D
|
||||
|
||||
// SLA is broken but only with holidays in between
|
||||
task.setDue(getInstant("2020-04-14T07:00:00")); // Tuesday after Easter
|
||||
task.setPlanned(getInstant("2020-04-09T07:00:00")); // Thursday before Easter
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getDue()).isEqualTo(getInstant("2020-04-14T07:00:00")); // Tuesday
|
||||
assertThat(task.getPlanned()).isEqualTo(getInstant("2020-04-09T07:00:00")); // Thursday
|
||||
}
|
||||
}
|
|
@ -346,7 +346,7 @@ class QueryTasksAccTest extends AbstractAccTest {
|
|||
List<Triplet<TaskCustomField, String[], Integer>> list =
|
||||
List.of(
|
||||
Triplet.of(
|
||||
TaskCustomField.CUSTOM_1, new String[] {"custom%", "p%", "%xyz%", "efg"}, 3),
|
||||
TaskCustomField.CUSTOM_1, new String[] {"custom%", "p%", "%xyz%", "efg"}, 4),
|
||||
Triplet.of(TaskCustomField.CUSTOM_2, new String[] {"custom%", "a%"}, 2),
|
||||
Triplet.of(TaskCustomField.CUSTOM_3, new String[] {"ffg"}, 1),
|
||||
Triplet.of(TaskCustomField.CUSTOM_4, new String[] {"%ust%", "%ty"}, 2),
|
||||
|
@ -359,7 +359,7 @@ class QueryTasksAccTest extends AbstractAccTest {
|
|||
Triplet.of(TaskCustomField.CUSTOM_11, new String[] {"%ert"}, 3),
|
||||
Triplet.of(TaskCustomField.CUSTOM_12, new String[] {"dd%"}, 1),
|
||||
Triplet.of(TaskCustomField.CUSTOM_13, new String[] {"%dd_"}, 1),
|
||||
Triplet.of(TaskCustomField.CUSTOM_14, new String[] {"%"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_14, new String[] {"%"}, 100),
|
||||
Triplet.of(TaskCustomField.CUSTOM_15, new String[] {"___"}, 4),
|
||||
Triplet.of(TaskCustomField.CUSTOM_16, new String[] {"___"}, 4));
|
||||
assertThat(list).hasSameSizeAs(TaskCustomField.values());
|
||||
|
@ -391,22 +391,22 @@ class QueryTasksAccTest extends AbstractAccTest {
|
|||
// carefully constructed to always return exactly 2 results
|
||||
List<Triplet<TaskCustomField, String[], Integer>> list =
|
||||
List.of(
|
||||
Triplet.of(TaskCustomField.CUSTOM_1, new String[] {"custom1"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_1, new String[] {"custom1"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_2, new String[] {""}, 2),
|
||||
Triplet.of(TaskCustomField.CUSTOM_3, new String[] {"custom3"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_3, new String[] {"custom3"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_4, new String[] {""}, 2),
|
||||
Triplet.of(TaskCustomField.CUSTOM_5, new String[] {"ew", "al", "el"}, 92),
|
||||
Triplet.of(TaskCustomField.CUSTOM_6, new String[] {"11", "vvg"}, 95),
|
||||
Triplet.of(TaskCustomField.CUSTOM_7, new String[] {"custom7", "ijk"}, 97),
|
||||
Triplet.of(TaskCustomField.CUSTOM_8, new String[] {"not_existing"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_9, new String[] {"custom9"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_10, new String[] {"custom10"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_11, new String[] {"custom11"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_12, new String[] {"custom12"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_13, new String[] {"custom13"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_5, new String[] {"ew", "al", "el"}, 93),
|
||||
Triplet.of(TaskCustomField.CUSTOM_6, new String[] {"11", "vvg"}, 96),
|
||||
Triplet.of(TaskCustomField.CUSTOM_7, new String[] {"custom7", "ijk"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_8, new String[] {"not_existing"}, 100),
|
||||
Triplet.of(TaskCustomField.CUSTOM_9, new String[] {"custom9"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_10, new String[] {"custom10"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_11, new String[] {"custom11"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_12, new String[] {"custom12"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_13, new String[] {"custom13"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_14, new String[] {"abc"}, 0),
|
||||
Triplet.of(TaskCustomField.CUSTOM_15, new String[] {"custom15"}, 98),
|
||||
Triplet.of(TaskCustomField.CUSTOM_16, new String[] {"custom16"}, 98));
|
||||
Triplet.of(TaskCustomField.CUSTOM_15, new String[] {"custom15"}, 99),
|
||||
Triplet.of(TaskCustomField.CUSTOM_16, new String[] {"custom16"}, 99));
|
||||
assertThat(list).hasSameSizeAs(TaskCustomField.values());
|
||||
|
||||
return DynamicTest.stream(
|
||||
|
@ -455,7 +455,7 @@ class QueryTasksAccTest extends AbstractAccTest {
|
|||
throws InvalidArgumentException {
|
||||
List<TaskSummary> results =
|
||||
taskService.createTaskQuery().customAttributeIn(TaskCustomField.CUSTOM_9, "").list();
|
||||
assertThat(results).hasSize(97);
|
||||
assertThat(results).hasSize(98);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
|
@ -467,7 +467,7 @@ class QueryTasksAccTest extends AbstractAccTest {
|
|||
.createTaskQuery()
|
||||
.customAttributeIn(TaskCustomField.CUSTOM_9, "", null)
|
||||
.list();
|
||||
assertThat(results).hasSize(98);
|
||||
assertThat(results).hasSize(99);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
|
@ -479,14 +479,14 @@ class QueryTasksAccTest extends AbstractAccTest {
|
|||
.createTaskQuery()
|
||||
.customAttributeNotIn(TaskCustomField.CUSTOM_9, new String[] {null})
|
||||
.list();
|
||||
assertThat(results).hasSize(98);
|
||||
assertThat(results).hasSize(99);
|
||||
|
||||
results =
|
||||
taskService
|
||||
.createTaskQuery()
|
||||
.customAttributeNotIn(TaskCustomField.CUSTOM_9, null, "custom9")
|
||||
.list();
|
||||
assertThat(results).hasSize(97);
|
||||
assertThat(results).hasSize(98);
|
||||
|
||||
results =
|
||||
taskService
|
||||
|
@ -494,7 +494,7 @@ class QueryTasksAccTest extends AbstractAccTest {
|
|||
.customAttributeNotIn(TaskCustomField.CUSTOM_9, new String[] {null})
|
||||
.customAttributeNotIn(TaskCustomField.CUSTOM_10, "custom10")
|
||||
.list();
|
||||
assertThat(results).hasSize(97);
|
||||
assertThat(results).hasSize(98);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
|
|
|
@ -47,7 +47,7 @@ class QueryTasksByRoleAccTest extends AbstractAccTest {
|
|||
switch (taskanaEngine.getCurrentUserContext().getUserid()) {
|
||||
case "admin":
|
||||
case "taskadmin":
|
||||
expectedSize = 99;
|
||||
expectedSize = 100;
|
||||
break;
|
||||
case "businessadmin":
|
||||
case "monitor":
|
||||
|
@ -57,7 +57,7 @@ class QueryTasksByRoleAccTest extends AbstractAccTest {
|
|||
expectedSize = 26;
|
||||
break;
|
||||
case "user-1-1":
|
||||
expectedSize = 9;
|
||||
expectedSize = 10;
|
||||
break;
|
||||
case "user-taskrouter":
|
||||
expectedSize = 0;
|
||||
|
|
|
@ -92,7 +92,7 @@ class QueryTasksByTimeIntervalsAccTest extends AbstractAccTest {
|
|||
List<TaskSummary> results =
|
||||
taskService.createTaskQuery().createdWithin(interval1).orderByCreated(asc).list();
|
||||
|
||||
assertThat(results).hasSize(61);
|
||||
assertThat(results).hasSize(62);
|
||||
TaskSummary previousSummary = null;
|
||||
for (TaskSummary taskSummary : results) {
|
||||
Instant cr = taskSummary.getCreated();
|
||||
|
|
|
@ -62,7 +62,7 @@ class QueryTasksListValuesAccTest extends AbstractAccTest {
|
|||
.ownerLike("%user%")
|
||||
.orderByClassificationName(ASCENDING)
|
||||
.listValues(TaskQueryColumnName.CLASSIFICATION_NAME, null);
|
||||
assertThat(columnValueList).hasSize(5);
|
||||
assertThat(columnValueList).hasSize(6);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "admin")
|
||||
|
|
|
@ -30,9 +30,9 @@ class QueryTasksWithPaginationAccTest extends AbstractAccTest {
|
|||
void testQueryAllPaged() {
|
||||
TaskQuery taskQuery = taskanaEngine.getTaskService().createTaskQuery();
|
||||
long numberOfTasks = taskQuery.count();
|
||||
assertThat(numberOfTasks).isEqualTo(99);
|
||||
assertThat(numberOfTasks).isEqualTo(100);
|
||||
List<TaskSummary> tasks = taskQuery.orderByDue(DESCENDING).list();
|
||||
assertThat(tasks).hasSize(99);
|
||||
assertThat(tasks).hasSize(100);
|
||||
List<TaskSummary> tasksp = taskQuery.orderByDue(DESCENDING).listPage(4, 5);
|
||||
assertThat(tasksp).hasSize(5);
|
||||
tasksp = taskQuery.orderByDue(DESCENDING).listPage(5, 5);
|
||||
|
|
|
@ -0,0 +1,655 @@
|
|||
package acceptance.task.update;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import acceptance.AbstractAccTest;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import pro.taskana.TaskanaConfiguration;
|
||||
import pro.taskana.TaskanaConfiguration.Builder;
|
||||
import pro.taskana.classification.api.ClassificationService;
|
||||
import pro.taskana.classification.api.exceptions.ClassificationNotFoundException;
|
||||
import pro.taskana.classification.api.models.Classification;
|
||||
import pro.taskana.classification.api.models.ClassificationSummary;
|
||||
import pro.taskana.classification.internal.models.ClassificationSummaryImpl;
|
||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||
import pro.taskana.common.test.security.JaasExtension;
|
||||
import pro.taskana.common.test.security.WithAccessId;
|
||||
import pro.taskana.task.api.TaskService;
|
||||
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
|
||||
import pro.taskana.task.api.models.Attachment;
|
||||
import pro.taskana.task.api.models.AttachmentSummary;
|
||||
import pro.taskana.task.api.models.Task;
|
||||
import pro.taskana.task.api.models.TaskSummary;
|
||||
import pro.taskana.task.internal.models.AttachmentImpl;
|
||||
import pro.taskana.task.internal.models.TaskImpl;
|
||||
|
||||
@ExtendWith(JaasExtension.class)
|
||||
public class UpdateTaskAttachmentWithWorkingDaysCalculationAccTest extends AbstractAccTest {
|
||||
|
||||
private Task task;
|
||||
private Attachment attachment;
|
||||
private ClassificationService classificationService;
|
||||
|
||||
@BeforeEach
|
||||
@WithAccessId(user = "admin")
|
||||
void setUp() throws Exception {
|
||||
resetDb(false);
|
||||
|
||||
TaskanaConfiguration config =
|
||||
new Builder(taskanaConfiguration).useWorkingTimeCalculation(false).build();
|
||||
|
||||
initTaskanaEngine(config);
|
||||
classificationService = taskanaEngine.getClassificationService();
|
||||
task =
|
||||
taskService.getTask(
|
||||
"TKI:000000000000000000000000000000000000"); // class T2000, prio 1, SL P1D
|
||||
task.setClassificationKey("T2000");
|
||||
attachment =
|
||||
createExampleAttachment(
|
||||
"DOCTYPE_DEFAULT", // prio 99, SL P2000D
|
||||
createObjectReference(
|
||||
"COMPANY_A",
|
||||
"SYSTEM_B",
|
||||
"INSTANCE_B",
|
||||
"ArchiveId",
|
||||
"12345678901234567890123456789012345678901234567890"),
|
||||
"E-MAIL",
|
||||
Instant.parse("2018-01-15T00:00:00Z"),
|
||||
createSimpleCustomPropertyMap(3));
|
||||
task.getAttachments().clear();
|
||||
taskService.updateTask(task);
|
||||
assertThat(task).isNotNull();
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_UpdateTaskCorrectlyInDatabase_When_AddingAnAttachment() throws Exception {
|
||||
final int attachmentCount = task.getAttachments().size();
|
||||
assertThat(task.getPriority()).isEqualTo(1);
|
||||
assertThat(task.getPlanned().plus(Duration.ofDays(1))).isEqualTo(task.getDue());
|
||||
task.addAttachment(attachment);
|
||||
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
|
||||
assertThat(task.getAttachments())
|
||||
.hasSize(attachmentCount + 1)
|
||||
.contains(attachment)
|
||||
.extracting(Attachment::getModified)
|
||||
.containsExactlyInAnyOrder(task.getModified());
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_UpdateTaskReceived_When_AddingAnAttachment() throws Exception {
|
||||
task.addAttachment(attachment);
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task)
|
||||
.extracting(TaskSummary::getReceived)
|
||||
.isEqualTo(Instant.parse("2018-01-15T00:00:00Z"));
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_NotUpdateTaskReceived_When_TaskAlreadyHasAReceived() throws Exception {
|
||||
task.setReceived(Instant.parse("2019-09-13T08:44:17.588Z"));
|
||||
task.addAttachment(attachment);
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task).extracting(TaskSummary::getReceived).isNotEqualTo(attachment.getReceived());
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_UpdateTaskReceived_When_AddingTwoAttachments() throws Exception {
|
||||
task.addAttachment(attachment);
|
||||
Attachment attachment2 =
|
||||
createExampleAttachment(
|
||||
"L10303",
|
||||
createObjectReference(
|
||||
"COMPANY_B",
|
||||
"SYSTEM_C",
|
||||
"INSTANCE_C",
|
||||
"ArchiveId",
|
||||
"ABC45678901234567890123456789012345678901234567890"),
|
||||
"ROHRPOST",
|
||||
Instant.parse("2018-01-12T00:00:00Z"),
|
||||
createSimpleCustomPropertyMap(4));
|
||||
|
||||
task.addAttachment(attachment2);
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task)
|
||||
.extracting(TaskSummary::getReceived)
|
||||
.isEqualTo(Instant.parse("2018-01-12T00:00:00Z"));
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_NotAddSameAttachmentAgain_When_AddingToTaskSummary() throws Exception {
|
||||
task.getAttachments().clear();
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).isEmpty();
|
||||
|
||||
AttachmentImpl attachment = (AttachmentImpl) this.attachment;
|
||||
attachment.setId("TAI:000017");
|
||||
task.addAttachment(attachment);
|
||||
task.addAttachment(attachment);
|
||||
task = taskService.updateTask(task);
|
||||
|
||||
assertThat(task.getAttachments())
|
||||
.hasSize(1)
|
||||
.extracting(AttachmentSummary::getModified)
|
||||
.containsExactlyInAnyOrder(task.getModified());
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowAttachmentPersistenceException_When_UpdatingTaskWithTwoIdenticalAttachments()
|
||||
throws Exception {
|
||||
final int attachmentCount = 0;
|
||||
task.getAttachments().clear();
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount);
|
||||
|
||||
AttachmentImpl attachment = (AttachmentImpl) this.attachment;
|
||||
attachment.setId("TAI:000017");
|
||||
task.getAttachments().add(attachment);
|
||||
task.getAttachments().add(attachment);
|
||||
ThrowingCallable call = () -> taskService.updateTask(task);
|
||||
assertThatThrownBy(call).isInstanceOf(AttachmentPersistenceException.class);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_UpdateExistingAttachment_When_AddingSameButNotEqualAttachmentAgain()
|
||||
throws Exception {
|
||||
// Add attachment before
|
||||
task = taskService.getTask(task.getId());
|
||||
final int attachmentCount = task.getAttachments().size();
|
||||
task.addAttachment(attachment);
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount + 1);
|
||||
|
||||
// Change sth. and add same (id) again - override/update
|
||||
String newChannel = "UPDATED EXTERNAL SINCE LAST ADD";
|
||||
final int attachmentCount2 = task.getAttachments().size();
|
||||
Attachment updatedAttachment = task.getAttachments().get(0);
|
||||
updatedAttachment.setChannel(newChannel);
|
||||
Classification newClassification =
|
||||
taskanaEngine
|
||||
.getClassificationService()
|
||||
.getClassification("CLI:100000000000000000000000000000000013"); // Prio 99, P2000D
|
||||
updatedAttachment.setClassificationSummary(newClassification.asSummary());
|
||||
task.addAttachment(updatedAttachment);
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount2);
|
||||
assertThat(task.getAttachments().get(0).getChannel()).isEqualTo(newChannel);
|
||||
assertThat(task.getPriority()).isEqualTo(99);
|
||||
|
||||
Instant expDue = workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1));
|
||||
assertThat(task.getDue()).isEqualTo(expDue);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_NotUpdateExistingAttachment_When_AddingIdenticalAttachmentAgain() throws Exception {
|
||||
// Add Attachment before
|
||||
final int attachmentCount = task.getAttachments().size();
|
||||
((AttachmentImpl) attachment).setId("TAI:0001");
|
||||
task.addAttachment(attachment);
|
||||
task.addAttachment(attachment); // overwrite, same id
|
||||
task.addAttachment(attachment); // overwrite, same id
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount + 1);
|
||||
|
||||
// Add same again - ignored
|
||||
final int attachmentCount2 = task.getAttachments().size();
|
||||
Attachment redundantAttachment = task.getAttachments().get(0);
|
||||
task.addAttachment(redundantAttachment);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount2);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void testAddAttachmentAsNullValueWillBeIgnored() throws Exception {
|
||||
// Try to add a single NULL-Element
|
||||
final int attachmentCount = task.getAttachments().size();
|
||||
task.addAttachment(null);
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount);
|
||||
|
||||
// Try to set the Attachments to NULL and update it
|
||||
((TaskImpl) task).setAttachments(null);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount); // locally, not inserted
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount); // inserted values not changed
|
||||
|
||||
// Test no NullPointer on NULL-Value and removing it on current data.
|
||||
// New loading can do this, but returned value should got this "function", too.
|
||||
final int attachmentCount2 = task.getAttachments().size();
|
||||
task.getAttachments().add(null);
|
||||
task.getAttachments().add(null);
|
||||
task.getAttachments().add(null);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount2); // locally, not inserted
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount2); // inserted values not changed
|
||||
assertThat(task.getPriority()).isEqualTo(1);
|
||||
assertThat(task.getPlanned().plus(Duration.ofDays(1))).isEqualTo(task.getDue());
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void testRemoveAttachment() throws Exception {
|
||||
task.addAttachment(attachment);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPriority()).isEqualTo(99);
|
||||
assertThat(task.getPlanned().plus(Duration.ofDays(1))).isEqualTo(task.getDue());
|
||||
int attachmentCount = task.getAttachments().size();
|
||||
Attachment attachmentToRemove = task.getAttachments().get(0);
|
||||
task.removeAttachment(attachmentToRemove.getId());
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments())
|
||||
.hasSize(attachmentCount - 1); // locally, removed and not inserted
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount - 1); // inserted, values removed
|
||||
assertThat(task.getPriority()).isEqualTo(1);
|
||||
assertThat(task.getPlanned().plus(Duration.ofDays(1))).isEqualTo(task.getDue());
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void testRemoveAttachmentWithNullAndNotAddedId() throws Exception {
|
||||
task.addAttachment(attachment);
|
||||
task = taskService.updateTask(task);
|
||||
int attachmentCount = task.getAttachments().size();
|
||||
|
||||
task.removeAttachment(null);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount); // locally, nothing changed
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount); // inserted, still same
|
||||
|
||||
task.removeAttachment("INVALID ID HERE");
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount); // locally, nothing changed
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount); // inserted, still same
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void testUpdateAttachment() throws Exception {
|
||||
((TaskImpl) task).setAttachments(new ArrayList<>());
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPriority()).isEqualTo(1);
|
||||
assertThat(task.getPlanned().plus(Duration.ofDays(1))).isEqualTo(task.getDue());
|
||||
|
||||
Attachment attachment = this.attachment;
|
||||
task.addAttachment(attachment);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getPriority()).isEqualTo(99);
|
||||
assertThat(task.getPlanned().plus(Duration.ofDays(1))).isEqualTo(task.getDue());
|
||||
|
||||
final int attachmentCount = task.getAttachments().size();
|
||||
|
||||
String newChannel = attachment.getChannel() + "-X";
|
||||
task.getAttachments().get(0).setChannel(newChannel);
|
||||
Classification newClassification =
|
||||
taskanaEngine
|
||||
.getClassificationService()
|
||||
.getClassification("CLI:100000000000000000000000000000000013"); // Prio 99, P2000D
|
||||
task.getAttachments().get(0).setClassificationSummary(newClassification.asSummary());
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(attachmentCount);
|
||||
assertThat(task.getAttachments().get(0).getChannel()).isEqualTo(newChannel);
|
||||
assertThat(task.getPriority()).isEqualTo(99);
|
||||
Instant expDue = workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1));
|
||||
|
||||
assertThat(task.getDue()).isEqualTo(expDue);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void modifyExistingAttachment() throws Exception {
|
||||
// setup test
|
||||
assertThat(task.getAttachments()).isEmpty();
|
||||
task.addAttachment(attachment);
|
||||
|
||||
Attachment attachment2 =
|
||||
createExampleAttachment(
|
||||
"L10303", // prio 101, SL PT7H
|
||||
createObjectReference(
|
||||
"COMPANY_B",
|
||||
"SYSTEM_C",
|
||||
"INSTANCE_C",
|
||||
"ArchiveId",
|
||||
"ABC45678901234567890123456789012345678901234567890"),
|
||||
"ROHRPOST",
|
||||
Instant.parse("2018-01-15T00:00:00Z"),
|
||||
createSimpleCustomPropertyMap(4));
|
||||
task.addAttachment(attachment2);
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
|
||||
assertThat(task.getPriority()).isEqualTo(101);
|
||||
Instant expDue = workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(1));
|
||||
assertThat(task.getDue()).isEqualTo(expDue);
|
||||
assertThat(task.getAttachments())
|
||||
.hasSize(2)
|
||||
.areExactly(
|
||||
1,
|
||||
new Condition<>(
|
||||
e -> "E-MAIL".equals(e.getChannel()) && e.getCustomAttributeMap().size() == 3,
|
||||
"E-MAIL with 3 custom attributes"))
|
||||
.areExactly(
|
||||
1,
|
||||
new Condition<>(
|
||||
e -> "ROHRPOST".equals(e.getChannel()) && e.getCustomAttributeMap().size() == 4,
|
||||
"ROHRPOST with 4 custom attributes"));
|
||||
|
||||
ClassificationSummary newClassificationSummary =
|
||||
taskanaEngine
|
||||
.getClassificationService()
|
||||
.getClassification("CLI:100000000000000000000000000000000006") // Prio 5, SL P16D
|
||||
.asSummary();
|
||||
// modify existing attachment
|
||||
for (Attachment att : task.getAttachments()) {
|
||||
att.setClassificationSummary(newClassificationSummary);
|
||||
if (att.getCustomAttributeMap().size() == 3) {
|
||||
att.setChannel("FAX");
|
||||
}
|
||||
}
|
||||
// modify existing attachment and task classification
|
||||
task.setClassificationKey("DOCTYPE_DEFAULT"); // Prio 99, SL P2000D
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getPriority()).isEqualTo(99);
|
||||
|
||||
expDue = workingTimeCalculator.addWorkingTime(task.getPlanned(), Duration.ofDays(16));
|
||||
assertThat(task.getDue()).isEqualTo(expDue);
|
||||
assertThat(task.getAttachments())
|
||||
.hasSize(2)
|
||||
.areExactly(
|
||||
1,
|
||||
new Condition<>(
|
||||
e -> "FAX".equals(e.getChannel()) && e.getCustomAttributeMap().size() == 3,
|
||||
"FAX with 3 custom attributes"))
|
||||
.areExactly(
|
||||
1,
|
||||
new Condition<>(
|
||||
e -> "ROHRPOST".equals(e.getChannel()) && e.getCustomAttributeMap().size() == 4,
|
||||
"ROHRPOST with 4 custom attributes"));
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void replaceExistingAttachments() throws Exception {
|
||||
// setup test
|
||||
assertThat(task.getAttachments()).isEmpty();
|
||||
task.addAttachment(attachment);
|
||||
Attachment attachment2 =
|
||||
createExampleAttachment(
|
||||
"DOCTYPE_DEFAULT",
|
||||
createObjectReference(
|
||||
"COMPANY_B",
|
||||
"SYSTEM_C",
|
||||
"INSTANCE_C",
|
||||
"ArchiveId",
|
||||
"ABC45678901234567890123456789012345678901234567890"),
|
||||
"E-MAIL",
|
||||
Instant.parse("2018-01-15T00:00:00Z"),
|
||||
createSimpleCustomPropertyMap(4));
|
||||
task.addAttachment(attachment2);
|
||||
task = taskService.updateTask(task);
|
||||
task = taskService.getTask(task.getId());
|
||||
assertThat(task.getAttachments()).hasSize(2);
|
||||
assertThat(task.getAttachments().get(0).getClassificationSummary().getKey())
|
||||
.isEqualTo("DOCTYPE_DEFAULT");
|
||||
|
||||
Attachment attachment3 =
|
||||
createExampleAttachment(
|
||||
"DOCTYPE_DEFAULT",
|
||||
createObjectReference(
|
||||
"COMPANY_C",
|
||||
"SYSTEM_7",
|
||||
"INSTANCE_7",
|
||||
"ArchiveId",
|
||||
"ABC4567890123456789012345678901234567890DEF"),
|
||||
"DHL",
|
||||
Instant.parse("2018-01-15T00:00:00Z"),
|
||||
createSimpleCustomPropertyMap(4));
|
||||
|
||||
// replace existing attachments by new via addAttachment call
|
||||
task.getAttachments().clear();
|
||||
task.addAttachment(attachment3);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments()).hasSize(1);
|
||||
assertThat(task.getAttachments().get(0).getChannel()).isEqualTo("DHL");
|
||||
task.getAttachments().forEach(at -> assertThat(task.getModified()).isEqualTo(at.getModified()));
|
||||
// setup environment for 2nd version of replacement (list.add call)
|
||||
task.getAttachments().add(attachment2);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments()).hasSize(2);
|
||||
assertThat(task.getAttachments().get(1).getChannel()).isEqualTo("E-MAIL");
|
||||
// replace attachments
|
||||
task.getAttachments().clear();
|
||||
task.getAttachments().add(attachment3);
|
||||
task = taskService.updateTask(task);
|
||||
assertThat(task.getAttachments()).hasSize(1);
|
||||
assertThat(task.getAttachments().get(0).getChannel()).isEqualTo("DHL");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void testPrioDurationOfTaskFromAttachmentsAtUpdate() throws Exception {
|
||||
|
||||
TaskService taskService = taskanaEngine.getTaskService();
|
||||
Task newTask = taskService.newTask("USER-1-1", "DOMAIN_A");
|
||||
newTask.setClassificationKey("L12010"); // prio 8, SL P7D
|
||||
newTask.setPrimaryObjRef(
|
||||
createObjectReference("COMPANY_A", "SYSTEM_A", "INSTANCE_A", "VNR", "1234567"));
|
||||
|
||||
newTask.addAttachment(
|
||||
createExampleAttachment(
|
||||
"DOCTYPE_DEFAULT", // prio 99, SL P2000D
|
||||
createObjectReference(
|
||||
"COMPANY_A",
|
||||
"SYSTEM_B",
|
||||
"INSTANCE_B",
|
||||
"ArchiveId",
|
||||
"12345678901234567890123456789012345678901234567890"),
|
||||
"E-MAIL",
|
||||
Instant.parse("2018-01-15T00:00:00Z"),
|
||||
createSimpleCustomPropertyMap(3)));
|
||||
newTask.addAttachment(
|
||||
createExampleAttachment(
|
||||
"L1060", // prio 1, SL P1D
|
||||
createObjectReference(
|
||||
"COMPANY_A",
|
||||
"SYSTEM_B",
|
||||
"INSTANCE_B",
|
||||
"ArchiveId",
|
||||
"12345678901234567890123456789012345678901234567890"),
|
||||
"E-MAIL",
|
||||
Instant.parse("2018-01-15T00:00:00Z"),
|
||||
createSimpleCustomPropertyMap(3)));
|
||||
Task createdTask = taskService.createTask(newTask);
|
||||
|
||||
assertThat(createdTask.getId()).isNotNull();
|
||||
assertThat(createdTask.getCreator())
|
||||
.isEqualTo(taskanaEngine.getCurrentUserContext().getUserid());
|
||||
createdTask
|
||||
.getAttachments()
|
||||
.forEach(at -> assertThat(createdTask.getModified()).isEqualTo(at.getModified()));
|
||||
Task readTask = taskService.getTask(createdTask.getId());
|
||||
assertThat(readTask).isNotNull();
|
||||
assertThat(createdTask.getCreator())
|
||||
.isEqualTo(taskanaEngine.getCurrentUserContext().getUserid());
|
||||
assertThat(readTask.getAttachments()).isNotNull();
|
||||
assertThat(readTask.getAttachments()).hasSize(2);
|
||||
assertThat(readTask.getAttachments().get(1).getCreated()).isNotNull();
|
||||
assertThat(readTask.getAttachments().get(1).getModified()).isNotNull();
|
||||
assertThat(readTask.getAttachments().get(0).getCreated())
|
||||
.isEqualTo(readTask.getAttachments().get(1).getModified());
|
||||
assertThat(readTask.getAttachments().get(0).getObjectReference()).isNotNull();
|
||||
|
||||
assertThat(readTask.getPriority()).isEqualTo(99);
|
||||
|
||||
Instant expDue =
|
||||
workingTimeCalculator.addWorkingTime(readTask.getPlanned(), Duration.ofDays(1));
|
||||
|
||||
assertThat(readTask.getDue()).isEqualTo(expDue);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void testAddCustomAttributeToAttachment() throws Exception {
|
||||
|
||||
TaskService taskService = taskanaEngine.getTaskService();
|
||||
task =
|
||||
taskService.getTask(
|
||||
"TKI:000000000000000000000000000000000000"); // class T2000, prio 1, SL P1D
|
||||
attachment =
|
||||
createExampleAttachment(
|
||||
"DOCTYPE_DEFAULT", // prio 99, SL P2000D
|
||||
createObjectReference(
|
||||
"COMPANY_A",
|
||||
"SYSTEM_B",
|
||||
"INSTANCE_B",
|
||||
"ArchiveId",
|
||||
"12345678901234567890123456789012345678901234567890"),
|
||||
"E-MAIL",
|
||||
Instant.parse("2018-01-15T00:00:00Z"),
|
||||
null);
|
||||
attachment.getCustomAttributeMap().put("TEST_KEY", "TEST_VALUE");
|
||||
task.addAttachment(attachment);
|
||||
taskService.updateTask(task);
|
||||
Task updatedTask = taskService.getTask("TKI:000000000000000000000000000000000000");
|
||||
Attachment updatedAttachment =
|
||||
updatedTask.getAttachments().stream()
|
||||
.filter(a -> attachment.getId().equals(a.getId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
assertThat(updatedAttachment).isNotNull();
|
||||
assertThat(updatedTask.getModified()).isEqualTo(updatedAttachment.getModified());
|
||||
assertThat(updatedAttachment.getCustomAttributeMap()).containsEntry("TEST_KEY", "TEST_VALUE");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowException_When_UpdatingTaskWithNewAttachmentClassificationNull() {
|
||||
attachment.setClassificationSummary(null);
|
||||
task.addAttachment(attachment);
|
||||
|
||||
assertThatThrownBy(() -> taskService.updateTask(task))
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessage("Classification of Attachment must not be null.");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowException_When_UpdatingTaskWithChangedAttachmentClassificationNull()
|
||||
throws Exception {
|
||||
task.addAttachment(attachment);
|
||||
taskService.updateTask(task);
|
||||
attachment.setClassificationSummary(null);
|
||||
|
||||
assertThatThrownBy(() -> taskService.updateTask(task))
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessage("Classification of Attachment must not be null.");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowException_When_UpdatingTaskWithNewAttachmentObjectReferenceNull()
|
||||
throws Exception {
|
||||
task.addAttachment(attachment);
|
||||
taskService.updateTask(task);
|
||||
|
||||
task.removeAttachment(attachment.getId());
|
||||
attachment.setObjectReference(null);
|
||||
task.addAttachment(attachment);
|
||||
|
||||
assertThatThrownBy(() -> taskService.updateTask(task))
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessage("ObjectReference of Attachment must not be null.");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowException_When_UpdatingTaskWithChangedAttachmentObjectReferenceNull()
|
||||
throws Exception {
|
||||
task.addAttachment(attachment);
|
||||
taskService.updateTask(task);
|
||||
|
||||
task.removeAttachment(attachment.getId());
|
||||
attachment.setObjectReference(null);
|
||||
task.addAttachment(attachment);
|
||||
|
||||
assertThatThrownBy(() -> taskService.updateTask(task))
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessage("ObjectReference of Attachment must not be null.");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowException_When_UpdatingTaskWithMissingAttachmentClassificationKey() {
|
||||
ClassificationSummaryImpl classification = new ClassificationSummaryImpl();
|
||||
attachment.setClassificationSummary(classification);
|
||||
task.addAttachment(attachment);
|
||||
|
||||
assertThatThrownBy(() -> taskService.updateTask(task))
|
||||
.isInstanceOf(InvalidArgumentException.class)
|
||||
.hasMessageContaining("ClassificationKey of Attachment must not be empty.");
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ThrowException_When_UpdatingTaskWithNotExistingAttachmentClassification() {
|
||||
Classification classification =
|
||||
classificationService.newClassification("NOT_EXISTING", "DOMAIN_A", "");
|
||||
attachment.setClassificationSummary(classification);
|
||||
task.addAttachment(attachment);
|
||||
|
||||
assertThatThrownBy(() -> taskService.updateTask(task))
|
||||
.isInstanceOf(ClassificationNotFoundException.class);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_FetchAttachmentClassification_When_UpdatingTaskWithAttachments() throws Exception {
|
||||
ClassificationSummary classification =
|
||||
classificationService.newClassification("T2000", "DOMAIN_A", "").asSummary();
|
||||
attachment.setClassificationSummary(classification);
|
||||
task.addAttachment(attachment);
|
||||
|
||||
assertThat(classification.getServiceLevel()).isNull();
|
||||
|
||||
TaskImpl updatedTask = (TaskImpl) taskService.updateTask(task);
|
||||
classification = updatedTask.getAttachments().get(0).getClassificationSummary();
|
||||
|
||||
assertThat(classification.getId()).isNotNull();
|
||||
assertThat(classification.getDomain()).isNotNull();
|
||||
assertThat(classification.getServiceLevel()).isNotNull();
|
||||
}
|
||||
}
|
|
@ -185,6 +185,8 @@ class DeleteWorkbasketAccTest extends AbstractAccTest {
|
|||
taskService.forceCompleteTask(task.getId());
|
||||
task = (TaskImpl) taskService.getTask("TKI:200000000000000000000000000000000066");
|
||||
taskService.forceCompleteTask(task.getId());
|
||||
task = (TaskImpl) taskService.getTask("TKI:000000000000000000000000000000000201");
|
||||
taskService.forceCompleteTask(task.getId());
|
||||
|
||||
boolean canBeDeletedNow = workbasketService.deleteWorkbasket(wb.getId());
|
||||
assertThat(canBeDeletedNow).isFalse();
|
||||
|
|
Loading…
Reference in New Issue