ResourcesPerDay now works with EffortDurations instead of hours
FEA: ItEr60S19TimeUnitDataType
This commit is contained in:
parent
597989de06
commit
0228ce0e65
6 changed files with 91 additions and 34 deletions
|
|
@ -23,6 +23,7 @@ package org.navalplanner.business.calendars.entities;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
|
@ -37,6 +38,8 @@ import org.navalplanner.business.calendars.daos.IBaseCalendarDAO;
|
|||
import org.navalplanner.business.calendars.entities.CalendarData.Days;
|
||||
import org.navalplanner.business.common.IntegrationEntity;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.EffortDuration.Granularity;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
|
||||
/**
|
||||
|
|
@ -886,11 +889,30 @@ public class BaseCalendar extends IntegrationEntity implements IWorkHours {
|
|||
calendarAvailability.setEndDate(endDate);
|
||||
}
|
||||
|
||||
public static int roundToHours(EffortDuration effortDuration) {
|
||||
if (effortDuration.equals(EffortDuration.zero())) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(1, roundHalfUpToHours(effortDuration.decompose()));
|
||||
}
|
||||
|
||||
private static int roundHalfUpToHours(
|
||||
EnumMap<Granularity, Integer> components) {
|
||||
int seconds = components.get(Granularity.SECONDS);
|
||||
int minutes = components.get(Granularity.MINUTES)
|
||||
+ (seconds < 30 ? 0 : 1);
|
||||
int hours = components.get(Granularity.HOURS) + (minutes < 30 ? 0 : 1);
|
||||
return hours;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer toHours(LocalDate day, ResourcesPerDay resourcesPerDay) {
|
||||
final Integer workableHours = getWorkableHours(day);
|
||||
return limitOverAssignability(day, resourcesPerDay
|
||||
.asHoursGivenResourceWorkingDayOf(workableHours), workableHours);
|
||||
return limitOverAssignability(day,
|
||||
roundToHours(resourcesPerDay
|
||||
.asDurationGivenWorkingDayOf(EffortDuration
|
||||
.hours(workableHours))),
|
||||
workableHours);
|
||||
}
|
||||
|
||||
private Integer limitOverAssignability(LocalDate day,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ package org.navalplanner.business.calendars.entities;
|
|||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
|
||||
public class SameWorkHoursEveryDay implements IWorkHours {
|
||||
|
|
@ -47,7 +48,9 @@ public class SameWorkHoursEveryDay implements IWorkHours {
|
|||
|
||||
@Override
|
||||
public Integer toHours(LocalDate day, ResourcesPerDay amount) {
|
||||
return amount.asHoursGivenResourceWorkingDayOf(getCapacityAt(day));
|
||||
return BaseCalendar.roundToHours(amount
|
||||
.asDurationGivenWorkingDayOf(EffortDuration
|
||||
.hours(getCapacityAt(day))));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.math.RoundingMode;
|
|||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.navalplanner.business.common.ProportionalDistributor;
|
||||
import org.navalplanner.business.workingday.EffortDuration.Granularity;
|
||||
|
||||
public class ResourcesPerDay {
|
||||
|
||||
|
|
@ -99,15 +100,16 @@ public class ResourcesPerDay {
|
|||
return amount;
|
||||
}
|
||||
|
||||
public int asHoursGivenResourceWorkingDayOf(
|
||||
Integer resourceWorkingDayHours) {
|
||||
public EffortDuration asDurationGivenWorkingDayOf(
|
||||
EffortDuration resourceWorkingDayDuration) {
|
||||
BigDecimal multiply = getAmount().multiply(
|
||||
new BigDecimal(resourceWorkingDayHours));
|
||||
if(multiply.compareTo(BigDecimal.ZERO)>0){
|
||||
return Math.max(1, multiply.setScale(0, RoundingMode.HALF_UP)
|
||||
.intValue());
|
||||
new BigDecimal(resourceWorkingDayDuration.getSeconds()));
|
||||
if (multiply.compareTo(BigDecimal.ZERO) > 0) {
|
||||
return EffortDuration.elapsing(Math.max(1,
|
||||
multiply.setScale(0, RoundingMode.HALF_UP).intValue()),
|
||||
Granularity.SECONDS);
|
||||
} else {
|
||||
return 0;
|
||||
return EffortDuration.zero();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import org.navalplanner.business.resources.entities.Resource;
|
|||
import org.navalplanner.business.resources.entities.VirtualWorker;
|
||||
import org.navalplanner.business.resources.entities.Worker;
|
||||
import org.navalplanner.business.scenarios.entities.Scenario;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
|
||||
public class GenericResourceAllocationTest {
|
||||
|
|
@ -232,8 +233,9 @@ public class GenericResourceAllocationTest {
|
|||
@Override
|
||||
public Integer answer() throws Throwable {
|
||||
ResourcesPerDay resourcesPerDay = (ResourcesPerDay) getCurrentArguments()[1];
|
||||
return resourcesPerDay
|
||||
.asHoursGivenResourceWorkingDayOf(hoursPerDay);
|
||||
return BaseCalendar.roundToHours(resourcesPerDay
|
||||
.asDurationGivenWorkingDayOf(EffortDuration
|
||||
.hours(hoursPerDay)));
|
||||
}
|
||||
}).anyTimes();
|
||||
expect(baseCalendar.canWork(isA(LocalDate.class))).andReturn(true)
|
||||
|
|
@ -325,7 +327,8 @@ public class GenericResourceAllocationTest {
|
|||
|
||||
List<GenericDayAssignment> orderedAssignmentsFor = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker1);
|
||||
int hoursPerDay = resourcesPerDay.asHoursGivenResourceWorkingDayOf(8);
|
||||
int hoursPerDay = resourcesPerDay.asDurationGivenWorkingDayOf(
|
||||
EffortDuration.hours(8)).getHours();
|
||||
assertThat(orderedAssignmentsFor, haveHours(hoursPerDay, hoursPerDay));
|
||||
}
|
||||
|
||||
|
|
@ -347,7 +350,8 @@ public class GenericResourceAllocationTest {
|
|||
|
||||
List<GenericDayAssignment> orderedAssignmentsFor = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker1);
|
||||
int hoursPerDay = resourcesPerDay.asHoursGivenResourceWorkingDayOf(8);
|
||||
int hoursPerDay = resourcesPerDay.asDurationGivenWorkingDayOf(
|
||||
EffortDuration.hours(8)).getHours();
|
||||
assertThat(orderedAssignmentsFor, haveHours(hoursPerDay, hoursPerDay));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,12 +49,13 @@ import org.junit.Test;
|
|||
import org.navalplanner.business.calendars.entities.AvailabilityTimeLine;
|
||||
import org.navalplanner.business.calendars.entities.BaseCalendar;
|
||||
import org.navalplanner.business.calendars.entities.ResourceCalendar;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation.DetachDayAssignmentOnRemoval;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation.IOnDayAssignmentRemoval;
|
||||
import org.navalplanner.business.planner.entities.SpecificDayAssignment;
|
||||
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.Task;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation.DetachDayAssignmentOnRemoval;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation.IOnDayAssignmentRemoval;
|
||||
import org.navalplanner.business.resources.entities.Worker;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
|
||||
public class SpecificResourceAllocationTest {
|
||||
|
|
@ -96,7 +97,9 @@ public class SpecificResourceAllocationTest {
|
|||
public Integer answer() throws Throwable {
|
||||
ResourcesPerDay perDay = (ResourcesPerDay) EasyMock
|
||||
.getCurrentArguments()[1];
|
||||
return perDay.asHoursGivenResourceWorkingDayOf(hours);
|
||||
return BaseCalendar.roundToHours(perDay
|
||||
.asDurationGivenWorkingDayOf(EffortDuration
|
||||
.hours(hours)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.navalplanner.business.workingday.EffortDuration.hours;
|
||||
import static org.navalplanner.business.workingday.EffortDuration.seconds;
|
||||
import static org.navalplanner.business.workingday.EffortDuration.zero;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
|
|
@ -32,6 +35,8 @@ import org.hamcrest.BaseMatcher;
|
|||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Test;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.EffortDuration.Granularity;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay.ResourcesPerDayDistributor;
|
||||
|
||||
|
|
@ -107,17 +112,43 @@ public class ResourcesPerDayTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void canBeConvertedToHoursGivenTheWorkingDayHours() {
|
||||
public void canBeConvertedToDurationsGivenTheWorkingDayInDifferentGranularities() {
|
||||
ResourcesPerDay units = ResourcesPerDay.amount(2);
|
||||
assertThat(units.asHoursGivenResourceWorkingDayOf(8), equalTo(16));
|
||||
for (Granularity each : Granularity.values()) {
|
||||
assertThat(units.asDurationGivenWorkingDayOf(EffortDuration
|
||||
.elapsing(8, each)), equalTo(EffortDuration.elapsing(16,
|
||||
each)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ifTheAmountIsDecimalTheRoundingIsHalfUp() {
|
||||
ResourcesPerDay units = ResourcesPerDay.amount(new BigDecimal(2.4));
|
||||
assertThat(units.asHoursGivenResourceWorkingDayOf(8), equalTo(19));
|
||||
assertThat(units.asHoursGivenResourceWorkingDayOf(10), equalTo(24));
|
||||
assertThat(units.asHoursGivenResourceWorkingDayOf(2), equalTo(5));
|
||||
public void ifTheAmountIsDecimalTheSecondsAreMultiplied() {
|
||||
ResourcesPerDay resourcesPerDay = ResourcesPerDay
|
||||
.amount(new BigDecimal(2.4));
|
||||
assertThat(resourcesPerDay.asDurationGivenWorkingDayOf(hours(8)),
|
||||
equalTo(hours(19).and(12, Granularity.MINUTES)));
|
||||
assertThat(resourcesPerDay.asDurationGivenWorkingDayOf(hours(10)),
|
||||
equalTo(hours(24)));
|
||||
assertThat(resourcesPerDay.asDurationGivenWorkingDayOf(hours(2)),
|
||||
equalTo(hours(4).and(48, Granularity.MINUTES)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theSecondsAreRoundedHalfUpUnlessItIsMinusThanOneSecond() {
|
||||
ResourcesPerDay resourcesPerDay = ResourcesPerDay
|
||||
.amount(new BigDecimal(2.4));
|
||||
assertThat(resourcesPerDay.asDurationGivenWorkingDayOf(seconds(1)),
|
||||
equalTo(seconds(2)));
|
||||
assertThat(resourcesPerDay.asDurationGivenWorkingDayOf(seconds(2)),
|
||||
equalTo(seconds(5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asSecondsMustReturnOneIfResultingAmountFromMultiplicationIsGreaterThanZero() {
|
||||
ResourcesPerDay resourcesPerDay = ResourcesPerDay
|
||||
.amount(new BigDecimal(0.1));
|
||||
assertThat(resourcesPerDay.asDurationGivenWorkingDayOf(seconds(1)),
|
||||
equalTo(seconds(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -128,19 +159,11 @@ public class ResourcesPerDayTest {
|
|||
assertEquals(a, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asHoursMustReturnOneIfAmountIsGreaterThanZero() {
|
||||
ResourcesPerDay amount = ResourcesPerDay.amount(new BigDecimal(0.05));
|
||||
int hours = amount
|
||||
.asHoursGivenResourceWorkingDayOf(8);
|
||||
assertThat(hours, equalTo(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ifTheAmountIsZeroMustReturnZero() {
|
||||
ResourcesPerDay amount = ResourcesPerDay.amount(BigDecimal.ZERO);
|
||||
int hours = amount.asHoursGivenResourceWorkingDayOf(8);
|
||||
assertThat(hours, equalTo(0));
|
||||
EffortDuration result = amount.asDurationGivenWorkingDayOf(hours(8));
|
||||
assertThat(result, equalTo(zero()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue