diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java index f0e52d698..aba60dfdb 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java @@ -39,6 +39,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.Validate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -567,6 +568,13 @@ public abstract class ResourceAllocation extends return intendedResourcesPerDay; } + public boolean areIntendedResourcesPerDaySatisfied() { + CalculatedValue calculatedValue = getTask().getCalculatedValue(); + return calculatedValue == CalculatedValue.RESOURCES_PER_DAY + || ObjectUtils.equals(getNonConsolidatedResourcePerDay(), + getIntendedResourcesPerDay()); + } + public ResourceAllocation(Task task) { this(task, null); } 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 2c0c3dde2..1dfb1eb45 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 @@ -79,6 +79,9 @@ import org.zkoss.zul.SimpleListModel; */ public abstract class AllocationRow { + private static final ResourcesPerDay RESOURCES_PER_DAY_DEFAULT_VALUE = ResourcesPerDay + .amount(1); + public static final SimpleConstraint CONSTRAINT_FOR_RESOURCES_PER_DAY = new SimpleConstraint( SimpleConstraint.NO_EMPTY | SimpleConstraint.NO_NEGATIVE); @@ -98,7 +101,8 @@ public abstract class AllocationRow { ResourcesPerDay[] resourcesPerDay) { int i = 0; for (AllocationRow each : rows) { - each.setNonConsolidatedResourcesPerDay(resourcesPerDay[i++]); + each.setResourcesPerDayEditedValue(resourcesPerDay[i++]); + each.clearRealResourcesPerDay(); } } @@ -109,6 +113,7 @@ public abstract class AllocationRow { .iterator(); for (AllocationRow each : rows) { each.loadDataFromLast(); + each.clearRealResourcesPerDay(); AllocationModification modification = iterator.next(); if (!modification.satisfiesModificationRequested()) { @@ -218,22 +223,53 @@ public abstract class AllocationRow { private String name; - private ResourcesPerDay nonConsolidatedResourcesPerDay; - private Intbox hoursInput = new Intbox(); - private final Decimalbox resourcesPerDayInput = new Decimalbox(); + private final Decimalbox intendedResourcesPerDayInput = new Decimalbox(); + + private ResourcesPerDay editedValue; + + private final Label realResourcesPerDay = new Label(); private Grid derivedAllocationsGrid; + public AllocationRow(CalculatedValue calculatedValue) { + this.currentCalculatedValue = calculatedValue; + this.origin = null; + setResourcesPerDayEditedValue(RESOURCES_PER_DAY_DEFAULT_VALUE); + initialize(); + } + + public AllocationRow(ResourceAllocation origin) { + this.origin = origin; + this.currentCalculatedValue = origin.getTask().getCalculatedValue(); + setResourcesPerDayEditedValue(resourcesPerDayForInputFrom(origin)); + if (origin != null && !origin.areIntendedResourcesPerDaySatisfied()) { + onDifferentRealResourcesPerDay(origin + .getNonConsolidatedResourcePerDay()); + } + loadHours(); + initialize(); + } + + private static ResourcesPerDay resourcesPerDayForInputFrom( + ResourceAllocation resourceAllocation) { + CalculatedValue calculatedValue = resourceAllocation.getTask() + .getCalculatedValue(); + return calculatedValue == CalculatedValue.RESOURCES_PER_DAY ? resourceAllocation + .getNonConsolidatedResourcePerDay() : resourceAllocation + .getIntendedResourcesPerDay(); + } + private void initializeResourcesPerDayInput() { - resourcesPerDayInput.setConstraint(CONSTRAINT_FOR_RESOURCES_PER_DAY); - resourcesPerDayInput.setWidth("80px"); - Util.bind(resourcesPerDayInput, new Util.Getter() { + intendedResourcesPerDayInput + .setConstraint(CONSTRAINT_FOR_RESOURCES_PER_DAY); + intendedResourcesPerDayInput.setWidth("80px"); + Util.bind(intendedResourcesPerDayInput, new Util.Getter() { @Override public BigDecimal get() { - return getNonConsolidatedResourcesPerDay().getAmount(); + return getResourcesPerDayEditedValue().getAmount(); } }, new Util.Setter() { @@ -241,26 +277,13 @@ public abstract class AllocationRow { @Override public void set(BigDecimal value) { BigDecimal amount = value == null ? new BigDecimal(0) : value; - setNonConsolidatedResourcesPerDay(ResourcesPerDay + setResourcesPerDayEditedValue(ResourcesPerDay .amount(amount)); } }); } - public AllocationRow(CalculatedValue calculatedValue) { - this.currentCalculatedValue = calculatedValue; - this.origin = null; - initialize(); - } - - public AllocationRow(ResourceAllocation origin) { - this.origin = origin; - this.currentCalculatedValue = origin.getTask().getCalculatedValue(); - initialize(); - } - private void initialize() { - setNonConsolidatedResourcesPerDay(ResourcesPerDay.amount(0)); initializeResourcesPerDayInput(); hoursInput.setWidth("80px"); hoursInput.setConstraint(constraintForHoursInput()); @@ -286,6 +309,18 @@ public abstract class AllocationRow { return origin; } + private void onDifferentRealResourcesPerDay( + ResourcesPerDay realResourcesPerDay) { + this.realResourcesPerDay + .setTooltiptext(_("It can't allocate the intended resources per day")); + this.realResourcesPerDay.setValue(_("(achieved: {0})", + realResourcesPerDay.getAmount().toPlainString())); + } + + private void clearRealResourcesPerDay() { + this.realResourcesPerDay.setValue(""); + } + public boolean hasDerivedAllocations() { return ! getDerivedAllocations().isEmpty(); } @@ -310,20 +345,19 @@ public abstract class AllocationRow { this.name = name; } - public ResourcesPerDay getNonConsolidatedResourcesPerDay() { - return this.nonConsolidatedResourcesPerDay; + public ResourcesPerDay getResourcesPerDayEditedValue() { + return this.editedValue; } public ResourcesPerDay getResourcesPerDayFromInput() { - BigDecimal value = resourcesPerDayInput.getValue(); + BigDecimal value = intendedResourcesPerDayInput.getValue(); value = value != null ? value : BigDecimal.ZERO; return ResourcesPerDay.amount(value); } - public void setNonConsolidatedResourcesPerDay( - ResourcesPerDay resourcesPerDay) { - this.nonConsolidatedResourcesPerDay = resourcesPerDay; - resourcesPerDayInput.setValue(getAmount(resourcesPerDay)); + private void setResourcesPerDayEditedValue(ResourcesPerDay resourcesPerDay) { + this.editedValue = resourcesPerDay; + intendedResourcesPerDayInput.setValue(getAmount(resourcesPerDay)); } private BigDecimal getAmount(ResourcesPerDay resourcesPerDay) { @@ -339,7 +373,7 @@ public abstract class AllocationRow { public abstract boolean isGeneric(); public boolean isEmptyResourcesPerDay() { - return getNonConsolidatedResourcesPerDay().isZero(); + return getResourcesPerDayEditedValue().isZero(); } public abstract List getAssociatedResources(); @@ -348,13 +382,17 @@ public abstract class AllocationRow { return hoursInput; } - public Decimalbox getResourcesPerDayInput() { - return resourcesPerDayInput; + public Decimalbox getIntendedResourcesPerDayInput() { + return intendedResourcesPerDayInput; + } + + public Label getRealResourcesPerDay() { + return realResourcesPerDay; } public void addListenerForInputChange(EventListener onChangeListener) { getHoursInput().addEventListener(Events.ON_CHANGE, onChangeListener); - getResourcesPerDayInput().addEventListener(Events.ON_CHANGE, + getIntendedResourcesPerDayInput().addEventListener(Events.ON_CHANGE, onChangeListener); } @@ -383,10 +421,14 @@ public abstract class AllocationRow { .setDisabled(calculatedValue != CalculatedValue.RESOURCES_PER_DAY || recommendedAllocation); hoursInput.setConstraint(constraintForHoursInput()); - resourcesPerDayInput + intendedResourcesPerDayInput .setDisabled(calculatedValue == CalculatedValue.RESOURCES_PER_DAY || recommendedAllocation); - resourcesPerDayInput.setConstraint(constraintForResourcesPerDayInput()); + if (intendedResourcesPerDayInput.isDisabled()) { + clearRealResourcesPerDay(); + } + intendedResourcesPerDayInput + .setConstraint(constraintForResourcesPerDayInput()); } private Constraint constraintForHoursInput() { @@ -394,17 +436,16 @@ public abstract class AllocationRow { } private Constraint constraintForResourcesPerDayInput() { - return (resourcesPerDayInput.isDisabled()) ? null + return (intendedResourcesPerDayInput.isDisabled()) ? null : CONSTRAINT_FOR_RESOURCES_PER_DAY; } private void loadDataFromLast() { Clients.closeErrorBox(hoursInput); - Clients.closeErrorBox(resourcesPerDayInput); + Clients.closeErrorBox(intendedResourcesPerDayInput); hoursInput.setValue(temporal.getAssignedHours()); - resourcesPerDayInput - .setValue(temporal.getResourcesPerDay().getAmount()); + loadResourcesPerDayFrom(temporal); } private void warnObjectiveNotSatisfied(AllocationModification modification) { @@ -413,10 +454,10 @@ public abstract class AllocationRow { @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()))); + + ResourcesPerDay realResourcesPerDay = modification + .getBeingModified().getNonConsolidatedResourcePerDay(); + onDifferentRealResourcesPerDay(realResourcesPerDay); return null; } @@ -442,7 +483,7 @@ public abstract class AllocationRow { public void addListenerForResourcesPerDayInputChange( EventListener resourcesPerDayRowInputChange) { - resourcesPerDayInput.addEventListener(Events.ON_CHANGE, + intendedResourcesPerDayInput.addEventListener(Events.ON_CHANGE, resourcesPerDayRowInputChange); } @@ -560,19 +601,17 @@ public abstract class AllocationRow { } public void loadResourcesPerDay() { - if (temporal != null) { - nonConsolidatedResourcesPerDay = temporal.getNonConsolidatedResourcePerDay(); - } else { - if (origin != null) { - nonConsolidatedResourcesPerDay = origin - .getNonConsolidatedResourcePerDay(); - } else { - nonConsolidatedResourcesPerDay = ResourcesPerDay.amount(0); - } - } + loadResourcesPerDayFrom(temporal != null ? temporal : origin); + } - resourcesPerDayInput.setValue(nonConsolidatedResourcesPerDay - .getAmount()); + private void loadResourcesPerDayFrom(ResourceAllocation allocation) { + if (allocation == null) { + setResourcesPerDayEditedValue(ResourcesPerDay.amount(0)); + } + boolean useIntention = currentCalculatedValue != CalculatedValue.RESOURCES_PER_DAY; + setResourcesPerDayEditedValue(useIntention ? allocation + .getIntendedResourcesPerDay() : allocation + .getNonConsolidatedResourcePerDay()); } public abstract ResourceEnum getType(); @@ -631,7 +670,7 @@ public abstract class AllocationRow { @Override public Void on(ResourcesPerDayIsZero result) { - throw new WrongValueException(resourcesPerDayInput, + throw new WrongValueException(intendedResourcesPerDayInput, _("Resources per day are zero")); } }); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/FormBinder.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/FormBinder.java index ad9f44e1a..cde13ebbe 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/FormBinder.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/FormBinder.java @@ -654,7 +654,7 @@ public class FormBinder { final String message = _("resources per day must be not empty and bigger than zero"); if (!recommendedAllocation) { AllocationRow first = rows.get(0); - throw new WrongValueException(first.getResourcesPerDayInput(), + throw new WrongValueException(first.getIntendedResourcesPerDayInput(), message); } else { throw new WrongValueException(allResourcesPerDay, message); @@ -790,7 +790,7 @@ public class FormBinder { private BigDecimal sumResourcesPerDayFromInputs() { BigDecimal sum = BigDecimal.ZERO; for (AllocationRow each : rows) { - if (each.getResourcesPerDayInput().isValid()) { + if (each.getIntendedResourcesPerDayInput().isValid()) { sum = sum.add(each.getResourcesPerDayFromInput().getAmount()); } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/GenericAllocationRow.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/GenericAllocationRow.java index f433e1f2d..979676abc 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/GenericAllocationRow.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/GenericAllocationRow.java @@ -42,7 +42,6 @@ import org.navalplanner.business.resources.entities.Criterion; import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.resources.entities.ResourceEnum; import org.navalplanner.business.resources.entities.ResourceType; -import org.navalplanner.business.workingday.ResourcesPerDay; /** * The information required for creating a {@link GenericResourceAllocation} @@ -54,7 +53,6 @@ public class GenericAllocationRow extends AllocationRow { GenericAllocationRow result, ResourceEnum resourceType) { Validate.notNull(resourceType); result.setName(_("Generic")); - result.setNonConsolidatedResourcesPerDay(ResourcesPerDay.amount(0)); result.resourceType = resourceType; return result; } @@ -81,9 +79,6 @@ public class GenericAllocationRow extends AllocationRow { new GenericAllocationRow(resourceAllocation), resourceAllocation.getResourceType()); - result.setNonConsolidatedResourcesPerDay(resourceAllocation - .getNonConsolidatedResourcePerDay()); - ResourceType type = resourceAllocation.isLimiting() ? ResourceType.LIMITING_RESOURCE : ResourceType.NON_LIMITING_RESOURCE; @@ -134,7 +129,7 @@ public class GenericAllocationRow extends AllocationRow { GenericResourceAllocation newGeneric = createGenericAllocation(task, requestedToRemove); return ResourcesPerDayModification - .create(newGeneric, getNonConsolidatedResourcesPerDay(), this.resources); + .create(newGeneric, getResourcesPerDayEditedValue(), this.resources); } private GenericResourceAllocation createGenericAllocation(Task task, diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java index 85b2af27e..7744ad997 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java @@ -66,6 +66,7 @@ import org.zkoss.zul.Checkbox; import org.zkoss.zul.Column; import org.zkoss.zul.Columns; import org.zkoss.zul.Decimalbox; +import org.zkoss.zul.Div; import org.zkoss.zul.Grid; import org.zkoss.zul.Hbox; import org.zkoss.zul.Intbox; @@ -636,7 +637,14 @@ public class ResourceAllocationController extends GenericForwardComposer { .toString())); append(row, new Label(data.getConsolidatedResourcesPerDay() .getAmount().toString())); - append(row, data.getResourcesPerDayInput()); + + Div resourcesPerDayContainer = append(row, new Div()); + append(resourcesPerDayContainer, + data.getIntendedResourcesPerDayInput()); + Label realResourcesPerDay = append(resourcesPerDayContainer, + data.getRealResourcesPerDay()); + realResourcesPerDay.setStyle("float: right; padding-right: 1em;"); + // On click delete button Button deleteButton = appendDeleteButton(row); formBinder.setDeleteButtonFor(data, deleteButton); @@ -685,8 +693,8 @@ public class ResourceAllocationController extends GenericForwardComposer { return append(row, button); } - private T append(Row row, T component) { - row.appendChild(component); + private T append(Component parent, T component) { + parent.appendChild(component); return component; } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/SpecificAllocationRow.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/SpecificAllocationRow.java index 599ecedc4..3ff7b1ef2 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/SpecificAllocationRow.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/SpecificAllocationRow.java @@ -34,7 +34,6 @@ import org.navalplanner.business.planner.entities.allocationalgorithms.HoursModi import org.navalplanner.business.planner.entities.allocationalgorithms.ResourcesPerDayModification; import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.resources.entities.ResourceEnum; -import org.navalplanner.business.workingday.ResourcesPerDay; /** * The information required for creating a {@link SpecificResourceAllocation} @@ -89,10 +88,6 @@ public class SpecificAllocationRow extends AllocationRow { public static SpecificAllocationRow from(SpecificResourceAllocation specific) { SpecificAllocationRow result = new SpecificAllocationRow(specific); setupResource(result, specific.getResource()); - - result.setNonConsolidatedResourcesPerDay(specific - .getNonConsolidatedResourcePerDay()); - return result; } @@ -108,8 +103,6 @@ public class SpecificAllocationRow extends AllocationRow { Resource resource) { specificRow.setName(resource.getShortDescription()); specificRow.setResource(resource); - specificRow - .setNonConsolidatedResourcesPerDay(ResourcesPerDay.amount(1)); } private Resource resource; @@ -126,7 +119,7 @@ public class SpecificAllocationRow extends AllocationRow { public ResourcesPerDayModification toResourcesPerDayModification(Task task, Collection> requestedToRemove) { return ResourcesPerDayModification.create(createSpecific(task), - getNonConsolidatedResourcesPerDay()); + getResourcesPerDayEditedValue()); } private SpecificResourceAllocation createSpecific(Task task) {