[Bug #989] Support discounting the hours of several allocations
FEA: ItEr74S04BugFixing
This commit is contained in:
parent
e03d524613
commit
e7bf3dc4dd
9 changed files with 77 additions and 20 deletions
|
|
@ -21,6 +21,12 @@
|
|||
|
||||
package org.navalplanner.business.common;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.validator.InvalidValue;
|
||||
|
|
@ -41,6 +47,24 @@ import org.navalplanner.business.util.deepcopy.Strategy;
|
|||
*/
|
||||
public abstract class BaseEntity implements INewObject {
|
||||
|
||||
/**
|
||||
* Groups the entities by id. Entities with null id are also included.
|
||||
*
|
||||
* @param entities
|
||||
* @return entities grouped by id
|
||||
*/
|
||||
public static <T extends BaseEntity> Map<Long, Set<T>> byId(
|
||||
Collection<? extends T> entities) {
|
||||
Map<Long, Set<T>> result = new HashMap<Long, Set<T>>();
|
||||
for (T each : entities) {
|
||||
if (!result.containsKey(each.getId())) {
|
||||
result.put(each.getId(), new HashSet<T>());
|
||||
}
|
||||
result.get(each.getId()).add(each);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(BaseEntity.class);
|
||||
|
||||
@OnCopy(Strategy.IGNORE)
|
||||
|
|
|
|||
|
|
@ -20,21 +20,31 @@
|
|||
*/
|
||||
package org.navalplanner.business.planner.entities;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
|
||||
public class AssignedEffortDiscounting implements
|
||||
IAssignedEffortForResource {
|
||||
|
||||
private final Object allocation;
|
||||
private final Map<Long, Set<BaseEntity>> allocations;
|
||||
|
||||
AssignedEffortDiscounting(Object discountFrom) {
|
||||
this.allocation = discountFrom;
|
||||
public AssignedEffortDiscounting(BaseEntity allocationToDiscountFrom) {
|
||||
this(Collections.singleton(allocationToDiscountFrom));
|
||||
}
|
||||
|
||||
AssignedEffortDiscounting(Collection<? extends BaseEntity> discountFrom) {
|
||||
this.allocations = BaseEntity.byId(discountFrom);
|
||||
}
|
||||
|
||||
public EffortDuration getAssignedDurationAt(Resource resource, LocalDate day) {
|
||||
return resource.getAssignedDurationDiscounting(allocation, day);
|
||||
return resource.getAssignedDurationDiscounting(allocations, day);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -267,7 +267,26 @@ public abstract class DayAssignment extends BaseEntity {
|
|||
|
||||
protected abstract void detachFromAllocation();
|
||||
|
||||
public abstract boolean belongsTo(Object allocation);
|
||||
public final boolean belongsToSomeOf(Map<Long, Set<BaseEntity>> allocations) {
|
||||
BaseEntity parent = getParent();
|
||||
if (parent.getId() == null) {
|
||||
Set<BaseEntity> entitiesWithNullId = allocations.get(null);
|
||||
return entitiesWithNullId != null
|
||||
&& entitiesWithNullId.contains(parent);
|
||||
}
|
||||
Set<BaseEntity> set = allocations.get(parent.getId());
|
||||
return set != null;
|
||||
}
|
||||
|
||||
protected abstract BaseEntity getParent();
|
||||
|
||||
public final boolean belongsTo(BaseEntity allocation) {
|
||||
if (allocation == null) {
|
||||
return false;
|
||||
}
|
||||
return belongsToSomeOf(BaseEntity.byId(Collections
|
||||
.singleton(allocation)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>null</code> if {@link DayAssignment this} day assignment
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import static org.navalplanner.business.workingday.EffortDuration.hours;
|
|||
import org.apache.commons.lang.Validate;
|
||||
import org.hibernate.validator.NotNull;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.resources.entities.Worker;
|
||||
import org.navalplanner.business.scenarios.entities.Scenario;
|
||||
|
|
@ -165,9 +166,8 @@ public class DerivedDayAssignment extends DayAssignment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean belongsTo(Object allocation) {
|
||||
return allocation != null
|
||||
&& parentState.getAllocation().equals(allocation);
|
||||
protected BaseEntity getParent() {
|
||||
return parentState.getAllocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import java.util.Set;
|
|||
import org.apache.commons.lang.Validate;
|
||||
import org.hibernate.validator.NotNull;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.scenarios.entities.Scenario;
|
||||
import org.navalplanner.business.util.deepcopy.OnCopy;
|
||||
|
|
@ -195,9 +196,8 @@ public class GenericDayAssignment extends DayAssignment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean belongsTo(Object allocation) {
|
||||
return allocation != null
|
||||
&& getGenericResourceAllocation().equals(allocation);
|
||||
protected BaseEntity getParent() {
|
||||
return getGenericResourceAllocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import java.util.Set;
|
|||
import org.apache.commons.lang.Validate;
|
||||
import org.hibernate.validator.NotNull;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.scenarios.entities.Scenario;
|
||||
import org.navalplanner.business.util.deepcopy.OnCopy;
|
||||
|
|
@ -186,9 +187,8 @@ public class SpecificDayAssignment extends DayAssignment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean belongsTo(Object resourceAllocation) {
|
||||
return resourceAllocation != null
|
||||
&& getSpecificResourceAllocation().equals(resourceAllocation);
|
||||
protected BaseEntity getParent() {
|
||||
return getSpecificResourceAllocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import org.navalplanner.business.calendars.entities.BaseCalendar;
|
|||
import org.navalplanner.business.calendars.entities.ICalendar;
|
||||
import org.navalplanner.business.calendars.entities.ResourceCalendar;
|
||||
import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
import org.navalplanner.business.common.IntegrationEntity;
|
||||
import org.navalplanner.business.common.Registry;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
|
|
@ -845,10 +846,13 @@ public abstract class Resource extends IntegrationEntity {
|
|||
}
|
||||
|
||||
public EffortDuration getAssignedDurationDiscounting(
|
||||
Object alloationFromWhichDiscountHours, LocalDate day) {
|
||||
Map<Long, Set<BaseEntity>> allocationsFromWhichDiscountHours,
|
||||
LocalDate day) {
|
||||
EffortDuration result = zero();
|
||||
for (DayAssignment dayAssignment : getAssignmentsForDay(day)) {
|
||||
if (!dayAssignment.belongsTo(alloationFromWhichDiscountHours)) {
|
||||
|
||||
if (!dayAssignment
|
||||
.belongsToSomeOf(allocationsFromWhichDiscountHours)) {
|
||||
result = result.plus(dayAssignment.getDuration());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ public class DerivedAllocationGeneratorTest {
|
|||
private Worker workerWithAlwaysAssignedHours(int assignedHours){
|
||||
Worker result = createNiceMock(Worker.class);
|
||||
expect(
|
||||
result.getAssignedDurationDiscounting(isA(Object.class),
|
||||
result.getAssignedDurationDiscounting(isA(Map.class),
|
||||
isA(LocalDate.class))).andReturn(hours(assignedHours))
|
||||
.anyTimes();
|
||||
replay(result);
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ public class GenericResourceAllocationTest {
|
|||
public static void mockZeroLoad(Resource... resources) {
|
||||
for (Resource each : resources) {
|
||||
expect(
|
||||
each.getAssignedDurationDiscounting(isA(Object.class),
|
||||
each.getAssignedDurationDiscounting(isA(Map.class),
|
||||
isA(LocalDate.class))).andReturn(zero()).anyTimes();
|
||||
}
|
||||
}
|
||||
|
|
@ -223,7 +223,7 @@ public class GenericResourceAllocationTest {
|
|||
Worker result = createNiceMock(Worker.class);
|
||||
expect(result.getCalendar()).andReturn(resourceCalendar).anyTimes();
|
||||
expect(
|
||||
result.getAssignedDurationDiscounting(isA(Object.class),
|
||||
result.getAssignedDurationDiscounting(isA(Map.class),
|
||||
isA(LocalDate.class))).andAnswer(
|
||||
new IAnswer<EffortDuration>() {
|
||||
|
||||
|
|
@ -807,7 +807,7 @@ public class GenericResourceAllocationTest {
|
|||
EffortDuration load) {
|
||||
VirtualWorker worker = createNiceMock(VirtualWorker.class);
|
||||
expect(
|
||||
worker.getAssignedDurationDiscounting(isA(Object.class),
|
||||
worker.getAssignedDurationDiscounting(isA(Map.class),
|
||||
isA(LocalDate.class))).andReturn(load)
|
||||
.anyTimes();
|
||||
expect(worker.getCalendar()).andReturn(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue