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:
parent
64e870bf21
commit
a219fa75a1
5 changed files with 135 additions and 27 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue