TSK-926: Intertwine planned and due Date for task creation

This commit is contained in:
Benjamin Eckstein 2019-11-14 13:01:21 +01:00 committed by Mustapha Zorgati
parent 25668e1324
commit 4e095f4580
6 changed files with 149 additions and 35 deletions

View File

@ -25,6 +25,7 @@ public interface Task {
* @return external Id
*/
String getExternalId();
/**
* Sets the external Id. It can be used to correlate the task to a task in an external system.
* The external Id is enforced to be unique. An attempt to create a task with
@ -36,7 +37,7 @@ public interface Task {
*/
void setExternalId(String externalId);
/**
/**
* Gets the UserId of the task-creator.
*
* @return creator
@ -93,6 +94,14 @@ public interface Task {
*/
Instant getDue();
/**
* Sets the time when the work on this task should be finished.
*
* @param due
* as exact {@link Instant}
*/
void setDue(Instant due);
/**
* Return the name of the current task.
*

View File

@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.LongStream;
import java.util.stream.Stream;
@ -96,6 +97,10 @@ public final class DaysToWorkingDaysConverter {
return instance;
}
public static Optional<DaysToWorkingDaysConverter> getLastCreatedInstance() {
return Optional.ofNullable(instance);
}
public static void setGermanPublicHolidaysEnabled(boolean germanPublicHolidaysEnabled) {
germanHolidaysEnabled = germanPublicHolidaysEnabled;
}
@ -179,8 +184,10 @@ public final class DaysToWorkingDaysConverter {
public long convertWorkingDaysToDays(Instant startTime, long numberOfDays) {
int days = 0;
int workingDays = 0;
while (workingDays < numberOfDays) {
workingDays += isWorkingDay(++days, startTime) ? 1 : 0;
int direction = numberOfDays > 0 ? 1 : -1;
while (workingDays < numberOfDays * direction) {
days += direction;
workingDays += isWorkingDay(days, startTime) ? 1 : 0;
}
return days;
}

View File

@ -146,6 +146,7 @@ public class TaskImpl implements Task {
return due;
}
@Override
public void setDue(Instant due) {
this.due = due;
}

View File

@ -637,18 +637,46 @@ public class TaskServiceImpl implements TaskService {
}
task.setCreator(creator);
if (task.getPlanned() == null) {
task.setPlanned(now);
}
// if no business process id is provided, a unique id is created.
if (task.getBusinessProcessId() == null) {
task.setBusinessProcessId(IdGenerator.generateWithPrefix(ID_PREFIX_BUSINESS_PROCESS));
}
// insert Classification specifications if Classification is given.
if (classification == null) {
if (task.getPlanned() == null) {
task.setPlanned(now);
}
} else {
// get duration in days from planned to due
PrioDurationHolder finalPrioDuration = getNewPrioDuration(prioDurationFromAttachments,
classification.getPriority(), classification.getServiceLevel());
Duration finalDuration = finalPrioDuration.getDuration();
if (finalDuration != null && !MAX_DURATION.equals(finalDuration)) {
// if we have a due date we need to go x days backwards,
// else we take the planned date (or now as fallback) and add x Days
if (task.getDue() != null) {
long days = converter.convertWorkingDaysToDays(task.getDue(), -finalDuration.toDays());
//days < 0 -> so we ne need to add, not substract
Instant planned = task.getDue().plus(Duration.ofDays(days));
task.setPlanned(planned);
} else {
task.setPlanned(task.getPlanned() == null ? now : task.getPlanned());
long days = converter.convertWorkingDaysToDays(task.getPlanned(), finalDuration.toDays());
Instant due = task.getPlanned().plus(Duration.ofDays(days));
task.setDue(due);
}
}
task.setPriority(finalPrioDuration.getPrio());
}
processStandardSettingsForConfiguration(task, classification, prioDurationFromAttachments);
if (task.getName() == null && classification != null) {
task.setName(classification.getName());
}
if (task.getDescription() == null && classification != null) {
task.setDescription(classification.getDescription());
}
// insert Attachments if needed
List<Attachment> attachments = task.getAttachments();
@ -665,32 +693,6 @@ public class TaskServiceImpl implements TaskService {
LOGGER.debug("exit from standardSettings()");
}
private void processStandardSettingsForConfiguration(TaskImpl task, Classification classification,
PrioDurationHolder prioDurationFromAttachments) {
LOGGER.debug("entry to processStandardSettingsForConfiguration()");
if (classification != null) {
PrioDurationHolder finalPrioDuration = getNewPrioDuration(prioDurationFromAttachments,
classification.getPriority(), classification.getServiceLevel());
Duration finalDuration = finalPrioDuration.getDuration();
if (finalDuration != null && !MAX_DURATION.equals(finalDuration)) {
long days = converter.convertWorkingDaysToDays(task.getPlanned(), finalDuration.toDays());
Instant due = task.getPlanned().plus(Duration.ofDays(days));
task.setDue(due);
}
task.setPriority(finalPrioDuration.getPrio());
}
if (task.getName() == null && classification != null) {
task.setName(classification.getName());
}
if (task.getDescription() == null && classification != null) {
task.setDescription(classification.getDescription());
}
LOGGER.debug("exit from processStandardSettingsForConfiguration()");
}
private void setCallbackStateOnTaskCreation(TaskImpl task) throws InvalidArgumentException {
Map<String, String> callbackInfo = task.getCallbackInfo();
if (callbackInfo != null && callbackInfo.containsKey(Task.CALLBACK_STATE)) {

View File

@ -14,6 +14,7 @@ import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import org.apache.ibatis.session.Configuration;
@ -24,6 +25,8 @@ import org.junit.jupiter.api.extension.ExtendWith;
import acceptance.AbstractAccTest;
import pro.taskana.Attachment;
import pro.taskana.Classification;
import pro.taskana.ClassificationService;
import pro.taskana.ObjectReference;
import pro.taskana.Task;
import pro.taskana.TaskService;
@ -332,6 +335,84 @@ class CreateTaskAccTest extends AbstractAccTest {
assertNotNull(readTask.getAttachments().get(0).getObjectReference());
}
@WithAccessId(
userName = "user_1_1",
groupNames = {"group_1"})
@Test
void testCalculationOfDueDateAtCreate()
throws NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException,
WorkbasketNotFoundException, TaskAlreadyExistException, TaskNotFoundException {
TaskService taskService = taskanaEngine.getTaskService();
ClassificationService classificationService = taskanaEngine.getClassificationService();
//SL P16D
Classification classification = classificationService.getClassification("L110105", "DOMAIN_A");
long serviceLevelDays = Duration.parse(classification.getServiceLevel()).toDays();
assertTrue(serviceLevelDays > 5);
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 = Instant.now().plus(10, ChronoUnit.DAYS);
newTask.setPlanned(planned);
Task createdTask = taskService.createTask(newTask);
assertNotNull(createdTask.getId());
Task readTask = taskService.getTask(createdTask.getId());
assertNotNull(readTask);
assertEquals(planned, readTask.getPlanned());
Optional<Instant> shouldBeDueDate = DaysToWorkingDaysConverter.getLastCreatedInstance()
.map(converter -> converter.convertWorkingDaysToDays(readTask.getPlanned(), serviceLevelDays))
.map(
calendarDays -> readTask.getPlanned().plus(Duration.ofDays(calendarDays)));
assertTrue(shouldBeDueDate.isPresent());
assertEquals(readTask.getDue(), shouldBeDueDate.get());
}
@WithAccessId(
userName = "user_1_1",
groupNames = {"group_1"})
@Test
void testCalculationOfPlannedDateAtCreate()
throws NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException,
WorkbasketNotFoundException, TaskAlreadyExistException, TaskNotFoundException {
TaskService taskService = taskanaEngine.getTaskService();
ClassificationService classificationService = taskanaEngine.getClassificationService();
//SL P16D
Classification classification = classificationService.getClassification("L110105", "DOMAIN_A");
long serviceLevelDays = Duration.parse(classification.getServiceLevel()).toDays();
assertTrue(serviceLevelDays > 5);
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 = Instant.now().plus(40, ChronoUnit.DAYS);
newTask.setDue(due);
Task createdTask = taskService.createTask(newTask);
assertNotNull(createdTask.getId());
Task readTask = taskService.getTask(createdTask.getId());
assertNotNull(readTask);
assertEquals(due, readTask.getDue());
Optional<Long> calendarDaysToSubstract = DaysToWorkingDaysConverter.getLastCreatedInstance()
.map(converter -> converter.convertWorkingDaysToDays(readTask.getPlanned(), -serviceLevelDays));
assertTrue(calendarDaysToSubstract.isPresent());
assertTrue(calendarDaysToSubstract.get() < 0);
assertTrue(calendarDaysToSubstract.get() <= -serviceLevelDays);
Instant shouldBePlannedDate = due.plus(Duration.ofDays(calendarDaysToSubstract.get()));
assertEquals(readTask.getPlanned(), shouldBePlannedDate);
}
@WithAccessId(
userName = "user_1_1",
groupNames = {"group_1"})

View File

@ -49,7 +49,21 @@ class DaysToWorkingDaysConverterTest {
Instant thursday0201 = Instant.parse("2018-02-01T07:00:00.000Z");
DaysToWorkingDaysConverter converter = DaysToWorkingDaysConverter.initialize(reportItems, thursday0201);
long days = converter.convertWorkingDaysToDays(thursday0201, 0); // = thursday
long days = converter.convertWorkingDaysToDays(thursday0201, -7); // = tuesday (sat + sun)
assertEquals(-9, days);
days = converter.convertWorkingDaysToDays(thursday0201, -6); // = wednesday (sat + sun)
assertEquals(-8, days);
days = converter.convertWorkingDaysToDays(thursday0201, -5); // = thursday (sat + sun)
assertEquals(-7, days);
days = converter.convertWorkingDaysToDays(thursday0201, -4); // = friday
assertEquals(-6, days);
days = converter.convertWorkingDaysToDays(thursday0201, -3); // monday
assertEquals(-3, days);
days = converter.convertWorkingDaysToDays(thursday0201, -2); // tuesday
assertEquals(-2, days);
days = converter.convertWorkingDaysToDays(thursday0201, -1); // wednesday
assertEquals(-1, days);
days = converter.convertWorkingDaysToDays(thursday0201, 0); // = thursday
assertEquals(0, days);
days = converter.convertWorkingDaysToDays(thursday0201, 1); // fri
assertEquals(1, days);