Bug #1428: Fix bug
Provide a IAssignedEffortForResource that takes into account the allocations being done. mb:e98367a8-015e-492e-bffd-56ebbaca7720
This commit is contained in:
parent
628f192be4
commit
7afcef6525
10 changed files with 144 additions and 51 deletions
|
|
@ -19,6 +19,7 @@
|
|||
package org.libreplan.business.planner.entities;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -38,11 +39,67 @@ public class AssignedEffortForResource {
|
|||
LocalDate day);
|
||||
}
|
||||
|
||||
public static IAssignedEffortForResource discount(
|
||||
public static IAssignedEffortForResource effortDiscounting(
|
||||
Collection<? extends BaseEntity> allocations) {
|
||||
return new AssignedEffortDiscounting(allocations);
|
||||
}
|
||||
|
||||
public static IAssignedEffortForResource sum(
|
||||
final IAssignedEffortForResource... assignedEffortForResources) {
|
||||
return new IAssignedEffortForResource() {
|
||||
|
||||
@Override
|
||||
public EffortDuration getAssignedDurationAt(Resource resource,
|
||||
LocalDate day) {
|
||||
EffortDuration result = EffortDuration.zero();
|
||||
for (IAssignedEffortForResource each : assignedEffortForResources) {
|
||||
EffortDuration e = each
|
||||
.getAssignedDurationAt(resource, day);
|
||||
if (e != null) {
|
||||
result = result.plus(e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static IAssignedEffortForResource sum(
|
||||
Collection<? extends IAssignedEffortForResource> assignedEffortForResources) {
|
||||
return sum(assignedEffortForResources
|
||||
.toArray(new IAssignedEffortForResource[0]));
|
||||
}
|
||||
|
||||
public static WithTheLoadOf withTheLoadOf(
|
||||
Collection<? extends ResourceAllocation<?>> allocations) {
|
||||
return new WithTheLoadOf(allocations);
|
||||
}
|
||||
|
||||
public static class WithTheLoadOf implements IAssignedEffortForResource {
|
||||
|
||||
private final Set<? extends ResourceAllocation<?>> allocations;
|
||||
private final IAssignedEffortForResource implementation;
|
||||
|
||||
public WithTheLoadOf(
|
||||
Collection<? extends ResourceAllocation<?>> allocations) {
|
||||
this.allocations = new HashSet<ResourceAllocation<?>>(allocations);
|
||||
this.implementation = sum(this.allocations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EffortDuration getAssignedDurationAt(Resource resource,
|
||||
LocalDate day) {
|
||||
return implementation.getAssignedDurationAt(resource, day);
|
||||
}
|
||||
|
||||
public WithTheLoadOf withoutConsidering(ResourceAllocation<?> allocation) {
|
||||
Set<ResourceAllocation<?>> copy = new HashSet<ResourceAllocation<?>>(
|
||||
this.allocations);
|
||||
copy.remove(allocation);
|
||||
return new WithTheLoadOf(copy);
|
||||
}
|
||||
}
|
||||
|
||||
private static class AssignedEffortDiscounting implements
|
||||
IAssignedEffortForResource {
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public class DerivedAllocationGenerator {
|
|||
List<? extends DayAssignment> dayAssignments) {
|
||||
List<DerivedDayAssignment> result = new ArrayList<DerivedDayAssignment>();
|
||||
EffortDistributor distributor = new EffortDistributor(resourcesFound,
|
||||
AssignedEffortForResource.discount(Collections.singletonList(parent)));
|
||||
AssignedEffortForResource.effortDiscounting(Collections.singletonList(parent)));
|
||||
for (DayAssignment each : dayAssignments) {
|
||||
int durationInSeconds = alpha.multiply(
|
||||
new BigDecimal(each.getDuration().getSeconds())).intValue();
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public class GenericDayAssignment extends DayAssignment {
|
|||
@Override
|
||||
ParentState setParent(
|
||||
GenericResourceAllocation genericResourceAllocation) {
|
||||
if (parent != null) {
|
||||
if (parent != null && parent != genericResourceAllocation) {
|
||||
throw new IllegalStateException(
|
||||
"the allocation cannot be changed once it has been set");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,19 +238,18 @@ public class GenericResourceAllocation extends
|
|||
|
||||
}
|
||||
|
||||
private IAssignedEffortForResource assignedEffortCalculatorOverriden = null;
|
||||
private IAssignedEffortForResource assignedEffortForResource = null;
|
||||
|
||||
public void discountAssignedHoursForResourceFrom(
|
||||
Collection<? extends ResourceAllocation<?>> allocations) {
|
||||
assignedEffortCalculatorOverriden = AssignedEffortForResource
|
||||
.discount(allocations);
|
||||
public void customAssignedEffortForResource(
|
||||
IAssignedEffortForResource assignedEffortForResource) {
|
||||
this.assignedEffortForResource = assignedEffortForResource;
|
||||
}
|
||||
|
||||
private IAssignedEffortForResource getAssignedEffortForResource() {
|
||||
if (assignedEffortCalculatorOverriden != null) {
|
||||
return assignedEffortCalculatorOverriden;
|
||||
if (assignedEffortForResource != null) {
|
||||
return assignedEffortForResource;
|
||||
}
|
||||
return AssignedEffortForResource.discount(Collections
|
||||
return AssignedEffortForResource.effortDiscounting(Collections
|
||||
.singletonList(this));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalcula
|
|||
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.CapacityResult;
|
||||
import org.libreplan.business.common.BaseEntity;
|
||||
import org.libreplan.business.common.Registry;
|
||||
import org.libreplan.business.planner.entities.AssignedEffortForResource.IAssignedEffortForResource;
|
||||
import org.libreplan.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
|
||||
import org.libreplan.business.planner.entities.allocationalgorithms.AllocationModification;
|
||||
import org.libreplan.business.planner.entities.allocationalgorithms.AllocatorForTaskDurationAndSpecifiedResourcesPerDay;
|
||||
|
|
@ -84,7 +85,7 @@ import org.libreplan.business.workingday.ResourcesPerDay;
|
|||
* Resources are allocated to planner tasks.
|
||||
*/
|
||||
public abstract class ResourceAllocation<T extends DayAssignment> extends
|
||||
BaseEntity {
|
||||
BaseEntity implements IAssignedEffortForResource {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(ResourceAllocation.class);
|
||||
|
||||
|
|
@ -1987,6 +1988,12 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
return getAssignedDuration(assignments, start, endExclusive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EffortDuration getAssignedDurationAt(Resource resource, LocalDate day) {
|
||||
IntraDayDate start = IntraDayDate.startOfDay(day);
|
||||
return getAssignedEffort(resource, start, start.nextDayAtStart());
|
||||
}
|
||||
|
||||
private List<DayAssignment> getAssingments(final Resource resource,
|
||||
LocalDate startInclusive, LocalDate endExclusive) {
|
||||
return filter(getAssignments(startInclusive, endExclusive),
|
||||
|
|
|
|||
|
|
@ -67,12 +67,12 @@ public class SpecificDayAssignment extends DayAssignment {
|
|||
|
||||
@Override
|
||||
ParentState setParent(
|
||||
SpecificResourceAllocation genericResourceAllocation) {
|
||||
if (parent != null) {
|
||||
SpecificResourceAllocation specificResourceAllocation) {
|
||||
if (parent != null && parent != specificResourceAllocation) {
|
||||
throw new IllegalStateException(
|
||||
"the allocation cannot be changed once it has been set");
|
||||
}
|
||||
this.parent = genericResourceAllocation;
|
||||
this.parent = specificResourceAllocation;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,8 +143,13 @@ public abstract class UntilFillingHoursAllocator {
|
|||
current = nextDay(current);
|
||||
}
|
||||
}
|
||||
return adjustFinish(resourcesPerDayModification, taken,
|
||||
IntraDayDate finish = adjustFinish(resourcesPerDayModification, taken,
|
||||
biggestLastAssignment, current);
|
||||
// we have to do it now, so the other allocations take into account. At
|
||||
// the end it's done again with the right end date.
|
||||
setNewDataForAllocation(resourcesPerDayModification, resultAssignments
|
||||
.get(resourcesPerDayModification), finish);
|
||||
return finish;
|
||||
}
|
||||
|
||||
private IntraDayDate adjustFinish(
|
||||
|
|
@ -231,21 +236,21 @@ public abstract class UntilFillingHoursAllocator {
|
|||
private void setAssignmentsForEachAllocation(IntraDayDate resultDate) {
|
||||
for (Entry<ResourcesPerDayModification, List<DayAssignment>> entry : resultAssignments
|
||||
.entrySet()) {
|
||||
setNewDataForAllocation(entry, resultDate);
|
||||
setNewDataForAllocation(entry.getKey(), entry.getValue(),
|
||||
resultDate);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends DayAssignment> void setNewDataForAllocation(
|
||||
Entry<ResourcesPerDayModification, List<DayAssignment>> entry,
|
||||
ResourcesPerDayModification modification,
|
||||
List<T> value,
|
||||
IntraDayDate resultDate) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ResourceAllocation<T> allocation = (ResourceAllocation<T>) entry
|
||||
.getKey().getBeingModified();
|
||||
ResourcesPerDay resourcesPerDay = entry.getKey().getGoal();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<T> value = (List<T>) entry.getValue();
|
||||
setNewDataForAllocation(allocation, resultDate, resourcesPerDay,
|
||||
value);
|
||||
ResourceAllocation<T> allocation = (ResourceAllocation<T>) modification
|
||||
.getBeingModified();
|
||||
ResourcesPerDay resourcesPerDay = modification.getGoal();
|
||||
setNewDataForAllocation(allocation, resultDate,
|
||||
resourcesPerDay, value);
|
||||
}
|
||||
|
||||
protected Direction getDirection() {
|
||||
|
|
|
|||
|
|
@ -42,10 +42,14 @@ import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalcula
|
|||
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.ResourcesPerDayIsZero;
|
||||
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.ThereAreNoValidPeriods;
|
||||
import org.libreplan.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.ValidPeriodsDontHaveCapacity;
|
||||
import org.libreplan.business.planner.entities.AssignedEffortForResource;
|
||||
import org.libreplan.business.planner.entities.AssignedEffortForResource.IAssignedEffortForResource;
|
||||
import org.libreplan.business.planner.entities.AssignedEffortForResource.WithTheLoadOf;
|
||||
import org.libreplan.business.planner.entities.AssignmentFunction;
|
||||
import org.libreplan.business.planner.entities.AssignmentFunction.AssignmentFunctionName;
|
||||
import org.libreplan.business.planner.entities.CalculatedValue;
|
||||
import org.libreplan.business.planner.entities.DerivedAllocation;
|
||||
import org.libreplan.business.planner.entities.GenericResourceAllocation;
|
||||
import org.libreplan.business.planner.entities.ResourceAllocation;
|
||||
import org.libreplan.business.planner.entities.Task;
|
||||
import org.libreplan.business.planner.entities.Task.ModifiedAllocation;
|
||||
|
|
@ -187,10 +191,43 @@ public abstract class AllocationRow {
|
|||
List<ResourcesPerDayModification> result = new ArrayList<ResourcesPerDayModification>();
|
||||
for (AllocationRow each : rows) {
|
||||
ResourcesPerDayModification modification = each
|
||||
.toResourcesPerDayModification(task, requestedToRemove);
|
||||
.toResourcesPerDayModification(task);
|
||||
result.add(modification);
|
||||
each.setTemporal(modification.getBeingModified());
|
||||
}
|
||||
setCustomAssignedEffortForResource(rows, requestedToRemove);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void setCustomAssignedEffortForResource(
|
||||
Collection<? extends AllocationRow> rows,
|
||||
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
|
||||
|
||||
List<ResourceAllocation<?>> allocationsToDiscount = getToDiscount(rows);
|
||||
allocationsToDiscount.addAll(requestedToRemove);
|
||||
|
||||
final IAssignedEffortForResource effortForResource = AssignedEffortForResource
|
||||
.effortDiscounting(allocationsToDiscount);
|
||||
List<ResourceAllocation<?>> beingModified = AllocationRow
|
||||
.getTemporalFrom(rows);
|
||||
final WithTheLoadOf withTheLoadOf = AssignedEffortForResource
|
||||
.withTheLoadOf(beingModified);
|
||||
|
||||
for (GenericResourceAllocation each : ResourceAllocation.getOfType(GenericResourceAllocation.class, beingModified)) {
|
||||
IAssignedEffortForResource custom = AssignedEffortForResource.sum(
|
||||
withTheLoadOf.withoutConsidering(each), effortForResource);
|
||||
each.customAssignedEffortForResource(custom);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ResourceAllocation<?>> getToDiscount(
|
||||
Collection<? extends AllocationRow> rows) {
|
||||
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
|
||||
for (AllocationRow each : rows) {
|
||||
if (each.getOrigin() != null) {
|
||||
result.add(each.getOrigin());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -209,11 +246,12 @@ public abstract class AllocationRow {
|
|||
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
|
||||
List<EffortModification> result = new ArrayList<EffortModification>();
|
||||
for (AllocationRow each : currentRows) {
|
||||
EffortModification hoursModification = each.toHoursModification(
|
||||
task, requestedToRemove);
|
||||
EffortModification hoursModification = each
|
||||
.toHoursModification(task);
|
||||
result.add(hoursModification);
|
||||
each.setTemporal(hoursModification.getBeingModified());
|
||||
}
|
||||
setCustomAssignedEffortForResource(currentRows, requestedToRemove);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -242,7 +280,7 @@ public abstract class AllocationRow {
|
|||
}
|
||||
|
||||
public static List<ResourceAllocation<?>> getTemporalFrom(
|
||||
List<AllocationRow> rows) {
|
||||
Collection<? extends AllocationRow> rows) {
|
||||
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
|
||||
for (AllocationRow each : rows) {
|
||||
if (each.temporal != null) {
|
||||
|
|
@ -379,11 +417,9 @@ public abstract class AllocationRow {
|
|||
}
|
||||
|
||||
public abstract ResourcesPerDayModification toResourcesPerDayModification(
|
||||
Task task,
|
||||
Collection<? extends ResourceAllocation<?>> requestedToRemove);
|
||||
Task task);
|
||||
|
||||
public abstract EffortModification toHoursModification(Task task,
|
||||
Collection<? extends ResourceAllocation<?>> requestedToRemove);
|
||||
public abstract EffortModification toHoursModification(Task task);
|
||||
|
||||
public boolean isCreating() {
|
||||
return origin == null;
|
||||
|
|
|
|||
|
|
@ -124,35 +124,26 @@ public class GenericAllocationRow extends AllocationRow {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourcesPerDayModification toResourcesPerDayModification(Task task,
|
||||
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
|
||||
GenericResourceAllocation newGeneric = createGenericAllocation(task,
|
||||
requestedToRemove);
|
||||
public ResourcesPerDayModification toResourcesPerDayModification(Task task) {
|
||||
GenericResourceAllocation newGeneric = createGenericAllocation(task);
|
||||
return ResourcesPerDayModification
|
||||
.create(newGeneric, getResourcesPerDayEditedValue(), this.resources);
|
||||
}
|
||||
|
||||
private GenericResourceAllocation createGenericAllocation(Task task,
|
||||
Collection<? extends ResourceAllocation<?>> allocationsRemoved) {
|
||||
private GenericResourceAllocation createGenericAllocation(Task task) {
|
||||
GenericResourceAllocation result = GenericResourceAllocation.create(
|
||||
task, resourceType, criterions);
|
||||
GenericResourceAllocation origin = (GenericResourceAllocation) getOrigin();
|
||||
Set<ResourceAllocation<?>> discountFrom = new HashSet<ResourceAllocation<?>>(
|
||||
allocationsRemoved);
|
||||
if (origin != null) {
|
||||
result.overrideConsolidatedDayAssignments(origin);
|
||||
discountFrom.add(origin);
|
||||
result.setAssignmentFunctionWithoutApply(origin.getAssignmentFunction());
|
||||
}
|
||||
result.discountAssignedHoursForResourceFrom(discountFrom);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EffortModification toHoursModification(Task task,
|
||||
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
|
||||
return EffortModification.create(
|
||||
createGenericAllocation(task, requestedToRemove),
|
||||
public EffortModification toHoursModification(Task task) {
|
||||
return EffortModification.create(createGenericAllocation(task),
|
||||
getEffortFromInput(), resources);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,8 +116,7 @@ public class SpecificAllocationRow extends AllocationRow {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourcesPerDayModification toResourcesPerDayModification(Task task,
|
||||
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
|
||||
public ResourcesPerDayModification toResourcesPerDayModification(Task task) {
|
||||
return ResourcesPerDayModification.create(createSpecific(task),
|
||||
getResourcesPerDayEditedValue());
|
||||
}
|
||||
|
|
@ -135,8 +134,7 @@ public class SpecificAllocationRow extends AllocationRow {
|
|||
}
|
||||
|
||||
@Override
|
||||
public EffortModification toHoursModification(Task task,
|
||||
Collection<? extends ResourceAllocation<?>> requestedToRemove) {
|
||||
public EffortModification toHoursModification(Task task) {
|
||||
return EffortModification.create(createSpecific(task),
|
||||
getEffortFromInput());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue