Add getCapacityWithOvertime to ICalendar
This method is needed to distribute the load among resources taking into account the overtime. FEA: ItEr71S07FragmentationDeletionItEr70S09
This commit is contained in:
parent
219b3c1f16
commit
c24fe5a615
7 changed files with 126 additions and 22 deletions
|
|
@ -31,6 +31,7 @@ import java.util.Set;
|
|||
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.hibernate.validator.AssertTrue;
|
||||
import org.hibernate.validator.NotEmpty;
|
||||
import org.hibernate.validator.NotNull;
|
||||
|
|
@ -42,6 +43,7 @@ import org.navalplanner.business.calendars.entities.CalendarData.Days;
|
|||
import org.navalplanner.business.common.IntegrationEntity;
|
||||
import org.navalplanner.business.common.entities.EntitySequence;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.resources.entities.VirtualWorker;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
import org.navalplanner.business.workingday.IntraDayDate.PartialDay;
|
||||
|
|
@ -265,10 +267,16 @@ public class BaseCalendar extends IntegrationEntity implements ICalendar {
|
|||
}
|
||||
|
||||
public EffortDuration getCapacityOn(PartialDay date) {
|
||||
return date.limitDuration(findCapacityAt(date.getDate())
|
||||
return date.limitDuration(getCapacityWithOvertime(date.getDate())
|
||||
.getStandardEffort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capacity getCapacityWithOvertime(LocalDate day) {
|
||||
Validate.notNull(day);
|
||||
return multiplyByCalendarUnits(findCapacityAt(day));
|
||||
}
|
||||
|
||||
private Capacity findCapacityAt(LocalDate date) {
|
||||
if (!isActive(date)) {
|
||||
return Capacity.zero();
|
||||
|
|
@ -759,14 +767,22 @@ public class BaseCalendar extends IntegrationEntity implements ICalendar {
|
|||
.getStandardEffort());
|
||||
EffortDuration asDuration = amount
|
||||
.asDurationGivenWorkingDayOf(workableDuration);
|
||||
return capacity.limitDuration(asDuration);
|
||||
return multiplyByCalendarUnits(capacity).limitDuration(asDuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is intended to be overriden
|
||||
* <p>
|
||||
* Calendar units are the number of units this calendar is applied to. For
|
||||
* example a {@link VirtualWorker} composed of ten workers would multiply
|
||||
* the capacity by ten.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method is intended to be overridden
|
||||
* </p>
|
||||
*
|
||||
*/
|
||||
protected EffortDuration multiplyByCapacity(EffortDuration duration) {
|
||||
return duration;
|
||||
protected Capacity multiplyByCalendarUnits(Capacity capacity) {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -996,4 +1012,5 @@ public class BaseCalendar extends IntegrationEntity implements ICalendar {
|
|||
public Integer getLastSequenceCode() {
|
||||
return lastSequenceCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.IntraDayDate.PartialDay;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
|
|
@ -92,6 +93,16 @@ public abstract class CombinedWorkHours implements ICalendar {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capacity getCapacityWithOvertime(LocalDate day) {
|
||||
Capacity result = null;
|
||||
for (ICalendar each : calendars) {
|
||||
Capacity current = each.getCapacityWithOvertime(day);
|
||||
result = result == null ? current : updateCapacity(result, current);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AvailabilityTimeLine getAvailability() {
|
||||
AvailabilityTimeLine result = AvailabilityTimeLine.allValid();
|
||||
|
|
@ -110,6 +121,8 @@ public abstract class CombinedWorkHours implements ICalendar {
|
|||
protected abstract EffortDuration updateCapacity(EffortDuration current,
|
||||
EffortDuration each);
|
||||
|
||||
protected abstract Capacity updateCapacity(Capacity a, Capacity current);
|
||||
|
||||
@Override
|
||||
public boolean thereAreCapacityFor(AvailabilityTimeLine availability,
|
||||
ResourcesPerDay resourcesPerDay, EffortDuration durationToAllocate) {
|
||||
|
|
@ -143,6 +156,11 @@ class Min extends CombinedWorkHours {
|
|||
return accumulated.and(each);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Capacity updateCapacity(Capacity accumulated, Capacity current) {
|
||||
return Capacity.min(accumulated, current);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Max extends CombinedWorkHours {
|
||||
|
|
@ -168,4 +186,9 @@ class Max extends CombinedWorkHours {
|
|||
AvailabilityTimeLine accumulated, AvailabilityTimeLine each) {
|
||||
return accumulated.or(each);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Capacity updateCapacity(Capacity accumulated, Capacity current) {
|
||||
return Capacity.max(accumulated, current);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
package org.navalplanner.business.calendars.entities;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.IntraDayDate.PartialDay;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
|
|
@ -48,6 +49,17 @@ public interface ICalendar {
|
|||
*/
|
||||
public EffortDuration getCapacityOn(PartialDay partialDay);
|
||||
|
||||
/**
|
||||
* Calculates the capacity information for a given date. It contains
|
||||
* information about the normal effort and the extra effort, i.e., the
|
||||
* overtime effort.
|
||||
*
|
||||
* @param date
|
||||
* a not null date
|
||||
* @return the capacity for the date provided
|
||||
*/
|
||||
public Capacity getCapacityWithOvertime(LocalDate date);
|
||||
|
||||
public AvailabilityTimeLine getAvailability();
|
||||
|
||||
public boolean thereAreCapacityFor(AvailabilityTimeLine availability,
|
||||
|
|
|
|||
|
|
@ -84,18 +84,8 @@ public class ResourceCalendar extends BaseCalendar {
|
|||
}
|
||||
|
||||
@Override
|
||||
public EffortDuration getCapacityOn(PartialDay date) {
|
||||
return multiplyByCapacity(super.getCapacityOn(date));
|
||||
}
|
||||
|
||||
protected EffortDuration multiplyByCapacity(EffortDuration duration) {
|
||||
if (duration == null) {
|
||||
return EffortDuration.zero();
|
||||
}
|
||||
if (capacity == null) {
|
||||
return duration;
|
||||
}
|
||||
return duration.multiplyBy(capacity);
|
||||
protected Capacity multiplyByCalendarUnits(Capacity capacity) {
|
||||
return capacity.multiplyBy(getCapacity());
|
||||
}
|
||||
|
||||
@AssertTrue(message = "Capacity must be a positive integer number")
|
||||
|
|
|
|||
|
|
@ -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.IntraDayDate.PartialDay;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
|
|
@ -44,7 +45,8 @@ public class SameWorkHoursEveryDay implements ICalendar {
|
|||
|
||||
@Override
|
||||
public EffortDuration getCapacityOn(PartialDay partialDay) {
|
||||
return partialDay.limitDuration(EffortDuration.hours(hours));
|
||||
return partialDay.limitDuration(getCapacityWithOvertime(
|
||||
partialDay.getDate()).getStandardEffort());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -63,4 +65,10 @@ public class SameWorkHoursEveryDay implements ICalendar {
|
|||
return AvailabilityTimeLine.allValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capacity getCapacityWithOvertime(LocalDate day) {
|
||||
return Capacity.create(EffortDuration.hours(hours))
|
||||
.overAssignableWithoutLimit(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -801,6 +801,23 @@ public class BaseCalendarTest {
|
|||
ResourcesPerDay.amount(2)), equalTo(hours(16)));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getCapacityWithOvertimeMustNotBeCalledWithANullDate() {
|
||||
BaseCalendar calendar = createBasicCalendar();
|
||||
calendar.getCapacityWithOvertime(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCapacityWithOvertimeOnReturnsTheCapacityForThatDay() {
|
||||
BaseCalendar calendar = createBasicCalendar();
|
||||
Capacity capacitySet = Capacity.create(hours(8))
|
||||
.overAssignableWithoutLimit(true);
|
||||
|
||||
calendar.setCapacityAt(Days.MONDAY, capacitySet);
|
||||
assertThat(calendar.getCapacityWithOvertime(MONDAY_LOCAL_DATE),
|
||||
equalTo(capacitySet));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asDurationOnRespectsTheNotOverAssignablePropertyOfCalendarData() {
|
||||
BaseCalendar calendar = createBasicCalendar();
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ import org.navalplanner.business.calendars.entities.CalendarData.Days;
|
|||
import org.navalplanner.business.calendars.entities.Capacity;
|
||||
import org.navalplanner.business.calendars.entities.ResourceCalendar;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.IntraDayDate.PartialDay;
|
||||
import org.navalplanner.business.workingday.ResourcesPerDay;
|
||||
|
||||
/**
|
||||
* Tests for {@link ResourceCalendar}.
|
||||
|
|
@ -45,17 +47,23 @@ import org.navalplanner.business.workingday.EffortDuration;
|
|||
*/
|
||||
public class ResourceCalendarTest {
|
||||
|
||||
public static ResourceCalendar createBasicResourceCalendar() {
|
||||
private static final Capacity capacityForEveryDay = Capacity.create(
|
||||
EffortDuration.hours(8)).overAssignableWithoutLimit(true);
|
||||
|
||||
public static ResourceCalendar createBasicResourceCalendar(int capacity) {
|
||||
ResourceCalendar calendar = ResourceCalendar.create();
|
||||
calendar.setName("Test");
|
||||
for (Days each : Days.values()) {
|
||||
calendar.setCapacityAt(each,
|
||||
Capacity.create(EffortDuration.hours(8))
|
||||
.overAssignableWithoutLimit(true));
|
||||
calendar.setCapacityAt(each, capacityForEveryDay);
|
||||
}
|
||||
calendar.setCapacity(capacity);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public static ResourceCalendar createBasicResourceCalendar() {
|
||||
return createBasicResourceCalendar(1);
|
||||
}
|
||||
|
||||
private static final LocalDate PAST = (new LocalDate()).minusMonths(1);
|
||||
private static final LocalDate FUTURE = (new LocalDate()).plusMonths(1);
|
||||
|
||||
|
|
@ -77,6 +85,35 @@ public class ResourceCalendarTest {
|
|||
equalTo(EffortDuration.hours(8)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCapacityWithOverTimeIsMultipliedByTheCapacityOfTheResourceCalendar() {
|
||||
ResourceCalendar calendar = createBasicResourceCalendar(2);
|
||||
Capacity capacity = calendar.getCapacityWithOvertime(FUTURE);
|
||||
assertThat(capacity, equalTo(capacityForEveryDay.multiplyBy(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theCapacityEffortIsMultipliedByTheCapacityOfTheResourceCalendar() {
|
||||
ResourceCalendar calendar = createBasicResourceCalendar(2);
|
||||
EffortDuration duration = calendar.getCapacityOn(PartialDay
|
||||
.wholeDay(FUTURE));
|
||||
assertThat(duration, equalTo(capacityForEveryDay.getStandardEffort()
|
||||
.multiplyBy(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asDurationOnDoesntChangeWithTheCapacityOfTheResourceCalendar() {
|
||||
ResourceCalendar[] calendars = { createBasicResourceCalendar(),
|
||||
createBasicResourceCalendar(2), createBasicResourceCalendar(3) };
|
||||
for (ResourceCalendar each : calendars) {
|
||||
EffortDuration duration = each.asDurationOn(
|
||||
PartialDay.wholeDay(FUTURE),
|
||||
ResourcesPerDay.amount(1));
|
||||
assertThat(duration,
|
||||
equalTo(capacityForEveryDay.getStandardEffort()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void notAllowCreateCalendarAvailabilityInThePast() {
|
||||
ResourceCalendar calendar = createBasicResourceCalendar();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue