Not allow to allocate on intervals beyond a task's bounds

Inside the task's bounds the allocations can grow until reaching
task's bounds but they can't shrink, i.e. the allocating zero hours
the last day would keep the same end date.

FEA: ItEr69S08AdvanceAllocationFix
This commit is contained in:
Óscar González Fernández 2011-01-24 22:53:49 +01:00
parent 64e870bf21
commit a219fa75a1
5 changed files with 135 additions and 27 deletions

View file

@ -718,16 +718,11 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
private void allocate(LocalDate startInclusive, LocalDate endExclusive,
EffortDuration durationToAssign) {
IntraDayDate firstDayNotConsolidated = getTask()
.getFirstDayNotConsolidated();
IntraDayDate start = IntraDayDate.max(
IntraDayDate.startOfDay(startInclusive),
firstDayNotConsolidated);
List<T> assignmentsCreated = createAssignments(
IntraDayDate.startOfDay(startInclusive),
IntraDayDate.startOfDay(endExclusive), durationToAssign);
resetAssigmentsForInterval(start.getDate(), endExclusive,
assignmentsCreated);
IntervalInsideTask interval = new IntervalInsideTask(
startInclusive, endExclusive);
List<T> assignmentsCreated = createAssignments(interval.getStart(),
interval.getEnd(), durationToAssign);
resetAssigmentsForInterval(interval, assignmentsCreated);
}
protected abstract AvailabilityTimeLine getResourcesAvailability();
@ -855,20 +850,59 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
getDayAssignmentsState().setIntraDayEnd(intraDayEnd);
}
protected void resetAssigmentsForInterval(LocalDate startInclusive,
LocalDate endExclusive, List<T> assignmentsCreated) {
LocalDate realEndExclusive = getEndDateGiven(assignmentsCreated);
boolean endMovedAfterCurrentEnd = realEndExclusive != null
&& getEndDate() != null
&& getEndDate().compareTo(realEndExclusive) < 0;
removingAssignments(withoutConsolidated(getAssignments(startInclusive,
endExclusive)));
class IntervalInsideTask {
private final IntraDayDate start;
private final IntraDayDate end;
public IntervalInsideTask(LocalDate startInclusive,
LocalDate endExclusive) {
this.start = IntraDayDate.max(IntraDayDate
.startOfDay(startInclusive), getTask()
.getFirstDayNotConsolidated());
this.end = IntraDayDate.min(task.getIntraDayEndDate(),
IntraDayDate.startOfDay(endExclusive));
}
public IntraDayDate getStart() {
return this.start;
}
public IntraDayDate getEnd() {
return this.end;
}
public List<DayAssignment> getAssignmentsOnInterval() {
return getAssignments(this.start.getDate(),
this.end.asExclusiveEnd());
}
}
protected void resetAssigmentsForInterval(IntervalInsideTask interval,
List<T> assignmentsCreated) {
IntraDayDate originalStart = getIntraDayStartDate();
IntraDayDate originalEnd = getIntraDayEndDate();
removingAssignments(withoutConsolidated(interval
.getAssignmentsOnInterval()));
addingAssignments(assignmentsCreated);
updateOriginalTotalAssigment();
if (endMovedAfterCurrentEnd) {
getDayAssignmentsState().setIntraDayEnd(null);
}
updateResourcesPerDay();
// The resource allocation cannot grow beyond the start of the task.
// This
// is guaranteed by IntervalInsideTask. It also cannot shrink from the
// original size, this is guaranteed by originalStart
getDayAssignmentsState().setIntraDayStart(
IntraDayDate.min(originalStart, interval.getStart()));
// The resource allocation cannot grow beyond the end of the task. This
// is guaranteed by IntervalInsideTask. It also cannot shrink from the
// original size, this is guaranteed by originalEnd
getDayAssignmentsState().setIntraDayEnd(
IntraDayDate.max(originalEnd, interval.getEnd()));
}
private static <T extends DayAssignment> List<T> withoutConsolidated(
@ -1498,7 +1532,7 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
LocalDate l = getEndDateGiven(getAssignments());
if (l == null) {
return null;
return task.getIntraDayEndDate();
}
return IntraDayDate.startOfDay(l);
}

View file

@ -305,12 +305,14 @@ public class SpecificResourceAllocation extends
public void allocateKeepingProportions(LocalDate start,
LocalDate endExclusive, int newHoursForInterval) {
List<DayAssignment> assignments = getAssignments(start, endExclusive);
IntervalInsideTask interval = new IntervalInsideTask(start,
endExclusive);
List<DayAssignment> assignments = interval.getAssignmentsOnInterval();
ProportionalDistributor distributor = ProportionalDistributor
.create(asHours(assignments));
int[] newHoursPerDay = distributor.distribute(newHoursForInterval);
resetAssigmentsForInterval(start, endExclusive, assignmentsForNewHours(
assignments, newHoursPerDay));
resetAssigmentsForInterval(interval,
assignmentsForNewHours(assignments, newHoursPerDay));
}
private List<SpecificDayAssignment> assignmentsForNewHours(

View file

@ -66,19 +66,20 @@ import org.navalplanner.business.planner.daos.ITaskElementDAO;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
import org.navalplanner.business.planner.daos.TaskElementDAO;
import org.navalplanner.business.planner.entities.Dependency;
import org.navalplanner.business.planner.entities.Dependency.Type;
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
import org.navalplanner.business.planner.entities.SubcontractedTaskData;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.planner.entities.TaskElement;
import org.navalplanner.business.planner.entities.TaskGroup;
import org.navalplanner.business.planner.entities.TaskMilestone;
import org.navalplanner.business.planner.entities.Dependency.Type;
import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.business.scenarios.IScenarioManager;
import org.navalplanner.business.scenarios.bootstrap.IScenariosBootstrap;
import org.navalplanner.business.scenarios.entities.OrderVersion;
import org.navalplanner.business.test.externalcompanies.daos.ExternalCompanyDAOTest;
import org.navalplanner.business.workingday.IntraDayDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration;
@ -551,7 +552,9 @@ public class TaskElementDAOTest {
SpecificResourceAllocation allocation =
SpecificResourceAllocation.create(task);
allocation.setResource(createValidWorker());
LocalDate start = new LocalDate(2000, 2, 4);
LocalDate start = task.getStartAsLocalDate();
task.setIntraDayEndDate(IntraDayDate.startOfDay(start
.plusDays(2)));
allocation.onInterval(start, start.plusDays(2)).allocateHours(16);
assertTrue(allocation.getAssignedHours() > 0);

View file

@ -317,6 +317,74 @@ public class SpecificResourceAllocationTest {
assertThat(specificResourceAllocation.getAssignments(), haveHours(5, 5));
}
@Test
public void thePartOfTheIntervalUsedIsTheOneOverlapping() {
LocalDate start = new LocalDate(2000, 2, 4);
givenSpecificResourceAllocation(start, 4);
specificResourceAllocation.onInterval(start.plusDays(1),
start.plusDays(6)).allocateHours(12);
assertThat(specificResourceAllocation.getAssignments(),
haveHours(4, 4, 4));
}
@Test
public void thePartOfTheIntervalUsedIsTheOneOverlappingWithTheTask() {
LocalDate start = new LocalDate(2000, 2, 4);
givenSpecificResourceAllocation(start, 4);
specificResourceAllocation.fromStartUntil(start.plusDays(2))
.allocateHours(16);
specificResourceAllocation.onInterval(start, start.plusDays(6))
.allocateHours(12);
assertThat(specificResourceAllocation.getAssignments(),
haveHours(3, 3, 3, 3));
}
@Test
public void theEndIsNotChangedIfAZeroAllocationIsDoneInTheLastDay() {
LocalDate start = new LocalDate(2000, 2, 4);
givenSpecificResourceAllocation(start, 4);
LocalDate end = start.plusDays(4);
specificResourceAllocation.fromStartUntil(end).allocateHours(32);
specificResourceAllocation.onInterval(start.plusDays(3), end)
.allocateHours(0);
assertThat(specificResourceAllocation.getIntraDayEndDate(),
equalTo(IntraDayDate.startOfDay(end)));
}
@Test
public void theEndCanGrowUntilReachingTheEndOfTheTask() {
LocalDate start = new LocalDate(2000, 2, 4);
givenSpecificResourceAllocation(start, 4);
LocalDate end = start.plusDays(4);
specificResourceAllocation.fromStartUntil(end.minusDays(1))
.allocateHours(24);
assertThat(specificResourceAllocation.getIntraDayEndDate(),
equalTo(IntraDayDate.startOfDay(end.minusDays(1))));
specificResourceAllocation.onInterval(start, end).allocateHours(32);
assertThat(specificResourceAllocation.getAssignments(),
haveHours(8, 8, 8, 8));
assertThat(specificResourceAllocation.getIntraDayEndDate(),
equalTo(IntraDayDate.startOfDay(end)));
}
@Test
public void theStartIsNotChangedIfAZeroAllocationIsDoneInTheFirstDay() {
LocalDate start = new LocalDate(2000, 2, 4);
givenSpecificResourceAllocation(start, 4);
specificResourceAllocation.fromStartUntil(start.plusDays(4))
.allocateHours(32);
specificResourceAllocation.onInterval(start, start.plusDays(1))
.allocateHours(0);
assertThat(specificResourceAllocation.getIntraDayStartDate(),
equalTo(IntraDayDate.startOfDay(start)));
}
@Test
public void canAssignFromStartUntilEnd() {
LocalDate start = new LocalDate(2000, 2, 4);

View file

@ -280,6 +280,7 @@ public class UntilFillingHoursAllocatorTest {
@Test
public void theResourcesPerDayAreKeptCorrectlyCalculatedAfterUpdatingTheEndInterval() {
givenTaskOfDaysLength(10);
final ResourcesPerDay oneResourcePerDay = ResourcesPerDay.amount(1);
givenSpecificAllocations(oneResourcePerDay);
ResourceAllocation.allocating(allocations).untilAllocating(30);