diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/AllocationModification.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/AllocationModification.java index 50897e281..f79dbaec3 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/AllocationModification.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/AllocationModification.java @@ -43,6 +43,8 @@ public abstract class AllocationModification { return result; } + public abstract boolean satisfiesModificationRequested(); + /** * It ensures that the provided allocations have at least one associated * resource. A {@link AllocationModification} doesn't have associated @@ -77,6 +79,24 @@ public abstract class AllocationModification { return resourcesOnWhichApplyAllocation.isEmpty(); } + public interface IByType { + + public T onResourcesPerDay(ResourcesPerDayModification modification); + + public T onHours(HoursModification modification); + + } + + public T byType(IByType visitor) { + if (this instanceof ResourcesPerDayModification) { + ResourcesPerDayModification r = (ResourcesPerDayModification) this; + return visitor.onResourcesPerDay(r); + } else { + HoursModification h = (HoursModification) this; + return visitor.onHours(h); + } + } + protected void withNewResources(IResourcesSearcher resourcesSearcher) { resourcesOnWhichApplyAllocation = beingModified .querySuitableResources(resourcesSearcher); diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/HoursModification.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/HoursModification.java index 306104fb3..aadc13c11 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/HoursModification.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/HoursModification.java @@ -135,6 +135,11 @@ public abstract class HoursModification extends AllocationModification { public abstract void allocateFromEndUntil(LocalDate start); + @Override + public boolean satisfiesModificationRequested() { + return hours == getBeingModified().getAssignedHours(); + } + public int getHours() { return hours; } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/ResourcesPerDayModification.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/ResourcesPerDayModification.java index 416f9124d..77c799873 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/ResourcesPerDayModification.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/allocationalgorithms/ResourcesPerDayModification.java @@ -307,4 +307,9 @@ public abstract class ResourcesPerDayModification extends goal); } + @Override + public boolean satisfiesModificationRequested() { + return getGoal().equals(getBeingModified().getResourcesPerDay()); + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRow.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRow.java index 326fab2b9..12617ba31 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRow.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRow.java @@ -27,6 +27,7 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.List; import org.apache.commons.lang.Validate; @@ -45,6 +46,8 @@ import org.navalplanner.business.planner.entities.DerivedAllocation; import org.navalplanner.business.planner.entities.ResourceAllocation; import org.navalplanner.business.planner.entities.Task; import org.navalplanner.business.planner.entities.Task.ModifiedAllocation; +import org.navalplanner.business.planner.entities.allocationalgorithms.AllocationModification; +import org.navalplanner.business.planner.entities.allocationalgorithms.AllocationModification.IByType; import org.navalplanner.business.planner.entities.allocationalgorithms.HoursModification; import org.navalplanner.business.planner.entities.allocationalgorithms.ResourcesPerDayModification; import org.navalplanner.business.resources.daos.IResourcesSearcher; @@ -54,10 +57,12 @@ import org.navalplanner.business.workingday.EffortDuration; import org.navalplanner.business.workingday.ResourcesPerDay; import org.navalplanner.web.common.Util; import org.navalplanner.web.planner.allocation.ResourceAllocationController.DerivedAllocationColumn; +import org.zkoss.zk.au.out.AuWrongValue; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Constraint; import org.zkoss.zul.Decimalbox; import org.zkoss.zul.Detail; @@ -97,9 +102,18 @@ public abstract class AllocationRow { } } - public static void loadDataFromLast(Collection rows) { + public static void loadDataFromLast(List rows, + List modifications) { + Validate.isTrue(rows.size() == modifications.size()); + Iterator iterator = modifications + .iterator(); for (AllocationRow each : rows) { each.loadDataFromLast(); + + AllocationModification modification = iterator.next(); + if (!modification.satisfiesModificationRequested()) { + each.warnObjectiveNotSatisfied(modification); + } } } @@ -374,12 +388,40 @@ public abstract class AllocationRow { : CONSTRAINT_FOR_RESOURCES_PER_DAY; } - public void loadDataFromLast() { + private void loadDataFromLast() { + Clients.closeErrorBox(hoursInput); + Clients.closeErrorBox(resourcesPerDayInput); + hoursInput.setValue(temporal.getAssignedHours()); resourcesPerDayInput .setValue(temporal.getResourcesPerDay().getAmount()); } + private void warnObjectiveNotSatisfied(AllocationModification modification) { + modification.byType(new IByType() { + + @Override + public Void onResourcesPerDay( + ResourcesPerDayModification modification) { + ResourcesPerDay goal = modification.getGoal(); + Clients.response(new AuWrongValue(resourcesPerDayInput, _( + "{0} resources per day cannot be fulfilled", goal + .getAmount().toPlainString()))); + + return null; + } + + @Override + public Void onHours(HoursModification modification) { + int goal = modification.getHours(); + Clients.response(new AuWrongValue(hoursInput, _( + "{0} hours cannot be fulfilled", goal + ""))); + + return null; + } + }); + } + public void addListenerForHoursInputChange(EventListener listener) { hoursInput.addEventListener(Events.ON_CHANGE, listener); } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRowsHandler.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRowsHandler.java index 778294540..bc99c0ce2 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRowsHandler.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRowsHandler.java @@ -36,6 +36,7 @@ import org.navalplanner.business.planner.entities.ResourceAllocation; import org.navalplanner.business.planner.entities.ResourceAllocation.AllocationsSpecified.INotFulfilledReceiver; import org.navalplanner.business.planner.entities.ResourceAllocation.Direction; import org.navalplanner.business.planner.entities.Task; +import org.navalplanner.business.planner.entities.allocationalgorithms.AllocationModification; import org.navalplanner.business.planner.entities.allocationalgorithms.HoursModification; import org.navalplanner.business.planner.entities.allocationalgorithms.ResourcesPerDayModification; import org.navalplanner.business.resources.entities.Criterion; @@ -231,28 +232,32 @@ public class AllocationRowsHandler { public AllocationResult doAllocation() { checkInvalidValues(); if (!currentRows.isEmpty()) { - switch (calculatedValue) { - case NUMBER_OF_HOURS: - calculateNumberOfHoursAllocation(); - break; - case END_DATE: - calculateEndDateOrStartDateAllocation(); - break; - case RESOURCES_PER_DAY: - calculateResourcesPerDayAllocation(); - break; - default: - throw new RuntimeException("cant handle: " + calculatedValue); - } + List modificationsDone; + modificationsDone = doSuitableAllocation(); + + AllocationRow.loadDataFromLast(currentRows, modificationsDone); + + createDerived(); } - createDerived(); AllocationResult result = AllocationResult.create(task, calculatedValue, currentRows, getWorkableDaysIfApplyable()); - AllocationRow.loadDataFromLast(currentRows); return result; } - private void calculateNumberOfHoursAllocation() { + private List doSuitableAllocation() { + switch (calculatedValue) { + case NUMBER_OF_HOURS: + return calculateNumberOfHoursAllocation(); + case END_DATE: + return calculateEndDateOrStartDateAllocation(); + case RESOURCES_PER_DAY: + return calculateResourcesPerDayAllocation(); + default: + throw new RuntimeException("cant handle: " + calculatedValue); + } + } + + private List calculateNumberOfHoursAllocation() { List allocations = AllocationRow .createAndAssociate(task, currentRows, requestedToRemove); if (isForwardsAllocation()) { @@ -262,18 +267,20 @@ public class AllocationRowsHandler { ResourceAllocation.allocating(allocations).allocateFromEndUntil( formBinder.getAllocationStart()); } + return allocations; } public boolean isForwardsAllocation() { return Direction.FORWARD.equals(task.getAllocationDirection()); } - private void calculateEndDateOrStartDateAllocation() { + private List calculateEndDateOrStartDateAllocation() { List allocations = AllocationRow .createAndAssociate(task, currentRows, requestedToRemove); ResourceAllocation.allocating(allocations).untilAllocating( task.getAllocationDirection(), formBinder.getAssignedHours(), notFullfiledReceiver()); + return allocations; } private INotFulfilledReceiver notFullfiledReceiver() { @@ -292,7 +299,7 @@ public class AllocationRowsHandler { return AllocationRow.find(currentRows, resourceAllocation); } - private void calculateResourcesPerDayAllocation() { + private List calculateResourcesPerDayAllocation() { List hours = AllocationRow .createHoursModificationsAndAssociate(task, currentRows, requestedToRemove); @@ -303,6 +310,7 @@ public class AllocationRowsHandler { ResourceAllocation.allocatingHours(hours).allocateFromEndUntil( formBinder.getAllocationStart()); } + return hours; } private Integer getWorkableDaysIfApplyable() {