Prevent exiting by accept if goals are not satisfied
FEA: ItEr74S04BugFixing
This commit is contained in:
parent
6cf707573a
commit
1e701e1adc
8 changed files with 191 additions and 25 deletions
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2011 Igalia, S.L.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.navalplanner.business.common;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Wraps a value with several arbitrary flags.
|
||||
*
|
||||
* @author Oscar Gonzalez Fernandez <ogonzalez@igalia.com>
|
||||
*
|
||||
* @param <T>
|
||||
* the value that can have flags associated with it
|
||||
* @param <F>
|
||||
* the type of the flags
|
||||
*/
|
||||
public class Flagged<T, F> {
|
||||
|
||||
public static <T, F> Flagged<T, F> justValue(T value) {
|
||||
return new Flagged<T, F>(value, new HashSet<F>());
|
||||
}
|
||||
|
||||
public static <T, F> Flagged<T, F> withFlags(T value, F... flags) {
|
||||
return new Flagged<T, F>(value, new HashSet<F>(Arrays.asList(flags)));
|
||||
}
|
||||
|
||||
private final T value;
|
||||
|
||||
private final Set<F> flags;
|
||||
|
||||
private Flagged(T value, Set<F> flags) {
|
||||
this.value = value;
|
||||
this.flags = Collections.unmodifiableSet(flags);
|
||||
}
|
||||
|
||||
public Flagged<T, F> withFlag(F flag) {
|
||||
Set<F> newFlags = new HashSet<F>(flags);
|
||||
newFlags.add(flag);
|
||||
return new Flagged<T, F>(value, newFlags);
|
||||
}
|
||||
|
||||
public Flagged<T, F> withoutFlag(F flag) {
|
||||
Set<F> newFlags = new HashSet<F>(flags);
|
||||
newFlags.remove(flag);
|
||||
return new Flagged<T, F>(value, newFlags);
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isFlagged() {
|
||||
return !this.flags.isEmpty();
|
||||
}
|
||||
|
||||
public Set<? extends F> getFlags() {
|
||||
return this.flags;
|
||||
}
|
||||
|
||||
public boolean isFlaggedWith(F flag){
|
||||
return this.flags.contains(flag);
|
||||
}
|
||||
|
||||
public boolean isFlaggedWithSomeOf(F... flags) {
|
||||
for (F each : flags) {
|
||||
if (this.isFlaggedWith(each)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,6 +34,16 @@ import org.navalplanner.business.resources.entities.Resource;
|
|||
*/
|
||||
public abstract class AllocationModification {
|
||||
|
||||
public static boolean allFullfiled(
|
||||
Collection<? extends AllocationModification> modificationsDone) {
|
||||
for (AllocationModification each : modificationsDone) {
|
||||
if (!each.satisfiesModificationRequested()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static List<ResourceAllocation<?>> getBeingModified(
|
||||
Collection<? extends AllocationModification> allocationModifications) {
|
||||
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import java.util.Set;
|
|||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.CapacityResult;
|
||||
import org.navalplanner.business.common.Flagged;
|
||||
import org.navalplanner.business.orders.entities.HoursGroup;
|
||||
import org.navalplanner.business.planner.entities.CalculatedValue;
|
||||
import org.navalplanner.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
|
||||
|
|
@ -229,7 +230,11 @@ public class AllocationRowsHandler {
|
|||
return result;
|
||||
}
|
||||
|
||||
public AllocationResult doAllocation() {
|
||||
public enum Warnings {
|
||||
SOME_GOALS_NOT_FULFILLED;
|
||||
}
|
||||
|
||||
public Flagged<AllocationResult, Warnings> doAllocation() {
|
||||
checkInvalidValues();
|
||||
if (!currentRows.isEmpty()) {
|
||||
List<? extends AllocationModification> modificationsDone;
|
||||
|
|
@ -238,10 +243,20 @@ public class AllocationRowsHandler {
|
|||
AllocationRow.loadDataFromLast(currentRows, modificationsDone);
|
||||
|
||||
createDerived();
|
||||
AllocationResult result = createResult();
|
||||
if (AllocationModification.allFullfiled(modificationsDone)) {
|
||||
return Flagged.justValue(result);
|
||||
} else {
|
||||
return Flagged.withFlags(result,
|
||||
Warnings.SOME_GOALS_NOT_FULFILLED);
|
||||
}
|
||||
}
|
||||
AllocationResult result = AllocationResult.create(task,
|
||||
return Flagged.justValue(createResult());
|
||||
}
|
||||
|
||||
private AllocationResult createResult() {
|
||||
return AllocationResult.create(task,
|
||||
calculatedValue, currentRows, getWorkableDaysIfApplyable());
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<? extends AllocationModification> doSuitableAllocation() {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import org.apache.commons.lang.Validate;
|
|||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.navalplanner.business.common.Flagged;
|
||||
import org.navalplanner.business.common.ProportionalDistributor;
|
||||
import org.navalplanner.business.planner.entities.AggregateOfResourceAllocations;
|
||||
import org.navalplanner.business.planner.entities.CalculatedValue;
|
||||
|
|
@ -48,6 +49,7 @@ import org.navalplanner.web.common.Level;
|
|||
import org.navalplanner.web.common.Util;
|
||||
import org.navalplanner.web.common.components.NewAllocationSelectorCombo;
|
||||
import org.navalplanner.web.common.components.ResourceAllocationBehaviour;
|
||||
import org.navalplanner.web.planner.allocation.AllocationRowsHandler.Warnings;
|
||||
import org.navalplanner.web.planner.allocation.IResourceAllocationModel.IResourceAllocationContext;
|
||||
import org.navalplanner.web.planner.taskedition.TaskPropertiesController;
|
||||
import org.zkoss.util.Locales;
|
||||
|
|
@ -486,14 +488,35 @@ public class FormBinder {
|
|||
}
|
||||
|
||||
public void doApply() {
|
||||
lastAllocation = resourceAllocationModel
|
||||
AllocationResult allocationResult = resourceAllocationModel
|
||||
.onAllocationContext(new IResourceAllocationContext<AllocationResult>() {
|
||||
|
||||
@Override
|
||||
public AllocationResult doInsideTransaction() {
|
||||
return allocationRowsHandler.doAllocation();
|
||||
return allocationRowsHandler.doAllocation().getValue();
|
||||
}
|
||||
});
|
||||
allocationProduced(allocationResult);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return <code>true</code> if and only if operation completed and must
|
||||
* exit the edition form
|
||||
*/
|
||||
public boolean accept() {
|
||||
Flagged<AllocationResult, Warnings> result = resourceAllocationModel
|
||||
.accept();
|
||||
|
||||
// result can be null when editing milestones
|
||||
if (result != null && result.isFlagged()) {
|
||||
allocationProduced(result.getValue());
|
||||
}
|
||||
return result == null || !result.isFlagged();
|
||||
}
|
||||
|
||||
private void allocationProduced(AllocationResult allocationResult) {
|
||||
lastAllocation = allocationResult;
|
||||
aggregate = lastAllocation.getAggregate();
|
||||
allResourcesPerDayVisibilityRule();
|
||||
sumResourcesPerDayFromRowsAndAssignToAllResourcesPerDay();
|
||||
|
|
@ -861,5 +884,4 @@ public class FormBinder {
|
|||
this.behaviour = behaviour;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,12 @@ package org.navalplanner.web.planner.allocation;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.common.Flagged;
|
||||
import org.navalplanner.business.common.ProportionalDistributor;
|
||||
import org.navalplanner.business.orders.entities.AggregatedHoursGroup;
|
||||
import org.navalplanner.business.planner.entities.Task;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.web.planner.allocation.AllocationRowsHandler.Warnings;
|
||||
import org.navalplanner.web.planner.order.PlanningState;
|
||||
import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
|
||||
|
||||
|
|
@ -50,8 +52,10 @@ public interface IResourceAllocationModel extends INewAllocationsAdder {
|
|||
|
||||
/**
|
||||
* Save task
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
void accept();
|
||||
Flagged<AllocationResult, Warnings> accept();
|
||||
|
||||
/**
|
||||
* Starts the use case
|
||||
|
|
|
|||
|
|
@ -597,9 +597,17 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
allocationsGrid.setModel(new SimpleListModel(Collections.emptyList()));
|
||||
}
|
||||
|
||||
public void accept() {
|
||||
resourceAllocationModel.accept();
|
||||
clear();
|
||||
/**
|
||||
*
|
||||
* @return <code>true</code> if it must exist <code>false</code> if exit
|
||||
* must be prevented
|
||||
*/
|
||||
public boolean accept() {
|
||||
boolean mustExit = formBinder.accept();
|
||||
if (mustExit) {
|
||||
clear();
|
||||
}
|
||||
return mustExit;
|
||||
}
|
||||
|
||||
private class ResourceAllocationRenderer implements RowRenderer {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.navalplanner.business.common.Flagged;
|
||||
import org.navalplanner.business.common.IAdHocTransactionService;
|
||||
import org.navalplanner.business.common.IOnTransaction;
|
||||
import org.navalplanner.business.common.ProportionalDistributor;
|
||||
|
|
@ -39,11 +40,11 @@ import org.navalplanner.business.planner.daos.ITaskElementDAO;
|
|||
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.DerivedAllocation;
|
||||
import org.navalplanner.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
|
||||
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.Task;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
|
||||
import org.navalplanner.business.resources.daos.ICriterionDAO;
|
||||
import org.navalplanner.business.resources.daos.IResourceDAO;
|
||||
import org.navalplanner.business.resources.daos.IResourcesSearcher;
|
||||
|
|
@ -55,6 +56,7 @@ import org.navalplanner.business.resources.entities.MachineWorkersConfigurationU
|
|||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.resources.entities.ResourceEnum;
|
||||
import org.navalplanner.business.resources.entities.Worker;
|
||||
import org.navalplanner.web.planner.allocation.AllocationRowsHandler.Warnings;
|
||||
import org.navalplanner.web.planner.order.PlanningState;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
|
|
@ -169,42 +171,52 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept() {
|
||||
public Flagged<AllocationResult, Warnings> accept() {
|
||||
if (context != null) {
|
||||
applyAllocationWithDateChangesNotification(new IOnTransaction<Void>() {
|
||||
return applyDateChangesNotificationIfNoFlags(new IOnTransaction<Flagged<AllocationResult, Warnings>>() {
|
||||
@Override
|
||||
public Void execute() {
|
||||
public Flagged<AllocationResult, Warnings> execute() {
|
||||
stepsBeforeDoingAllocation();
|
||||
allocationRowsHandler.doAllocation().applyTo(
|
||||
planningState.getCurrentScenario(), task);
|
||||
return null;
|
||||
Flagged<AllocationResult, Warnings> allocationResult = allocationRowsHandler
|
||||
.doAllocation();
|
||||
if (!allocationResult.isFlagged()) {
|
||||
allocationResult.getValue().applyTo(
|
||||
planningState.getCurrentScenario(), task);
|
||||
}
|
||||
return allocationResult;
|
||||
}
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(final AllocationResult modifiedAllocationResult) {
|
||||
if (context != null) {
|
||||
applyAllocationWithDateChangesNotification(new IOnTransaction<Void>() {
|
||||
applyDateChangesNotificationIfNoFlags(new IOnTransaction<Flagged<Void, Void>>() {
|
||||
@Override
|
||||
public Void execute() {
|
||||
public Flagged<Void, Void> execute() {
|
||||
stepsBeforeDoingAllocation();
|
||||
modifiedAllocationResult.applyTo(planningState
|
||||
.getCurrentScenario(), task);
|
||||
return null;
|
||||
|
||||
return Flagged.justValue(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void applyAllocationWithDateChangesNotification(
|
||||
IOnTransaction<?> allocationDoer) {
|
||||
private <V, T extends Flagged<V, ?>> T applyDateChangesNotificationIfNoFlags(
|
||||
IOnTransaction<T> allocationDoer) {
|
||||
org.zkoss.ganttz.data.Task ganttTask = context.getTask();
|
||||
GanttDate previousStartDate = ganttTask.getBeginDate();
|
||||
GanttDate previousEnd = ganttTask.getEndDate();
|
||||
transactionService.runOnReadOnlyTransaction(allocationDoer);
|
||||
ganttTask.fireChangesForPreviousValues(previousStartDate, previousEnd);
|
||||
T result = transactionService.runOnReadOnlyTransaction(allocationDoer);
|
||||
if (!result.isFlagged()) {
|
||||
ganttTask.fireChangesForPreviousValues(previousStartDate,
|
||||
previousEnd);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void stepsBeforeDoingAllocation() {
|
||||
|
|
|
|||
|
|
@ -282,7 +282,10 @@ public class EditTaskController extends GenericForwardComposer {
|
|||
ResourceAllocationTypeEnum currentState = taskPropertiesController.getCurrentState();
|
||||
if (ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES.equals(currentState)) {
|
||||
editTaskTabbox.setSelectedPanelApi(resourceAllocationTabpanel);
|
||||
resourceAllocationController.accept();
|
||||
boolean mustNotExit = !resourceAllocationController.accept();
|
||||
if (mustNotExit) {
|
||||
return;
|
||||
}
|
||||
} else if (ResourceAllocationTypeEnum.SUBCONTRACT.equals(currentState)) {
|
||||
editTaskTabbox.setSelectedPanelApi(subcontractTabpanel);
|
||||
subcontractController.accept();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue