TSK-322 Calculate due timestamp with respect to custom holidays and weekends
This commit is contained in:
parent
d4ab03667c
commit
e323ea3e6e
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue