TSK-322 Calculate due timestamp with respect to custom holidays and weekends

This commit is contained in:
BerndBreier 2018-03-12 13:11:01 +01:00 committed by Holger Hagen
parent d4ab03667c
commit e323ea3e6e
4 changed files with 105 additions and 12 deletions

View File

@ -149,6 +149,21 @@ public final class DaysToWorkingDaysConverter {
return ageInWorkingDays; return ageInWorkingDays;
} }
public long convertWorkingDaysToDays(Instant startTime, long numberOfDays) {
int days = 0;
int workingDays = 0;
while (workingDays < numberOfDays) {
if (isWorkingDay(days, startTime)) {
workingDays++;
}
days++;
while (!isWorkingDay(days, startTime)) {
days++;
}
}
return days;
}
private ArrayList<Integer> generateNegativeDaysToWorkingDays( private ArrayList<Integer> generateNegativeDaysToWorkingDays(
List<ReportLineItemDefinition> reportLineItemDefinitions, Instant referenceDate) { List<ReportLineItemDefinition> reportLineItemDefinitions, Instant referenceDate) {
int minUpperLimit = getSmallestUpperLimit(reportLineItemDefinitions); int minUpperLimit = getSmallestUpperLimit(reportLineItemDefinitions);
@ -205,11 +220,10 @@ public final class DaysToWorkingDaysConverter {
} }
private boolean isWorkingDay(int day, Instant referenceDate) { private boolean isWorkingDay(int day, Instant referenceDate) {
if (LocalDateTime.ofInstant(referenceDate, ZoneId.systemDefault()).plusDays(day).getDayOfWeek().equals( LocalDateTime dateTime = LocalDateTime.ofInstant(referenceDate, ZoneId.systemDefault()).plusDays(day);
DayOfWeek.SATURDAY) if (dateTime.getDayOfWeek().equals(DayOfWeek.SATURDAY)
|| LocalDateTime.ofInstant(referenceDate, ZoneId.systemDefault()).plusDays(day).getDayOfWeek().equals( || dateTime.getDayOfWeek().equals(DayOfWeek.SUNDAY)
DayOfWeek.SUNDAY) || isHoliday(dateTime.toLocalDate())) {
|| isHoliday(LocalDateTime.ofInstant(referenceDate, ZoneId.systemDefault()).plusDays(day).toLocalDate())) {
return false; return false;
} }
return true; return true;

View File

@ -58,6 +58,7 @@ public class TaskServiceImpl implements TaskService {
private static final String ID_PREFIX_BUSINESS_PROCESS = "BPI"; private static final String ID_PREFIX_BUSINESS_PROCESS = "BPI";
private static final String MUST_NOT_BE_EMPTY = " must not be empty"; private static final String MUST_NOT_BE_EMPTY = " must not be empty";
private static final Duration MAX_DURATION = Duration.ofSeconds(Long.MAX_VALUE, 999_999_999); private static final Duration MAX_DURATION = Duration.ofSeconds(Long.MAX_VALUE, 999_999_999);
private DaysToWorkingDaysConverter converter;
private TaskanaEngineImpl taskanaEngine; private TaskanaEngineImpl taskanaEngine;
private WorkbasketService workbasketService; private WorkbasketService workbasketService;
private ClassificationServiceImpl classificationService; private ClassificationServiceImpl classificationService;
@ -67,6 +68,13 @@ public class TaskServiceImpl implements TaskService {
TaskServiceImpl(TaskanaEngine taskanaEngine, TaskMapper taskMapper, TaskServiceImpl(TaskanaEngine taskanaEngine, TaskMapper taskMapper,
AttachmentMapper attachmentMapper) { AttachmentMapper attachmentMapper) {
super(); super();
try {
this.converter = DaysToWorkingDaysConverter
.initialize(new ArrayList<>(Arrays.asList(new ReportLineItemDefinition(0))), Instant.now());
} catch (InvalidArgumentException e) {
LOGGER.error("could not initialize DaysToWorkingDaysConverter. Caught exception " + e);
throw new SystemException("Internal error. Cannot initialize DaysToWorkingDaysConverter");
}
this.taskanaEngine = (TaskanaEngineImpl) taskanaEngine; this.taskanaEngine = (TaskanaEngineImpl) taskanaEngine;
this.taskMapper = taskMapper; this.taskMapper = taskMapper;
this.workbasketService = taskanaEngine.getWorkbasketService(); this.workbasketService = taskanaEngine.getWorkbasketService();
@ -650,7 +658,8 @@ public class TaskServiceImpl implements TaskService {
classification.getPriority(), classification.getServiceLevel()); classification.getPriority(), classification.getServiceLevel());
Duration finalDuration = finalPrioDuration.getDuration(); Duration finalDuration = finalPrioDuration.getDuration();
if (finalDuration != null && !MAX_DURATION.equals(finalDuration)) { if (finalDuration != null && !MAX_DURATION.equals(finalDuration)) {
Instant due = task.getPlanned().plus(finalDuration); long days = converter.convertWorkingDaysToDays(task.getPlanned(), finalDuration.toDays());
Instant due = task.getPlanned().plus(Duration.ofDays(days));
task.setDue(due); task.setDue(due);
} }
task.setPriority(finalPrioDuration.getPrio()); task.setPriority(finalPrioDuration.getPrio());
@ -1123,7 +1132,9 @@ public class TaskServiceImpl implements TaskService {
if (newClassificationSummary == null) { // newClassification is null -> take prio and duration from attachments if (newClassificationSummary == null) { // newClassification is null -> take prio and duration from attachments
if (prioDurationFromAttachments.getDuration() != null) { if (prioDurationFromAttachments.getDuration() != null) {
Instant due = newTaskImpl.getPlanned().plus(prioDurationFromAttachments.getDuration()); long days = converter.convertWorkingDaysToDays(newTaskImpl.getPlanned(),
prioDurationFromAttachments.getDuration().toDays());
Instant due = newTaskImpl.getPlanned().plus(Duration.ofDays(days));
newTaskImpl.setDue(due); newTaskImpl.setDue(due);
} }
if (prioDurationFromAttachments.getPrio() > Integer.MIN_VALUE) { if (prioDurationFromAttachments.getPrio() > Integer.MIN_VALUE) {
@ -1150,7 +1161,9 @@ public class TaskServiceImpl implements TaskService {
minDuration = durationFromClassification; minDuration = durationFromClassification;
} }
Instant due = newTaskImpl.getPlanned().plus(minDuration); long days = converter.convertWorkingDaysToDays(newTaskImpl.getPlanned(), minDuration.toDays());
Instant due = newTaskImpl.getPlanned().plus(Duration.ofDays(days));
newTaskImpl.setDue(due); newTaskImpl.setDue(due);
} }

View File

@ -10,7 +10,9 @@ import static org.junit.Assert.fail;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.Duration; import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.junit.Test; import org.junit.Test;
@ -32,6 +34,8 @@ import pro.taskana.exceptions.TaskAlreadyExistException;
import pro.taskana.exceptions.TaskNotFoundException; import pro.taskana.exceptions.TaskNotFoundException;
import pro.taskana.exceptions.WorkbasketNotFoundException; import pro.taskana.exceptions.WorkbasketNotFoundException;
import pro.taskana.impl.AttachmentImpl; import pro.taskana.impl.AttachmentImpl;
import pro.taskana.impl.DaysToWorkingDaysConverter;
import pro.taskana.impl.ReportLineItemDefinition;
import pro.taskana.impl.TaskImpl; import pro.taskana.impl.TaskImpl;
import pro.taskana.security.CurrentUserContext; import pro.taskana.security.CurrentUserContext;
import pro.taskana.security.JAASRunner; import pro.taskana.security.JAASRunner;
@ -147,7 +151,7 @@ public class UpdateTaskAttachmentsAccTest extends AbstractAccTest {
assertThat(task.getAttachments().size(), equalTo(attachmentCount)); assertThat(task.getAttachments().size(), equalTo(attachmentCount));
assertThat(task.getAttachments().get(0).getChannel(), equalTo(newChannel)); assertThat(task.getAttachments().get(0).getChannel(), equalTo(newChannel));
assertTrue(task.getPriority() == 999); assertTrue(task.getPriority() == 999);
assertTrue(task.getDue().equals(task.getPlanned().plus(Duration.ofHours(5)))); assertTrue(task.getDue().equals(task.getPlanned()));
} }
@ -297,7 +301,7 @@ public class UpdateTaskAttachmentsAccTest extends AbstractAccTest {
assertThat(task.getAttachments().size(), equalTo(attachmentCount)); assertThat(task.getAttachments().size(), equalTo(attachmentCount));
assertThat(task.getAttachments().get(0).getChannel(), equalTo(newChannel)); assertThat(task.getAttachments().get(0).getChannel(), equalTo(newChannel));
assertTrue(task.getPriority() == 999); assertTrue(task.getPriority() == 999);
assertTrue(task.getDue().equals(task.getPlanned().plus(Duration.ofHours(5)))); assertTrue(task.getDue().equals(task.getPlanned()));
} }
@ -322,7 +326,7 @@ public class UpdateTaskAttachmentsAccTest extends AbstractAccTest {
task = taskService.updateTask(task); task = taskService.updateTask(task);
task = taskService.getTask(task.getId()); task = taskService.getTask(task.getId());
assertTrue(task.getPriority() == 101); assertTrue(task.getPriority() == 101);
assertTrue(task.getDue().equals(task.getPlanned().plus(Duration.ofHours(7)))); assertTrue(task.getDue().equals(task.getPlanned()));
assertThat(task.getAttachments().size(), equalTo(2)); assertThat(task.getAttachments().size(), equalTo(2));
List<Attachment> attachments = task.getAttachments(); List<Attachment> attachments = task.getAttachments();
@ -358,7 +362,12 @@ public class UpdateTaskAttachmentsAccTest extends AbstractAccTest {
task = taskService.updateTask(task); task = taskService.updateTask(task);
task = taskService.getTask(task.getId()); task = taskService.getTask(task.getId());
assertTrue(task.getPriority() == 99); assertTrue(task.getPriority() == 99);
assertTrue(task.getDue().equals(task.getPlanned().plus(Duration.ofDays(16))));
DaysToWorkingDaysConverter converter = DaysToWorkingDaysConverter
.initialize(new ArrayList<>(Arrays.asList(new ReportLineItemDefinition(0))), Instant.now());
long calendarDays = converter.convertWorkingDaysToDays(task.getDue(), 16);
assertTrue(task.getDue().equals(task.getPlanned().plus(Duration.ofDays(calendarDays))));
rohrpostFound = false; rohrpostFound = false;
boolean faxFound = false; boolean faxFound = false;

View File

@ -2,6 +2,7 @@ package pro.taskana.impl;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
@ -40,6 +41,62 @@ public class DaysToWorkingDaysConverterTest {
assertNotEquals(instance1, instance3); assertNotEquals(instance1, instance3);
} }
@Test
public void testConvertWorkingDaysToDaysForTasks() {
List<ReportLineItemDefinition> reportItems = new ArrayList<>(Arrays.asList(new ReportLineItemDefinition(0)));
try {
DaysToWorkingDaysConverter converter = DaysToWorkingDaysConverter.initialize(reportItems, Instant.now());
Instant thursday0201 = Instant.parse("2018-02-01T07:00:00.000Z");
long days = converter.convertWorkingDaysToDays(thursday0201, 0); // = thursday
assertEquals(0, days);
days = converter.convertWorkingDaysToDays(thursday0201, 1); // fri
assertEquals(1, days);
days = converter.convertWorkingDaysToDays(thursday0201, 2); // mon
assertEquals(4, days);
days = converter.convertWorkingDaysToDays(thursday0201, 3); // tues
assertEquals(5, days);
days = converter.convertWorkingDaysToDays(thursday0201, 4); // we
assertEquals(6, days);
days = converter.convertWorkingDaysToDays(thursday0201, 5); // thurs
assertEquals(7, days);
days = converter.convertWorkingDaysToDays(thursday0201, 6); // fri
assertEquals(8, days);
days = converter.convertWorkingDaysToDays(thursday0201, 7); // mon
assertEquals(11, days);
days = converter.convertWorkingDaysToDays(thursday0201, 8); // tue
assertEquals(12, days);
days = converter.convertWorkingDaysToDays(thursday0201, 9); // we
assertEquals(13, days);
days = converter.convertWorkingDaysToDays(thursday0201, 10); // thu
assertEquals(14, days);
days = converter.convertWorkingDaysToDays(thursday0201, 11); // fri
assertEquals(15, days);
Instant gruenDonnerstag2018 = Instant.parse("2018-03-29T01:00:00.000Z");
days = converter.convertWorkingDaysToDays(gruenDonnerstag2018, 0);
assertEquals(0, days);
days = converter.convertWorkingDaysToDays(gruenDonnerstag2018, 1); // Karfreitag
assertEquals(5, days); // osterdienstag
days = converter.convertWorkingDaysToDays(gruenDonnerstag2018, 2); // Karfreitag
assertEquals(6, days); // ostermittwoch
Instant freitag0427 = Instant.parse("2018-04-27T19:00:00.000Z");
days = converter.convertWorkingDaysToDays(freitag0427, 0);
assertEquals(0, days);
days = converter.convertWorkingDaysToDays(freitag0427, 1);
assertEquals(3, days); // 30.4.
days = converter.convertWorkingDaysToDays(freitag0427, 2);
assertEquals(5, days); // 2.5.
} catch (InvalidArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail("");
}
}
@Test @Test
public void testInitializeForDifferentDates() throws InvalidArgumentException { public void testInitializeForDifferentDates() throws InvalidArgumentException {
DaysToWorkingDaysConverter instance1 = DaysToWorkingDaysConverter DaysToWorkingDaysConverter instance1 = DaysToWorkingDaysConverter