Merge branch 'master' into scenarios
Conflicts: navalplanner-business/src/main/java/org/navalplanner/business/planner/daos/DayAssignmentDAO.java navalplanner-business/src/main/java/org/navalplanner/business/planner/daos/IDayAssignmentDAO.java navalplanner-business/src/main/java/org/navalplanner/business/planner/daos/ResourceAllocationDAO.java navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/ResourceAllocation.java navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/SpecificResourceAllocation.java navalplanner-webapp/src/main/java/org/navalplanner/web/planner/ITaskElementAdapter.java navalplanner-webapp/src/main/java/org/navalplanner/web/planner/TaskElementAdapter.java navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/OrderPlanningModel.java navalplanner-webapp/src/main/java/org/navalplanner/web/planner/order/SaveCommand.java
This commit is contained in:
commit
948b60dc47
134 changed files with 6205 additions and 1722 deletions
|
|
@ -83,7 +83,7 @@ public class CommandOnTaskContextualized<T> {
|
|||
return new ItemAction<TaskComponent>() {
|
||||
@Override
|
||||
public void onEvent(TaskComponent choosen, Event event) {
|
||||
doAction(choosen.getTask());
|
||||
doAction(choosen);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,9 +57,20 @@ public class DatesMapperOnInterval implements IDatesMapper {
|
|||
return this.toPixels(date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toPixelsAbsolute(long milliseconds) {
|
||||
Date date = new Date(milliseconds);
|
||||
return this.toPixels(date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long toMilliseconds(int pixels) {
|
||||
return millisecondsPerPixel * pixels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMilisecondsPerPixel() {
|
||||
return millisecondsPerPixel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ import org.zkoss.ganttz.data.Position;
|
|||
import org.zkoss.ganttz.data.Task;
|
||||
import org.zkoss.ganttz.data.TaskContainer;
|
||||
import org.zkoss.ganttz.data.TaskLeaf;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.GanttZKDiagramGraph;
|
||||
import org.zkoss.ganttz.data.criticalpath.CriticalPathCalculator;
|
||||
import org.zkoss.ganttz.extensions.IContext;
|
||||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
|
|
@ -166,13 +167,13 @@ public class FunctionalityExposedForExtensions<T> implements IContext<T> {
|
|||
private final IAdapterToTaskFundamentalProperties<T> adapter;
|
||||
private final IStructureNavigator<T> navigator;
|
||||
private final OneToOneMapper<T> mapper = new OneToOneMapper<T>();
|
||||
private final GanttDiagramGraph diagramGraph;
|
||||
private final GanttZKDiagramGraph diagramGraph;
|
||||
private TimeTracker timeTracker;
|
||||
private final PlannerConfiguration<T> configuration;
|
||||
|
||||
public FunctionalityExposedForExtensions(Planner planner,
|
||||
PlannerConfiguration<T> configuration,
|
||||
GanttDiagramGraph diagramGraph) {
|
||||
GanttZKDiagramGraph diagramGraph) {
|
||||
this.planner = planner;
|
||||
this.configuration = configuration;
|
||||
this.adapter = configuration.getAdapter();
|
||||
|
|
@ -313,7 +314,7 @@ public class FunctionalityExposedForExtensions<T> implements IContext<T> {
|
|||
add(position, newDomainObject);
|
||||
}
|
||||
|
||||
public GanttDiagramGraph getDiagramGraph() {
|
||||
public GanttZKDiagramGraph getDiagramGraph() {
|
||||
return diagramGraph;
|
||||
}
|
||||
|
||||
|
|
@ -351,7 +352,7 @@ public class FunctionalityExposedForExtensions<T> implements IContext<T> {
|
|||
|
||||
public void removeDependency(Dependency dependency) {
|
||||
adapter.removeDependency(toDomainDependency(dependency));
|
||||
diagramGraph.remove(dependency);
|
||||
diagramGraph.removeDependency(dependency);
|
||||
getDependencyList().remove(dependency);
|
||||
}
|
||||
|
||||
|
|
@ -478,4 +479,9 @@ public class FunctionalityExposedForExtensions<T> implements IContext<T> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GanttDiagramGraph getGanttDiagramGraph() {
|
||||
return diagramGraph;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import java.util.Date;
|
|||
|
||||
public interface IDatesMapper {
|
||||
|
||||
final long MILISECONDS_PER_HOUR = 3600000;
|
||||
|
||||
int toPixels(Date date);
|
||||
|
||||
Date toDate(int pixel);
|
||||
|
|
@ -32,4 +34,8 @@ public interface IDatesMapper {
|
|||
|
||||
long toMilliseconds(int pixels);
|
||||
|
||||
int toPixelsAbsolute(long milliseconds);
|
||||
|
||||
long getMilisecondsPerPixel();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -389,7 +389,8 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
|
||||
private boolean canChangeStartDate() {
|
||||
return disabilityConfiguration.isMovingTasksEnabled()
|
||||
&& task.canBeExplicitlyMoved();
|
||||
&& task.canBeExplicitlyMoved()
|
||||
&& !task.isLimitingAndHasDayAssignments();
|
||||
}
|
||||
|
||||
private boolean canChangeEndDate() {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import org.zkoss.ganttz.data.Dependency;
|
|||
import org.zkoss.ganttz.data.GanttDiagramGraph;
|
||||
import org.zkoss.ganttz.data.Position;
|
||||
import org.zkoss.ganttz.data.Task;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.GanttZKDiagramGraph;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.IGraphChangeListener;
|
||||
import org.zkoss.ganttz.extensions.ICommand;
|
||||
import org.zkoss.ganttz.extensions.ICommandOnTask;
|
||||
|
|
@ -111,7 +112,7 @@ public class Planner extends HtmlMacroComponent {
|
|||
return result;
|
||||
}
|
||||
|
||||
private GanttDiagramGraph diagramGraph;
|
||||
private GanttZKDiagramGraph diagramGraph;
|
||||
|
||||
private LeftPane leftPane;
|
||||
|
||||
|
|
@ -257,11 +258,14 @@ public class Planner extends HtmlMacroComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
this.diagramGraph = new GanttDiagramGraph(configuration
|
||||
.getStartConstraints(), configuration.getEndConstraints(),
|
||||
configuration.isDependenciesConstraintsHavePriority());
|
||||
this.diagramGraph = GanttDiagramGraph.create(configuration
|
||||
.getStartConstraints(), configuration.getEndConstraints(), configuration.isDependenciesConstraintsHavePriority());
|
||||
FunctionalityExposedForExtensions<T> newContext = new FunctionalityExposedForExtensions<T>(
|
||||
this, configuration, diagramGraph);
|
||||
diagramGraph.addPreChangeListeners(configuration
|
||||
.getPreChangeListeners());
|
||||
diagramGraph.addPostChangeListeners(configuration
|
||||
.getPostChangeListeners());
|
||||
this.contextualizedGlobalCommands = contextualize(newContext,
|
||||
configuration.getGlobalCommands());
|
||||
this.commandsOnTasksContextualized = contextualize(newContext,
|
||||
|
|
|
|||
|
|
@ -183,24 +183,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
setHeight(HEIGHT_PER_TASK + "px");
|
||||
setContext("idContextMenuTaskAssignment");
|
||||
this.task = task;
|
||||
String cssClass = "";
|
||||
if (task.isSubcontracted()) {
|
||||
cssClass = "box subcontracted-task";
|
||||
} else {
|
||||
if (task.isContainer()) {
|
||||
if (task.isExpanded()) {
|
||||
cssClass = "box standard-task expanded";
|
||||
} else {
|
||||
cssClass = "box standard-task closed";
|
||||
}
|
||||
} else {
|
||||
cssClass = "box standard-task";
|
||||
}
|
||||
setClass(calculateCSSClass());
|
||||
|
||||
cssClass += " " + getTask().getAssignedStatus();
|
||||
|
||||
setClass(cssClass);
|
||||
}
|
||||
setId(UUID.randomUUID().toString());
|
||||
this.disabilityConfiguration = disabilityConfiguration;
|
||||
taskViolationListener = new IConstraintViolationListener<Date>() {
|
||||
|
|
@ -219,64 +203,37 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
if (canShowResourcesText()) {
|
||||
smartUpdate("resourcesText", getResourcesText());
|
||||
}
|
||||
String cssClass = calculateCssClass();
|
||||
String cssClass = calculateCSSClass();
|
||||
|
||||
response("setClass", new AuInvoke(TaskComponent.this,
|
||||
"setClass", cssClass));
|
||||
}
|
||||
|
||||
private String calculateCssClass() {
|
||||
String cssClass = (isSubcontracted() ? "box subcontracted-task"
|
||||
: "box standard-task")
|
||||
+ (isResizingTasksEnabled() ? " yui-resize" : "");
|
||||
|
||||
if (getTask() instanceof TaskContainer) {
|
||||
if (getTask().isExpanded()) {
|
||||
cssClass += " expanded";
|
||||
} else {
|
||||
cssClass += " closed";
|
||||
}
|
||||
}
|
||||
|
||||
cssClass += " " + getTask().getAssignedStatus();
|
||||
|
||||
return cssClass;
|
||||
}
|
||||
|
||||
};
|
||||
this.task.addReloadListener(reloadResourcesTextRequested);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: This method is intended to be overridden.
|
||||
*/
|
||||
protected boolean canShowResourcesText() {
|
||||
return true;
|
||||
/* Generate CSS class attribute depending on task properties */
|
||||
protected String calculateCSSClass() {
|
||||
String cssClass = isSubcontracted() ? "box subcontracted-task"
|
||||
: "box standard-task";
|
||||
cssClass += isResizingTasksEnabled() ? " yui-resize" : "";
|
||||
if (isContainer()) {
|
||||
cssClass += task.isExpanded() ? " expanded" : " closed ";
|
||||
}
|
||||
cssClass += task.isInCriticalPath() ? " critical" : "";
|
||||
cssClass += " " + task.getAssignedStatus();
|
||||
if (task.isLimiting()) {
|
||||
cssClass += task.isLimitingAndHasDayAssignments() ? " limiting-assigned "
|
||||
: " limiting-unassigned ";
|
||||
}
|
||||
return cssClass;
|
||||
}
|
||||
|
||||
protected String calculateClass() {
|
||||
String classText;
|
||||
|
||||
if (getSclass() == null || getSclass().equals("null")) {
|
||||
classText = "box";
|
||||
} else {
|
||||
classText = getSclass();
|
||||
}
|
||||
if (task.isInCriticalPath()) {
|
||||
classText += " critical";
|
||||
}
|
||||
if (task.isSubcontracted()) {
|
||||
classText += " subcontracted-task";
|
||||
}
|
||||
|
||||
classText += " " + getTask().getAssignedStatus();
|
||||
|
||||
return classText;
|
||||
}
|
||||
|
||||
protected void updateClass() {
|
||||
response(null, new AuInvoke(this, "setClass",
|
||||
new Object[] { calculateClass() }));
|
||||
new Object[] { calculateCSSClass() }));
|
||||
}
|
||||
|
||||
public final void afterCompose() {
|
||||
|
|
@ -311,6 +268,13 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
updateClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: This method is intended to be overridden.
|
||||
*/
|
||||
protected boolean canShowResourcesText() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private String _color;
|
||||
|
||||
private boolean isTopLevel;
|
||||
|
|
@ -356,7 +320,8 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
|
||||
public boolean isResizingTasksEnabled() {
|
||||
return disabilityConfiguration.isResizingTasksEnabled()
|
||||
return (disabilityConfiguration != null)
|
||||
&& disabilityConfiguration.isResizingTasksEnabled()
|
||||
&& !task.isSubcontracted() && task.canBeExplicitlyResized();
|
||||
}
|
||||
|
||||
|
|
@ -366,7 +331,13 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
}
|
||||
|
||||
void doUpdatePosition(String leftX, String topY) {
|
||||
Date startBeforeMoving = this.task.getBeginDate();
|
||||
this.task.moveTo(getMapper().toDate(stripPx(leftX)));
|
||||
boolean remainsInOriginalPosition = this.task.getBeginDate().equals(
|
||||
startBeforeMoving);
|
||||
if (remainsInOriginalPosition) {
|
||||
updateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void doUpdateSize(String size) {
|
||||
|
|
@ -550,6 +521,10 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
return task.isSubcontracted();
|
||||
}
|
||||
|
||||
public boolean isContainer() {
|
||||
return task.isContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return task.toString();
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@ public class TaskContainerComponent extends TaskComponent implements
|
|||
}
|
||||
|
||||
@Override
|
||||
protected String calculateClass() {
|
||||
return super.calculateClass() + " "
|
||||
protected String calculateCSSClass() {
|
||||
return super.calculateCSSClass() + " "
|
||||
+ (getTaskContainer().isExpanded() ? "expanded" : "closed");
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ import java.util.Map;
|
|||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.zkoss.ganttz.Planner;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.IGraphChangeListener;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint;
|
||||
import org.zkoss.ganttz.data.constraint.DateConstraint;
|
||||
import org.zkoss.ganttz.extensions.ICommand;
|
||||
|
|
@ -150,6 +151,10 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
|
||||
private boolean expandPlanningViewCharts;
|
||||
|
||||
private final List<IGraphChangeListener> preGraphChangeListeners = new ArrayList<IGraphChangeListener>();
|
||||
|
||||
private final List<IGraphChangeListener> postGraphChangeListeners = new ArrayList<IGraphChangeListener>();
|
||||
|
||||
public PlannerConfiguration(IAdapterToTaskFundamentalProperties<T> adapter,
|
||||
IStructureNavigator<T> navigator, List<? extends T> data) {
|
||||
this.adapter = adapter;
|
||||
|
|
@ -380,4 +385,24 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
return expandPlanningViewCharts;
|
||||
}
|
||||
|
||||
public void addPreGraphChangeListener(
|
||||
IGraphChangeListener preGraphChangeListener) {
|
||||
Validate.notNull(preGraphChangeListener);
|
||||
preGraphChangeListeners.add(preGraphChangeListener);
|
||||
}
|
||||
|
||||
public void addPostGraphChangeListener(
|
||||
IGraphChangeListener postGraphChangeListener) {
|
||||
Validate.notNull(postGraphChangeListener);
|
||||
postGraphChangeListeners.add(postGraphChangeListener);
|
||||
}
|
||||
|
||||
public List<IGraphChangeListener> getPreChangeListeners() {
|
||||
return Collections.unmodifiableList(preGraphChangeListeners);
|
||||
}
|
||||
|
||||
public List<IGraphChangeListener> getPostChangeListeners() {
|
||||
return Collections.unmodifiableList(postGraphChangeListeners);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties
|
|||
long lengthMilliseconds, String notes,
|
||||
Date hoursAdvanceEndDate,
|
||||
Date advanceEndDate,
|
||||
BigDecimal hoursAdvancePercentage, BigDecimal advancePercentage) {
|
||||
BigDecimal hoursAdvancePercentage, BigDecimal advancePercentage) {
|
||||
this.name = name;
|
||||
this.beginDate = beginDate.getTime();
|
||||
this.lengthMilliseconds = lengthMilliseconds;
|
||||
|
|
@ -167,11 +167,23 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isLimiting() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isLimitingAndHasDayAssignments() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeExplicitlyResized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasConsolidations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAssignedStatus() {
|
||||
return "unassigned";
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.GanttZKAdapter;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.TaskPoint;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
||||
|
|
@ -167,8 +168,9 @@ public class Dependency implements IDependency<Task> {
|
|||
return new Dependency(source, destination, type, visible);
|
||||
}
|
||||
|
||||
public TaskPoint getDestinationPoint() {
|
||||
return new TaskPoint(destination, type.getPointModified());
|
||||
public TaskPoint<Task, Dependency> getDestinationPoint() {
|
||||
return new TaskPoint<Task, Dependency>(new GanttZKAdapter(),
|
||||
destination, type.getPointModified());
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -78,6 +78,12 @@ public interface ITaskFundamentalProperties {
|
|||
|
||||
public boolean isSubcontracted();
|
||||
|
||||
public boolean isLimiting();
|
||||
|
||||
public boolean isLimitingAndHasDayAssignments();
|
||||
|
||||
public boolean hasConsolidations();
|
||||
|
||||
public boolean canBeExplicitlyResized();
|
||||
|
||||
public String getAssignedStatus();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ import java.util.List;
|
|||
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.IDependenciesEnforcerHook;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.IDependenciesEnforcerHookFactory;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph.INotificationAfterDependenciesEnforcement;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint;
|
||||
import org.zkoss.ganttz.data.constraint.DateConstraint;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
||||
|
|
@ -66,6 +69,46 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
private ConstraintViolationNotificator<Date> violationNotificator = ConstraintViolationNotificator
|
||||
.create();
|
||||
|
||||
private IDependenciesEnforcerHook dependenciesEnforcerHook = doNothingHook();
|
||||
|
||||
private final INotificationAfterDependenciesEnforcement notifyDates = new INotificationAfterDependenciesEnforcement() {
|
||||
|
||||
@Override
|
||||
public void onStartDateChange(Date previousStart, long oldLength,
|
||||
Date newStart) {
|
||||
fundamentalPropertiesListeners.firePropertyChange("beginDate",
|
||||
previousStart, fundamentalProperties.getBeginDate());
|
||||
fireLengthMilliseconds(oldLength);
|
||||
reloadResourcesTextIfChange(newStart, previousStart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLengthChange(long previousLength, long newLength) {
|
||||
fireLengthMilliseconds(previousLength);
|
||||
}
|
||||
|
||||
private void fireLengthMilliseconds(long previousValue) {
|
||||
fundamentalPropertiesListeners.firePropertyChange(
|
||||
"lengthMilliseconds", previousValue, fundamentalProperties
|
||||
.getLengthMilliseconds());
|
||||
}
|
||||
};
|
||||
|
||||
private IDependenciesEnforcerHook doNothingHook() {
|
||||
return new IDependenciesEnforcerHook() {
|
||||
|
||||
@Override
|
||||
public void setLengthMilliseconds(long previousLengthMilliseconds,
|
||||
long lengthMilliseconds) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStartDate(Date previousStart, long previousLength,
|
||||
Date newStart) {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
public Task(ITaskFundamentalProperties fundamentalProperties) {
|
||||
this.fundamentalProperties = fundamentalProperties;
|
||||
}
|
||||
|
|
@ -140,14 +183,19 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
previousValue, name);
|
||||
}
|
||||
|
||||
public long setBeginDate(Date beginDate) {
|
||||
public void registerDependenciesEnforcerHook(
|
||||
IDependenciesEnforcerHookFactory factory) {
|
||||
Validate.notNull(factory);
|
||||
dependenciesEnforcerHook = factory.create(this, notifyDates);
|
||||
Validate.notNull(dependenciesEnforcerHook);
|
||||
}
|
||||
|
||||
public long setBeginDate(Date newStart) {
|
||||
Date previousValue = fundamentalProperties.getBeginDate();
|
||||
long oldLength = fundamentalProperties.getLengthMilliseconds();
|
||||
fundamentalProperties.setBeginDate(beginDate);
|
||||
fundamentalPropertiesListeners.firePropertyChange("beginDate",
|
||||
previousValue, fundamentalProperties.getBeginDate());
|
||||
fireLengthMilliseconds(oldLength);
|
||||
reloadResourcesTextIfChange(beginDate, previousValue);
|
||||
long previousLength = fundamentalProperties.getLengthMilliseconds();
|
||||
fundamentalProperties.setBeginDate(newStart);
|
||||
dependenciesEnforcerHook.setStartDate(previousValue, previousLength,
|
||||
newStart);
|
||||
return fundamentalProperties.getLengthMilliseconds();
|
||||
}
|
||||
|
||||
|
|
@ -159,9 +207,10 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
|
||||
public void fireChangesForPreviousValues(Date previousStart,
|
||||
long previousLength) {
|
||||
fundamentalPropertiesListeners.firePropertyChange("beginDate",
|
||||
previousStart, fundamentalProperties.getBeginDate());
|
||||
fireLengthMilliseconds(previousLength);
|
||||
dependenciesEnforcerHook.setStartDate(previousStart, previousLength,
|
||||
fundamentalProperties.getBeginDate());
|
||||
dependenciesEnforcerHook.setLengthMilliseconds(previousLength,
|
||||
fundamentalProperties.getLengthMilliseconds());
|
||||
}
|
||||
|
||||
public Date getBeginDate() {
|
||||
|
|
@ -171,12 +220,8 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
public void setLengthMilliseconds(long lengthMilliseconds) {
|
||||
long previousValue = fundamentalProperties.getLengthMilliseconds();
|
||||
fundamentalProperties.setLengthMilliseconds(lengthMilliseconds);
|
||||
fireLengthMilliseconds(previousValue);
|
||||
}
|
||||
|
||||
private void fireLengthMilliseconds(long previousValue) {
|
||||
fundamentalPropertiesListeners.firePropertyChange("lengthMilliseconds",
|
||||
previousValue, fundamentalProperties.getLengthMilliseconds());
|
||||
dependenciesEnforcerHook.setLengthMilliseconds(previousValue,
|
||||
lengthMilliseconds);
|
||||
}
|
||||
|
||||
public long getLengthMilliseconds() {
|
||||
|
|
@ -208,6 +253,9 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
}
|
||||
|
||||
public Constraint<Date> getCurrentLengthConstraint() {
|
||||
if (isContainer()) {
|
||||
return Constraint.emptyConstraint();
|
||||
}
|
||||
return violationNotificator.withListener(DateConstraint
|
||||
.biggerOrEqualThan(getEndDate()));
|
||||
}
|
||||
|
|
@ -275,9 +323,7 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
Date previousStart = getBeginDate();
|
||||
long previousLength = getLengthMilliseconds();
|
||||
fundamentalProperties.moveTo(date);
|
||||
fireChangesForPreviousValues(previousStart, previousLength);
|
||||
reloadResourcesTextIfChange(date, previousStart);
|
||||
reloadResourcesText();
|
||||
dependenciesEnforcerHook.setStartDate(previousStart, previousLength, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -311,6 +357,18 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
return fundamentalProperties.isSubcontracted();
|
||||
}
|
||||
|
||||
public boolean isLimiting() {
|
||||
return fundamentalProperties.isLimiting();
|
||||
}
|
||||
|
||||
public boolean isLimitingAndHasDayAssignments() {
|
||||
return fundamentalProperties.isLimitingAndHasDayAssignments();
|
||||
}
|
||||
|
||||
public boolean hasConsolidations() {
|
||||
return fundamentalProperties.hasConsolidations();
|
||||
}
|
||||
|
||||
public boolean canBeExplicitlyResized() {
|
||||
return fundamentalProperties.canBeExplicitlyResized();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class TaskLeaf extends Task {
|
|||
|
||||
@Override
|
||||
public boolean canBeExplicitlyMoved() {
|
||||
return !isSubcontracted();
|
||||
return !(isSubcontracted() || isLimitingAndHasDayAssignments() || hasConsolidations());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,21 @@ import org.zkoss.ganttz.util.WeakReferencedListeners.IListenerNotification;
|
|||
*/
|
||||
public abstract class Constraint<T> {
|
||||
|
||||
public static <T> Constraint<T> emptyConstraint() {
|
||||
return new Constraint<T>() {
|
||||
|
||||
@Override
|
||||
protected T applyConstraintTo(T currentValue) {
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfiedBy(T value) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public interface IConstraintViolationListener<T> {
|
||||
public void constraintViolated(Constraint<T> constraint, T value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* 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.zkoss.ganttz.data.limitingresource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.zkoss.ganttz.data.resourceload.LoadLevel;
|
||||
|
||||
public class QueueTask {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(QueueTask.class);
|
||||
|
||||
private final LocalDate start;
|
||||
|
||||
private final LocalDate end;
|
||||
|
||||
private final LoadLevel loadLevel;
|
||||
|
||||
private final int totalResourceWorkHours;
|
||||
|
||||
private final int assignedHours;
|
||||
|
||||
public QueueTask(LocalDate start, LocalDate end,
|
||||
int totalResourceWorkHours, int assignedHours, LoadLevel loadLevel) {
|
||||
Validate.notNull(start);
|
||||
Validate.notNull(end);
|
||||
Validate.notNull(loadLevel);
|
||||
Validate.notNull(totalResourceWorkHours);
|
||||
Validate.notNull(assignedHours);
|
||||
Validate.isTrue(!start.isAfter(end));
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.loadLevel = loadLevel;
|
||||
this.totalResourceWorkHours = totalResourceWorkHours;
|
||||
this.assignedHours = assignedHours;
|
||||
}
|
||||
|
||||
public LocalDate getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public LocalDate getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
// public boolean overlaps(QueueTask other) {
|
||||
// return start.isBefore(other.end) && end.isAfter(other.start);
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param loadPeriods
|
||||
* @return
|
||||
* @throws IllegalArgumentException
|
||||
* if some of the QueueTask overlaps
|
||||
*/
|
||||
public static List<QueueTask> sort(List<QueueTask> loadPeriods)
|
||||
throws IllegalArgumentException {
|
||||
ArrayList<QueueTask> result = new ArrayList<QueueTask>(loadPeriods);
|
||||
// Collections.sort(result, new Comparator<QueueTask>() {
|
||||
|
||||
// @Override
|
||||
// public int compare(QueueTask o1, QueueTask o2) {
|
||||
// if (o1.overlaps(o2)) {
|
||||
// LOG.warn(o1 + " overlaps with " + o2);
|
||||
// throw new IllegalArgumentException(o1 + " overlaps with "
|
||||
// + o2);
|
||||
// }
|
||||
// int comparison = compareLocalDates(o1.start, o2.start);
|
||||
// if (comparison != 0) {
|
||||
// return comparison;
|
||||
// }
|
||||
// return compareLocalDates(o1.end, o2.end);
|
||||
// }
|
||||
// });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int compareLocalDates(LocalDate l1, LocalDate l2) {
|
||||
if (l1.isBefore(l2)) {
|
||||
return -1;
|
||||
}
|
||||
if (l1.isAfter(l2)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this);
|
||||
}
|
||||
|
||||
public LoadLevel getLoadLevel() {
|
||||
return loadLevel;
|
||||
}
|
||||
|
||||
public int getTotalResourceWorkHours() {
|
||||
return totalResourceWorkHours;
|
||||
}
|
||||
|
||||
public int getAssignedHours() {
|
||||
return assignedHours;
|
||||
}
|
||||
}
|
||||
|
|
@ -71,7 +71,6 @@ public class LoadTimeLine {
|
|||
this.timeLineRole = principal.getRole();
|
||||
this.type = principal.getType();
|
||||
Validate.notNull(children);
|
||||
allChildrenAreNotEmpty(children);
|
||||
this.children = Collections
|
||||
.unmodifiableList(new ArrayList<LoadTimeLine>(children));
|
||||
|
||||
|
|
@ -178,8 +177,8 @@ public class LoadTimeLine {
|
|||
public List<LoadTimeLine> getAllChildren() {
|
||||
List<LoadTimeLine> result = new ArrayList<LoadTimeLine>();
|
||||
for (LoadTimeLine child : children) {
|
||||
result.addAll(child.getAllChildren());
|
||||
result.add(child);
|
||||
result.addAll(child.getAllChildren());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
|
||||
import org.zkoss.ganttz.adapters.IDomainAndBeansMapper;
|
||||
import org.zkoss.ganttz.adapters.PlannerConfiguration;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph;
|
||||
import org.zkoss.ganttz.data.Position;
|
||||
import org.zkoss.ganttz.data.Task;
|
||||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
|
|
@ -115,4 +116,9 @@ public class ContextRelativeToOtherComponent<T> implements IContext<T> {
|
|||
return context.getTasksOrderedByStartDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GanttDiagramGraph getGanttDiagramGraph() {
|
||||
return context.getGanttDiagramGraph();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
|
||||
import org.zkoss.ganttz.adapters.IDomainAndBeansMapper;
|
||||
import org.zkoss.ganttz.adapters.PlannerConfiguration;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph;
|
||||
import org.zkoss.ganttz.data.Position;
|
||||
import org.zkoss.ganttz.data.Task;
|
||||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
|
|
@ -117,4 +118,9 @@ public class ContextWithPlannerTask<T> implements IContextWithPlannerTask<T> {
|
|||
return context.getTasksOrderedByStartDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GanttDiagramGraph getGanttDiagramGraph() {
|
||||
return context.getGanttDiagramGraph();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.zkoss.ganttz.adapters.IAdapterToTaskFundamentalProperties;
|
|||
import org.zkoss.ganttz.adapters.IDomainAndBeansMapper;
|
||||
import org.zkoss.ganttz.adapters.IStructureNavigator;
|
||||
import org.zkoss.ganttz.adapters.PlannerConfiguration;
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph;
|
||||
import org.zkoss.ganttz.data.Position;
|
||||
import org.zkoss.ganttz.data.Task;
|
||||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
|
|
@ -121,4 +122,6 @@ public interface IContext<T> {
|
|||
|
||||
public void reloadCharts();
|
||||
|
||||
public GanttDiagramGraph getGanttDiagramGraph();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import static org.zkoss.ganttz.i18n.I18nHelper._;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.zkoss.ganttz.IChartVisibilityChangedListener;
|
||||
import org.zkoss.ganttz.data.resourceload.LoadTimeLine;
|
||||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
import org.zkoss.ganttz.timetracker.TimeTrackerComponent;
|
||||
|
|
@ -43,6 +44,7 @@ import org.zkoss.zk.ui.HtmlMacroComponent;
|
|||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zkex.zul.api.South;
|
||||
import org.zkoss.zul.Button;
|
||||
import org.zkoss.zul.Comboitem;
|
||||
import org.zkoss.zul.ListModel;
|
||||
|
|
@ -88,14 +90,28 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
private int filterByNamePosition = 0;
|
||||
private int numberOfGroupsByName = 10;
|
||||
|
||||
public ResourcesLoadPanel(List<LoadTimeLine> groups,
|
||||
TimeTracker timeTracker, Component componentOnWhichGiveFeedback) {
|
||||
this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
|
||||
init(groups, timeTracker);
|
||||
private WeakReferencedListeners<IFilterChangedListener> nameFilterListener =
|
||||
WeakReferencedListeners.create();
|
||||
|
||||
private Component loadChart;
|
||||
|
||||
private boolean visibleChart = true;
|
||||
|
||||
private WeakReferencedListeners<IChartVisibilityChangedListener> chartVisibilityListeners = WeakReferencedListeners
|
||||
.create();
|
||||
|
||||
private final boolean expandResourceLoadViewCharts;
|
||||
|
||||
public ResourcesLoadPanel(List<LoadTimeLine> groups,
|
||||
TimeTracker timeTracker, Component componentOnWhichGiveFeedback,
|
||||
boolean expandResourceLoadViewCharts) {
|
||||
this.componentOnWhichGiveFeedback = componentOnWhichGiveFeedback;
|
||||
this.expandResourceLoadViewCharts = expandResourceLoadViewCharts;
|
||||
init(groups, timeTracker);
|
||||
}
|
||||
|
||||
public void init(List<LoadTimeLine> groups, TimeTracker timeTracker) {
|
||||
refreshNameFilter = true;
|
||||
this.groups = groups;
|
||||
this.timeTracker = timeTracker;
|
||||
treeModel = createModelForTree();
|
||||
|
|
@ -280,9 +296,14 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
TimeTrackerComponent timeTrackerHeader = createTimeTrackerHeader();
|
||||
getFellow("insertionPointTimetracker").appendChild(timeTrackerHeader);
|
||||
|
||||
Component additionalFilter = (Component) getVariable("additionalFilter", true);
|
||||
// Insert additional filters if any
|
||||
Component additionalFilter = (Component) getVariable("additionalFilter1", true);
|
||||
if(additionalFilter != null) {
|
||||
getFellow("additionalFilterInsertionPoint").appendChild(additionalFilter);
|
||||
getFellow("additionalFilterInsertionPoint1").appendChild(additionalFilter);
|
||||
}
|
||||
additionalFilter = (Component) getVariable("additionalFilter2", true);
|
||||
if(additionalFilter != null) {
|
||||
getFellow("additionalFilterInsertionPoint2").appendChild(additionalFilter);
|
||||
}
|
||||
|
||||
timeTrackerHeader.afterCompose();
|
||||
|
|
@ -293,12 +314,18 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
if(refreshNameFilter) {
|
||||
setupNameFilter();
|
||||
}
|
||||
|
||||
getFellow("insertionPointChart").appendChild(loadChart);
|
||||
|
||||
this.visibleChart = expandResourceLoadViewCharts;
|
||||
((South) getFellow("graphics")).setOpen(this.visibleChart);
|
||||
}
|
||||
|
||||
public void clearComponents() {
|
||||
getFellow("insertionPointLeftPanel").getChildren().clear();
|
||||
getFellow("insertionPointRightPanel").getChildren().clear();
|
||||
getFellow("insertionPointTimetracker").getChildren().clear();
|
||||
getFellow("insertionPointChart").getChildren().clear();
|
||||
}
|
||||
|
||||
private TimeTrackerComponent createTimeTrackerHeader() {
|
||||
|
|
@ -375,7 +402,34 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
public void onSelectFilterByName(Integer filterByNamePosition) {
|
||||
this.filterByNamePosition = filterByNamePosition.intValue();
|
||||
this.feedBackMessage = _("filtering by name");
|
||||
invalidatingChangeHappenedWithFeedback();
|
||||
changeNameFilterWithFeedback();
|
||||
}
|
||||
|
||||
private void changeNameFilterWithFeedback() {
|
||||
LongOperationFeedback.execute(componentOnWhichGiveFeedback,
|
||||
new ILongOperation() {
|
||||
|
||||
@Override
|
||||
public void doAction() throws Exception {
|
||||
treeModel = createModelForTree();
|
||||
timeTrackerComponent = timeTrackerForResourcesLoadPanel(timeTracker);
|
||||
resourceLoadList = new ResourceLoadList(timeTracker, treeModel);
|
||||
leftPane = new ResourceLoadLeftPane(treeModel, resourceLoadList);
|
||||
registerNeededScripts();
|
||||
nameFilterListener.fireEvent(new IListenerNotification<IFilterChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(IFilterChangedListener listener) {
|
||||
listener.filterChanged(getFilter());
|
||||
}
|
||||
});
|
||||
afterCompose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getFeedBackMessage();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setNameFilterDisabled(boolean disabled) {
|
||||
|
|
@ -387,4 +441,34 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
}
|
||||
}
|
||||
|
||||
public void addNameFilterListener(
|
||||
IFilterChangedListener iFilterChangedListener) {
|
||||
nameFilterListener.addListener(iFilterChangedListener);
|
||||
}
|
||||
|
||||
public void changeChartVisibility(boolean visible) {
|
||||
visibleChart = visible;
|
||||
chartVisibilityListeners
|
||||
.fireEvent(new IListenerNotification<IChartVisibilityChangedListener>() {
|
||||
@Override
|
||||
public void doNotify(
|
||||
IChartVisibilityChangedListener listener) {
|
||||
listener.chartVisibilityChanged(visibleChart);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isVisibleChart() {
|
||||
return visibleChart;
|
||||
}
|
||||
|
||||
public void addChartVisibilityListener(
|
||||
IChartVisibilityChangedListener chartVisibilityChangedListener) {
|
||||
chartVisibilityListeners.addListener(chartVisibilityChangedListener);
|
||||
}
|
||||
|
||||
public void setLoadChart(Component loadChart) {
|
||||
this.loadChart = loadChart;
|
||||
}
|
||||
|
||||
}
|
||||
33
ganttzk/src/main/java/org/zkoss/ganttz/util/IAction.java
Normal file
33
ganttzk/src/main/java/org/zkoss/ganttz/util/IAction.java
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* 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.zkoss.ganttz.util;
|
||||
|
||||
import org.zkoss.ganttz.data.GanttDiagramGraph;
|
||||
|
||||
/**
|
||||
* Represents some computation to execute. It's usually used to execute some
|
||||
* computation in a context.
|
||||
* @see PreAndPostNotReentrantActionsWrapper
|
||||
* {@link GanttDiagramGraph#manualNotificationOn(IAction)}
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
*/
|
||||
public interface IAction {
|
||||
public void doAction();
|
||||
}
|
||||
|
|
@ -26,10 +26,6 @@ import org.apache.commons.lang.Validate;
|
|||
*/
|
||||
public abstract class PreAndPostNotReentrantActionsWrapper {
|
||||
|
||||
public interface IAction {
|
||||
public void doAction();
|
||||
}
|
||||
|
||||
private final ThreadLocal<Boolean> inside = new ThreadLocal<Boolean>() {
|
||||
@Override
|
||||
protected Boolean initialValue() {
|
||||
|
|
|
|||
|
|
@ -38,17 +38,19 @@ resourcesLoadPanel = self;
|
|||
onSelect="resourcesLoadPanel.setZoomLevel(self.selectedItem.value);" >
|
||||
</listbox>
|
||||
<separator/>
|
||||
<hbox id="additionalFilterInsertionPoint1" />
|
||||
<separator/>
|
||||
Filter:
|
||||
<listbox id="listFilters" mold="select" rows="1" width="150px"
|
||||
<listbox id="listFilters" mold="select" rows="1" width="100px"
|
||||
model="${resourcesLoadPanel.filters}"
|
||||
onSelect="resourcesLoadPanel.setFilter(self.selectedItem.value);">
|
||||
</listbox>
|
||||
<separator/>
|
||||
${i18n:_('Show elements between')}:
|
||||
<combobox id="filterByNameCombo"
|
||||
${i18n:_('Name filter')}:
|
||||
<combobox id="filterByNameCombo" width="50px"
|
||||
onChange="resourcesLoadPanel.onSelectFilterByName(self.selectedItemApi.value)" />
|
||||
<separator/>
|
||||
<hbox id="additionalFilterInsertionPoint" />
|
||||
<hbox id="additionalFilterInsertionPoint2" />
|
||||
</hbox>
|
||||
</north>
|
||||
|
||||
|
|
@ -85,35 +87,10 @@ resourcesLoadPanel = self;
|
|||
</center>
|
||||
</borderlayout>
|
||||
</center>
|
||||
<south height="170px" collapsible="true" title="Resources load graph legend">
|
||||
<borderlayout>
|
||||
<center sclass="legend-gap">
|
||||
<vbox pack="center" align="center" height="150px" width="100%">
|
||||
<vbox sclass="legend">
|
||||
|
||||
<hbox pack="center" sclass="legend-title">
|
||||
<n:label class="title">${i18n:_('Assignation percentage')}</n:label>
|
||||
</hbox>
|
||||
|
||||
<hbox pack="center" sclass="legend-row">
|
||||
<n:div class="resourceload SOME_LOAD" />
|
||||
<n:label>${i18n:_('0% - 100%')}</n:label>
|
||||
</hbox>
|
||||
|
||||
<hbox pack="center" sclass="legend-row">
|
||||
<n:div class="resourceload FULL_LOAD" />
|
||||
<n:label>${i18n:_('100%')}</n:label>
|
||||
</hbox>
|
||||
|
||||
<hbox pack="center" sclass="legend-row">
|
||||
<n:div class="resourceload OVERLOAD" />
|
||||
<n:label>${i18n:_('+ 100%')}</n:label>
|
||||
</hbox>
|
||||
|
||||
</vbox>
|
||||
</vbox>
|
||||
</center>
|
||||
</borderlayout>
|
||||
<south height="200px" collapsible="true" title="Graphics"
|
||||
sclass="scheduling-graphics" id="graphics"
|
||||
onOpen="resourcesLoadPanel.changeChartVisibility(event.open);">
|
||||
<div id="insertionPointChart" />
|
||||
</south>
|
||||
</borderlayout>
|
||||
</zk>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ function addResourcesLoadListMethods(object) {
|
|||
return YAHOO.util.Selector.query('.rightpanellayout div')[0];
|
||||
}
|
||||
|
||||
|
||||
function timetrackergap() {
|
||||
return YAHOO.util.Selector.query('.timetrackergap')[0];
|
||||
}
|
||||
|
|
@ -56,6 +55,9 @@ function addResourcesLoadListMethods(object) {
|
|||
return YAHOO.util.Selector.query('.leftpanelgap .z-tree-body')[0];
|
||||
}
|
||||
|
||||
function rightpanel() {
|
||||
return YAHOO.util.Selector.query('.rightpanellayout div')[0];
|
||||
}
|
||||
|
||||
object.init = function(cmp) {
|
||||
this.adjustTimeTrackerSize(cmp);
|
||||
|
|
@ -73,16 +75,16 @@ function addResourcesLoadListMethods(object) {
|
|||
var scrolledpannel_ = scrolledpannel();
|
||||
var resourcesloadgraph_ = resourcesloadgraph();
|
||||
var leftpanel_ = leftpanel();
|
||||
var rightpanel_ = rightpanel();
|
||||
|
||||
var onScroll = function() {
|
||||
timetrackergap_.style["left"] = "-" + scrolledpannel_.scrollLeft + "px";
|
||||
var timeplotcontainer_ = YAHOO.util.Selector.query('canvas.timeplot-canvas')[0];
|
||||
timeplotcontainer_.style["left"] = "-" + scrolledpannel_.scrollLeft + "px";
|
||||
leftpanel_.style["top"] = "-" + scrolledpannel_.scrollTop + "px";
|
||||
resourcesloadgraph_.scrollLeft = scrolledpannel_.scrollLeft;
|
||||
|
||||
};
|
||||
|
||||
YAHOO.util.Selector.query('.rightpanellayout div')[0].onscroll = onScroll;
|
||||
|
||||
rightpanel_.onscroll = onScroll;
|
||||
}
|
||||
|
||||
object.adjustTimeTrackerSize = function(cmp) {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,15 @@ public class ResourceCalendar extends BaseCalendar {
|
|||
addNewCalendarAvailability(calendarAvailability);
|
||||
}
|
||||
|
||||
public Integer getCapacity(LocalDate from, LocalDate to) {
|
||||
Integer result = getCapacityAt(to);
|
||||
for (LocalDate date = from; date.isBefore(to);) {
|
||||
result += getCapacityAt(date);
|
||||
date = date.plusDays(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getCapacityAt(LocalDate date) {
|
||||
if (!isActive(date)) {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ public class Configuration extends BaseEntity {
|
|||
|
||||
private Boolean expandOrderPlanningViewCharts = true;
|
||||
|
||||
private Boolean expandResourceLoadViewCharts = true;
|
||||
|
||||
public void setDefaultCalendar(BaseCalendar defaultCalendar) {
|
||||
this.defaultCalendar = defaultCalendar;
|
||||
}
|
||||
|
|
@ -165,4 +167,13 @@ public class Configuration extends BaseEntity {
|
|||
return expandOrderPlanningViewCharts;
|
||||
}
|
||||
|
||||
public void setExpandResourceLoadViewCharts(
|
||||
Boolean expandResourceLoadViewCharts) {
|
||||
this.expandResourceLoadViewCharts = expandResourceLoadViewCharts;
|
||||
}
|
||||
|
||||
public Boolean isExpandResourceLoadViewCharts() {
|
||||
return expandResourceLoadViewCharts;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -22,14 +22,19 @@ package org.navalplanner.business.planner.daos;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.daos.GenericDAOHibernate;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.DerivedDayAssignment;
|
||||
import org.navalplanner.business.planner.entities.GenericDayAssignment;
|
||||
import org.navalplanner.business.planner.entities.SpecificDayAssignment;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.scenarios.entities.Scenario;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
|
@ -57,34 +62,100 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
|
|||
@Override
|
||||
public List<DayAssignment> getAllFor(Scenario scenario) {
|
||||
List<DayAssignment> result = new ArrayList<DayAssignment>();
|
||||
result.addAll(getSpecific(scenario));
|
||||
result.addAll(getGeneric(scenario));
|
||||
result.addAll(getDerived(scenario));
|
||||
result.addAll(getSpecific(scenario, null, null));
|
||||
result.addAll(getGeneric(scenario, null, null));
|
||||
result.addAll(getDerived(scenario, null, null));
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<DerivedDayAssignment> getDerived(Scenario scenario) {
|
||||
public List<DayAssignment> getAllFor(Scenario scenario, LocalDate init,
|
||||
LocalDate end) {
|
||||
List<DayAssignment> result = new ArrayList<DayAssignment>();
|
||||
result.addAll(getSpecific(scenario, init, end));
|
||||
result.addAll(getGeneric(scenario, init, end));
|
||||
result.addAll(getDerived(scenario, init, end));
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<DerivedDayAssignment> getDerived(Scenario scenario,
|
||||
LocalDate initInclusive, LocalDate endInclusive) {
|
||||
String queryString = "select d from DerivedDayAssignmentsContainer c "
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario";
|
||||
Query query = getSession().createQuery(queryString)
|
||||
.setParameter("scenario", scenario);
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
|
||||
+ addQueryConditionForInitAndEndDate(initInclusive,
|
||||
endInclusive);
|
||||
Query query = getSession().createQuery(queryString);
|
||||
query = query.setParameter("scenario", scenario);
|
||||
addInitAndEndParameters(query, initInclusive, endInclusive);
|
||||
return query.list();
|
||||
}
|
||||
|
||||
private List<GenericDayAssignment> getGeneric(Scenario scenario) {
|
||||
private String addQueryConditionForInitAndEndDate(LocalDate initInclusive,
|
||||
LocalDate endInclusive) {
|
||||
String initCondition = initInclusive != null ? " and d.day >= :init"
|
||||
: "";
|
||||
String endCondition = endInclusive != null ? " and d.day <= :end" : "";
|
||||
return initCondition + endCondition;
|
||||
}
|
||||
|
||||
private Query addInitAndEndParameters(Query query, LocalDate initInclusive,
|
||||
LocalDate endInclusive) {
|
||||
if (initInclusive != null) {
|
||||
query.setParameter("init", initInclusive);
|
||||
}
|
||||
if (endInclusive != null) {
|
||||
query.setParameter("end", endInclusive);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
private List<GenericDayAssignment> getGeneric(Scenario scenario,
|
||||
LocalDate initInclusive, LocalDate endInclusive) {
|
||||
String queryString = "select d from GenericDayAssignmentsContainer c "
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario";
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
|
||||
+ addQueryConditionForInitAndEndDate(initInclusive,
|
||||
endInclusive);
|
||||
Query query = getSession().createQuery(queryString).setParameter(
|
||||
"scenario", scenario);
|
||||
query = addInitAndEndParameters(query, initInclusive, endInclusive);
|
||||
return query.list();
|
||||
}
|
||||
|
||||
private List<SpecificDayAssignment> getSpecific(Scenario scenario) {
|
||||
private List<SpecificDayAssignment> getSpecific(Scenario scenario,
|
||||
LocalDate initInclusive, LocalDate endInclusive) {
|
||||
String queryString = "select d from SpecificDayAssignmentsContainer c "
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario";
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
|
||||
+ addQueryConditionForInitAndEndDate(initInclusive,
|
||||
endInclusive);
|
||||
Query query = getSession().createQuery(queryString).setParameter(
|
||||
"scenario", scenario);
|
||||
query = addInitAndEndParameters(query, initInclusive, endInclusive);
|
||||
return query.list();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<DayAssignment> listFilteredByDate(LocalDate init, LocalDate end) {
|
||||
Criteria criteria = getSession().createCriteria(DayAssignment.class);
|
||||
addDateRestrictionsToDayAssignmentQuery(criteria, init, end);
|
||||
return criteria.list();
|
||||
}
|
||||
|
||||
private void addDateRestrictionsToDayAssignmentQuery(Criteria criteria,
|
||||
LocalDate init, LocalDate end) {
|
||||
if(init != null) {
|
||||
criteria.add(Restrictions.ge("day", init));
|
||||
}
|
||||
if(end != null) {
|
||||
criteria.add(Restrictions.le("day", end));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DayAssignment> findByResources(List<Resource> resources) {
|
||||
if (resources.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return getSession().createCriteria(DayAssignment.class).add(
|
||||
Restrictions.in("resource", resources)).list();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.common.daos.GenericDAOHibernate;
|
||||
import org.navalplanner.business.planner.entities.Dependency;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueDependency;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* DAO for entity @{link Dedenpency}
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*
|
||||
*/
|
||||
|
||||
@Repository
|
||||
@Scope(BeanDefinition.SCOPE_SINGLETON)
|
||||
public class DependencyDAO extends GenericDAOHibernate<Dependency,Long>
|
||||
implements IDependencyDAO {
|
||||
|
||||
}
|
||||
|
|
@ -23,9 +23,11 @@ package org.navalplanner.business.planner.daos;
|
|||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.daos.IGenericDAO;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.DerivedDayAssignment;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.scenarios.entities.Scenario;
|
||||
|
||||
/**
|
||||
|
|
@ -34,12 +36,18 @@ import org.navalplanner.business.scenarios.entities.Scenario;
|
|||
* @author @author Diego Pino García <dpino@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
public interface IDayAssignmentDAO extends
|
||||
IGenericDAO<DayAssignment, Long> {
|
||||
public interface IDayAssignmentDAO extends IGenericDAO<DayAssignment, Long> {
|
||||
|
||||
public void removeDerived(
|
||||
Collection<? extends DerivedDayAssignment> derivedAllocations);
|
||||
|
||||
public List<DayAssignment> getAllFor(Scenario scenario);
|
||||
|
||||
public List<DayAssignment> getAllFor(Scenario scenario,
|
||||
LocalDate initInclusive, LocalDate endInclusive);
|
||||
|
||||
List<DayAssignment> listFilteredByDate(LocalDate init, LocalDate end);
|
||||
|
||||
public List<DayAssignment> findByResources(List<Resource> resources);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.common.daos.IGenericDAO;
|
||||
import org.navalplanner.business.planner.entities.Dependency;
|
||||
|
||||
/**
|
||||
* Interface for interface for repositories related with @{link Dependency}
|
||||
* entity
|
||||
*
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*
|
||||
*/
|
||||
public interface IDependencyDAO extends IGenericDAO<Dependency,Long> {
|
||||
|
||||
}
|
||||
|
|
@ -20,8 +20,11 @@
|
|||
|
||||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.common.daos.IGenericDAO;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
|
||||
/**
|
||||
* DAO interface for {@link ILimitingResourceQueueDAO}
|
||||
|
|
@ -31,4 +34,8 @@ import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
|||
public interface ILimitingResourceQueueDAO extends
|
||||
IGenericDAO<LimitingResourceQueue, Long> {
|
||||
|
||||
LimitingResourceQueue findQueueByResource(Resource resource);
|
||||
|
||||
List<LimitingResourceQueue> getAll();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.common.daos.IGenericDAO;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueDependency;
|
||||
|
||||
/**
|
||||
* Interface for repositories to implement queies related to
|
||||
* @{link LimitingResourceQueueDependency} entities
|
||||
*
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*
|
||||
*/
|
||||
public interface ILimitingResourceQueueDependencyDAO extends
|
||||
IGenericDAO<LimitingResourceQueueDependency,Long> {
|
||||
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -44,10 +45,19 @@ public interface IResourceAllocationDAO extends
|
|||
List<ResourceAllocation<?>> findAllocationsRelatedToAnyOf(
|
||||
List<Resource> resources);
|
||||
|
||||
List<ResourceAllocation<?>> findAllocationsRelatedToAnyOf(
|
||||
List<Resource> resources, Date intervalFilterStartDate, Date intervalFilterEndDate);
|
||||
|
||||
List<ResourceAllocation<?>> findAllocationsRelatedTo(Resource resource);
|
||||
|
||||
List<ResourceAllocation<?>> findAllocationsRelatedTo(Resource resource,
|
||||
Date intervalFilterStartDate, Date intervalFilterEndDate);
|
||||
|
||||
Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsByCriterion();
|
||||
|
||||
Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsByCriterion(
|
||||
Date intervalFilterStartDate, Date intervalFilterEndDate);
|
||||
|
||||
List<SpecificDayAssignment> getSpecificAssignmentsBetween(
|
||||
Collection<Resource> relatedToOne,
|
||||
LocalDate start, LocalDate end);
|
||||
|
|
@ -57,4 +67,9 @@ public interface IResourceAllocationDAO extends
|
|||
|
||||
Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsBySomeCriterion(
|
||||
List<Criterion> criterions);
|
||||
|
||||
Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsBySomeCriterion(
|
||||
List<Criterion> criterions, Date intervalFilterStartDate,
|
||||
Date intervalFilterEndDate);
|
||||
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
|
@ -43,4 +44,6 @@ public interface ITaskElementDAO extends IGenericDAO<TaskElement, Long> {
|
|||
List<CompletedEstimatedHoursPerTaskDTO> getCompletedEstimatedHoursPerTaskReport(
|
||||
Order order, LocalDate deadline);
|
||||
|
||||
List<TaskElement> listFilteredByDate(Date start, Date end);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,12 @@
|
|||
|
||||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.navalplanner.business.common.daos.GenericDAOHibernate;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
|
@ -37,4 +41,15 @@ public class LimitingResourceQueueDAO extends
|
|||
GenericDAOHibernate<LimitingResourceQueue, Long> implements
|
||||
ILimitingResourceQueueDAO {
|
||||
|
||||
public LimitingResourceQueue findQueueByResource(Resource resource) {
|
||||
return (LimitingResourceQueue) getSession().createCriteria(
|
||||
LimitingResourceQueue.class).add(
|
||||
Restrictions.eq("resource", resource)).uniqueResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LimitingResourceQueue> getAll() {
|
||||
return list(LimitingResourceQueue.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.common.daos.GenericDAOHibernate;
|
||||
import org.navalplanner.business.planner.entities.Dependency;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueDependency;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/*
|
||||
* DAO for the entity @{link LimitingResourceQueueDependency}
|
||||
*
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*/
|
||||
|
||||
@Repository
|
||||
@Scope(BeanDefinition.SCOPE_SINGLETON)
|
||||
public class LimitingResourceQueueDependencyDAO
|
||||
extends GenericDAOHibernate<LimitingResourceQueueDependency, Long>
|
||||
implements ILimitingResourceQueueDependencyDAO {
|
||||
|
||||
}
|
||||
|
|
@ -23,12 +23,14 @@ package org.navalplanner.business.planner.daos;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.daos.GenericDAOHibernate;
|
||||
|
|
@ -57,28 +59,64 @@ public class ResourceAllocationDAO extends
|
|||
public List<ResourceAllocation<?>> findAllocationsRelatedToAnyOf(
|
||||
List<Resource> resources) {
|
||||
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
|
||||
result.addAll(findSpecificAllocationsRelatedTo(resources));
|
||||
result.addAll(findGenericAllocationsFor(resources));
|
||||
result.addAll(findSpecificAllocationsRelatedTo(resources, null, null));
|
||||
result.addAll(findGenericAllocationsFor(resources, null, null));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourceAllocation<?>> findAllocationsRelatedToAnyOf(
|
||||
List<Resource> resources, Date intervalFilterStartDate, Date intervalFilterEndDate) {
|
||||
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();
|
||||
result.addAll(findSpecificAllocationsRelatedTo(resources, intervalFilterStartDate, intervalFilterEndDate));
|
||||
result.addAll(findGenericAllocationsFor(resources, intervalFilterStartDate, intervalFilterEndDate));
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<GenericResourceAllocation> findGenericAllocationsFor(
|
||||
List<Resource> resources) {
|
||||
return (List<GenericResourceAllocation>) getSession().createCriteria(
|
||||
GenericResourceAllocation.class).setResultTransformer(
|
||||
Criteria.DISTINCT_ROOT_ENTITY).createCriteria(
|
||||
private List<GenericResourceAllocation> findGenericAllocationsFor(List<Resource> resources, Date intervalFilterStartDate, Date intervalFilterEndDate) {
|
||||
if(resources.isEmpty()) {
|
||||
return new ArrayList<GenericResourceAllocation>();
|
||||
}
|
||||
Criteria criteria = getSession().createCriteria(GenericResourceAllocation.class);
|
||||
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
|
||||
.createCriteria(
|
||||
"genericDayAssignmentsContainers").createCriteria(
|
||||
"dayAssignments").add(
|
||||
Restrictions.in("resource", resources)).list();
|
||||
Restrictions.in("resource", resources));
|
||||
|
||||
if(intervalFilterStartDate != null || intervalFilterEndDate != null) {
|
||||
Criteria dateCriteria = criteria.createCriteria("task");
|
||||
if(intervalFilterEndDate != null) {
|
||||
dateCriteria.add(Restrictions.le("startDate", intervalFilterEndDate));
|
||||
}
|
||||
if(intervalFilterStartDate != null) {
|
||||
dateCriteria.add(Restrictions.ge("endDate", intervalFilterStartDate));
|
||||
}
|
||||
}
|
||||
return (List<GenericResourceAllocation>) criteria.list();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<SpecificResourceAllocation> findSpecificAllocationsRelatedTo(
|
||||
List<Resource> resources) {
|
||||
return (List<SpecificResourceAllocation>) getSession().createCriteria(
|
||||
SpecificResourceAllocation.class).add(
|
||||
Restrictions.in("resource", resources)).list();
|
||||
List<Resource> resources, Date intervalFilterStartDate, Date intervalFilterEndDate) {
|
||||
if(resources.isEmpty()) {
|
||||
return new ArrayList<SpecificResourceAllocation>();
|
||||
}
|
||||
Criteria criteria = getSession().createCriteria(
|
||||
SpecificResourceAllocation.class);
|
||||
criteria.add(Restrictions.in("resource", resources));
|
||||
|
||||
if(intervalFilterStartDate != null || intervalFilterEndDate != null) {
|
||||
Criteria dateCriteria = criteria.createCriteria("task");
|
||||
if(intervalFilterEndDate != null) {
|
||||
dateCriteria.add(Restrictions.le("startDate", intervalFilterEndDate));
|
||||
}
|
||||
if(intervalFilterStartDate != null) {
|
||||
dateCriteria.add(Restrictions.ge("endDate", intervalFilterStartDate));
|
||||
}
|
||||
}
|
||||
return (List<SpecificResourceAllocation>) criteria.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -88,6 +126,13 @@ public class ResourceAllocationDAO extends
|
|||
.asList(resource)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourceAllocation<?>> findAllocationsRelatedTo(
|
||||
Resource resource, Date intervalFilterStartDate, Date intervalFilterEndDate) {
|
||||
return stripAllocationsWithoutAssignations(findAllocationsRelatedToAnyOf(Arrays
|
||||
.asList(resource), intervalFilterStartDate, intervalFilterEndDate));
|
||||
}
|
||||
|
||||
private <R extends ResourceAllocation<?>> List<R> stripAllocationsWithoutAssignations(
|
||||
List<R> allocations) {
|
||||
List<R> result = new ArrayList<R>();
|
||||
|
|
@ -124,6 +169,38 @@ public class ResourceAllocationDAO extends
|
|||
return stripAllocationsWithoutAssignations(byCriterion(results));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsByCriterion(
|
||||
Date intervalFilterStartDate, Date intervalFilterEndDate) {
|
||||
String query = "select generic, criterion "
|
||||
+ "from GenericResourceAllocation as generic "
|
||||
+ "join generic.criterions as criterion ";
|
||||
if(intervalFilterStartDate != null || intervalFilterEndDate != null) {
|
||||
query += "inner join generic.task as task ";
|
||||
if(intervalFilterEndDate != null) {
|
||||
query += "where task.startDate <= :intervalFilterEndDate ";
|
||||
}
|
||||
if(intervalFilterStartDate != null) {
|
||||
if(intervalFilterEndDate != null) {
|
||||
query += "and ";
|
||||
}
|
||||
else {
|
||||
query += "where ";
|
||||
}
|
||||
query += "task.endDate >= :intervalFilterStartDate ";
|
||||
}
|
||||
}
|
||||
Query q = getSession().createQuery(query);
|
||||
if(intervalFilterStartDate != null) {
|
||||
q.setParameter("intervalFilterStartDate", intervalFilterStartDate);
|
||||
}
|
||||
if(intervalFilterEndDate != null) {
|
||||
q.setParameter("intervalFilterEndDate", intervalFilterEndDate);
|
||||
}
|
||||
return stripAllocationsWithoutAssignations(byCriterion(q.list()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsByCriterionFor(
|
||||
|
|
@ -156,6 +233,38 @@ public class ResourceAllocationDAO extends
|
|||
return stripAllocationsWithoutAssignations(byCriterion(list));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsBySomeCriterion(
|
||||
List<Criterion> criterions, Date intervalFilterStartDate, Date intervalFilterEndDate) {
|
||||
if (criterions.isEmpty()) {
|
||||
return new HashMap<Criterion, List<GenericResourceAllocation>>();
|
||||
}
|
||||
String query = "select generic, criterion "
|
||||
+ "from GenericResourceAllocation as generic "
|
||||
+ "join generic.criterions as criterion ";
|
||||
if(intervalFilterStartDate != null || intervalFilterEndDate != null) {
|
||||
query += "inner join generic.task as task ";
|
||||
}
|
||||
query += "where criterion in(:criterions) ";
|
||||
if(intervalFilterEndDate != null) {
|
||||
query += "and task.startDate <= :intervalFilterEndDate ";
|
||||
}
|
||||
if(intervalFilterStartDate != null) {
|
||||
query += "and task.endDate >= :intervalFilterStartDate ";
|
||||
}
|
||||
|
||||
Query q = getSession().createQuery(query);
|
||||
q.setParameterList("criterions", criterions);
|
||||
if(intervalFilterStartDate != null) {
|
||||
q.setParameter("intervalFilterStartDate", intervalFilterStartDate);
|
||||
}
|
||||
if(intervalFilterEndDate != null) {
|
||||
q.setParameter("intervalFilterEndDate", intervalFilterEndDate);
|
||||
}
|
||||
return stripAllocationsWithoutAssignations(byCriterion(q.list()));
|
||||
}
|
||||
|
||||
private Map<Criterion, List<GenericResourceAllocation>> byCriterion(
|
||||
List<Object> results) {
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,10 @@
|
|||
package org.navalplanner.business.planner.daos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.joda.time.LocalDate;
|
||||
|
|
@ -150,4 +152,17 @@ public class TaskElementDAO extends GenericDAOHibernate<TaskElement, Long>
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<TaskElement> listFilteredByDate(Date start, Date end) {
|
||||
Criteria criteria = getSession().createCriteria(TaskElement.class);
|
||||
if(start != null) {
|
||||
criteria.add(Restrictions.ge("endDate", start));
|
||||
}
|
||||
if(end != null) {
|
||||
criteria.add(Restrictions.le("startDate", end));
|
||||
}
|
||||
return criteria.list();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* 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.planner.entities;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Diego Pino Garcia <dpino@igalia.com>
|
||||
*
|
||||
*/
|
||||
public class DateAndHour implements Comparable<DateAndHour> {
|
||||
|
||||
private LocalDate date;
|
||||
|
||||
private Integer hour;
|
||||
|
||||
public DateAndHour(LocalDate date, Integer hour) {
|
||||
this.date = date;
|
||||
this.hour = hour;
|
||||
}
|
||||
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public Integer getHour() {
|
||||
return hour;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(DateAndHour dateAndTime) {
|
||||
int compareDate = date.compareTo(getDate(dateAndTime));
|
||||
return (compareDate != 0) ? compareDate : compareHour(dateAndTime
|
||||
.getHour());
|
||||
}
|
||||
|
||||
private LocalDate getDate(DateAndHour dateAndHour) {
|
||||
return (dateAndHour != null) ? dateAndHour.getDate() : null;
|
||||
}
|
||||
|
||||
private int compareHour(int hour) {
|
||||
int deltaHour = this.hour - hour;
|
||||
return (deltaHour != 0) ? deltaHour / Math.abs(deltaHour) : 0;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return date + "; " + hour;
|
||||
}
|
||||
|
||||
public static DateAndHour Max(DateAndHour arg0, DateAndHour arg1) {
|
||||
if (arg0 == null) {
|
||||
return arg1;
|
||||
}
|
||||
if (arg1 == null) {
|
||||
return arg0;
|
||||
}
|
||||
return (arg0.compareTo(arg1) > 0) ? arg0 : arg1;
|
||||
}
|
||||
|
||||
public boolean isBefore(DateAndHour dateAndHour) {
|
||||
return (this.compareTo(dateAndHour) < 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -24,7 +24,11 @@ import org.apache.commons.lang.Validate;
|
|||
import org.navalplanner.business.common.BaseEntity;
|
||||
|
||||
/**
|
||||
* Entity which represents an associated with properties
|
||||
* between two @{link Task}
|
||||
*
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*/
|
||||
public class Dependency extends BaseEntity {
|
||||
|
||||
|
|
@ -45,6 +49,8 @@ public class Dependency extends BaseEntity {
|
|||
|
||||
private TaskElement destination;
|
||||
|
||||
private LimitingResourceQueueDependency queueDependency;
|
||||
|
||||
private Type type;
|
||||
|
||||
/**
|
||||
|
|
@ -76,4 +82,20 @@ public class Dependency extends BaseEntity {
|
|||
return type;
|
||||
}
|
||||
|
||||
public void setQueueDependency(LimitingResourceQueueDependency queueDependency) {
|
||||
this.queueDependency = queueDependency;
|
||||
}
|
||||
|
||||
public LimitingResourceQueueDependency getQueueDependency() {
|
||||
return queueDependency;
|
||||
}
|
||||
|
||||
public boolean isDependencyBetweenLimitedAllocatedTasks() {
|
||||
return getOrigin().hasLimitedResourceAllocation() &&
|
||||
getDestination().hasLimitedResourceAllocation();
|
||||
}
|
||||
|
||||
public boolean hasLimitedQueueDependencyAssociated() {
|
||||
return queueDependency != null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -397,6 +397,25 @@ public class GenericResourceAllocation extends
|
|||
return assignmentsState;
|
||||
}
|
||||
|
||||
private List<GenericDayAssignment> getDayAssignmentsByConsolidated(
|
||||
boolean consolidated) {
|
||||
List<GenericDayAssignment> result = new ArrayList<GenericDayAssignment>();
|
||||
for (GenericDayAssignment day : getAssignments()) {
|
||||
if (day.isConsolidated() == consolidated) {
|
||||
result.add(day);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<GenericDayAssignment> getNonConsolidatedAssignments() {
|
||||
return getDayAssignmentsByConsolidated(false);
|
||||
}
|
||||
|
||||
public List<GenericDayAssignment> getConsolidatedAssignments() {
|
||||
return getDayAssignmentsByConsolidated(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<GenericDayAssignment> getDayAssignmentType() {
|
||||
return GenericDayAssignment.class;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@ public class HoursCostCalculator implements ICostCalculator {
|
|||
|
||||
@Override
|
||||
public SortedMap<LocalDate, BigDecimal> getAdvanceCost(Task task) {
|
||||
return getAdvanceCost(task, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedMap<LocalDate, BigDecimal> getAdvanceCost(Task task,
|
||||
LocalDate filterStartDate, LocalDate filterEndDate) {
|
||||
DirectAdvanceAssignment advanceAssignment = task.getOrderElement()
|
||||
.getReportGlobalAdvanceAssignment();
|
||||
|
||||
|
|
@ -59,19 +65,25 @@ public class HoursCostCalculator implements ICostCalculator {
|
|||
}
|
||||
|
||||
return calculateHoursPerDay(task.getHoursSpecifiedAtOrder(),
|
||||
advanceAssignment.getAdvanceMeasurements());
|
||||
advanceAssignment.getAdvanceMeasurements(),
|
||||
filterStartDate, filterEndDate);
|
||||
}
|
||||
|
||||
private SortedMap<LocalDate, BigDecimal> calculateHoursPerDay(
|
||||
Integer totalHours,
|
||||
SortedSet<AdvanceMeasurement> advanceMeasurements) {
|
||||
SortedSet<AdvanceMeasurement> advanceMeasurements,
|
||||
LocalDate filterStartDate, LocalDate filterEndDate) {
|
||||
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
|
||||
|
||||
for (AdvanceMeasurement advanceMeasurement : advanceMeasurements) {
|
||||
BigDecimal cost = advanceMeasurement.getValue().setScale(2)
|
||||
.multiply(new BigDecimal(totalHours)).divide(
|
||||
new BigDecimal(100));
|
||||
result.put(advanceMeasurement.getDate(), cost);
|
||||
LocalDate day = advanceMeasurement.getDate();
|
||||
if(((filterStartDate == null) || day.compareTo(filterStartDate) >= 0) &&
|
||||
((filterEndDate == null) || day.compareTo(filterEndDate) <= 0)) {
|
||||
BigDecimal cost = advanceMeasurement.getValue().setScale(2)
|
||||
.multiply(new BigDecimal(totalHours)).divide(
|
||||
new BigDecimal(100));
|
||||
result.put(day, cost);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -79,6 +91,12 @@ public class HoursCostCalculator implements ICostCalculator {
|
|||
|
||||
@Override
|
||||
public SortedMap<LocalDate, BigDecimal> getEstimatedCost(Task task) {
|
||||
return getEstimatedCost(task, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedMap<LocalDate, BigDecimal> getEstimatedCost(Task task,
|
||||
LocalDate filterStartDate, LocalDate filterEndDate) {
|
||||
if (task.isSubcontracted()) {
|
||||
return getAdvanceCost(task);
|
||||
}
|
||||
|
|
@ -93,12 +111,15 @@ public class HoursCostCalculator implements ICostCalculator {
|
|||
|
||||
for (DayAssignment dayAssignment : dayAssignments) {
|
||||
LocalDate day = dayAssignment.getDay();
|
||||
BigDecimal cost = new BigDecimal(dayAssignment.getHours());
|
||||
if(((filterStartDate == null) || day.compareTo(filterStartDate) >= 0) &&
|
||||
((filterEndDate == null) || day.compareTo(filterEndDate) <= 0)) {
|
||||
BigDecimal cost = new BigDecimal(dayAssignment.getHours());
|
||||
|
||||
if (!result.containsKey(day)) {
|
||||
result.put(day, BigDecimal.ZERO);
|
||||
if (!result.containsKey(day)) {
|
||||
result.put(day, BigDecimal.ZERO);
|
||||
}
|
||||
result.put(day, result.get(day).add(cost));
|
||||
}
|
||||
result.put(day, result.get(day).add(cost));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -38,4 +38,10 @@ public interface ICostCalculator {
|
|||
|
||||
public SortedMap<LocalDate, BigDecimal> getWorkReportCost(Task task);
|
||||
|
||||
SortedMap<LocalDate, BigDecimal> getEstimatedCost(Task task,
|
||||
LocalDate filterStartDate, LocalDate filterEndDate);
|
||||
|
||||
SortedMap<LocalDate, BigDecimal> getAdvanceCost(Task task,
|
||||
LocalDate filterStartDate, LocalDate filterEndDate);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* 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.planner.entities;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.calendars.entities.ResourceCalendar;
|
||||
import org.navalplanner.business.resources.entities.Criterion;
|
||||
import org.navalplanner.business.resources.entities.CriterionCompounder;
|
||||
import org.navalplanner.business.resources.entities.ICriterion;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
|
||||
/**
|
||||
* Handles all the logic related to allocation of
|
||||
* {@link LimitingResourceQueueElement} into {@link LimitingResourceQueue}
|
||||
*
|
||||
* The class does not do the allocation itself but provides methods:
|
||||
* <em>getFirstValidGap</em>, <em>calculateStartAndEndTime</em> or
|
||||
* <em>generateDayAssignments</em>, needed to do the allocation of
|
||||
* {@link LimitingResourceQueueElement}
|
||||
*
|
||||
* @author Diego Pino Garcia <dpino@igalia.com>
|
||||
*
|
||||
*/
|
||||
public class LimitingResourceAllocator {
|
||||
|
||||
private final static ResourcesPerDay ONE_RESOURCE_PER_DAY = ResourcesPerDay
|
||||
.amount(new BigDecimal(1));
|
||||
|
||||
/**
|
||||
* Returns first valid gap in queue for element
|
||||
*
|
||||
* Returns null if there is not a valid gap. This case can only happen on
|
||||
* trying to allocate an element related to a generic resource allocation.
|
||||
* It is possible that queue.resource does not hold element.criteria at any
|
||||
* interval of time
|
||||
*
|
||||
* @param queue search gap inside queue
|
||||
* @param element element to fit into queue
|
||||
* @return
|
||||
*/
|
||||
public static LimitingResourceQueueElementGap getFirstValidGap(LimitingResourceQueue queue,
|
||||
LimitingResourceQueueElement element) {
|
||||
|
||||
final Resource resource = queue.getResource();
|
||||
final List<LimitingResourceQueueElement> elements = new LinkedList<LimitingResourceQueueElement>(
|
||||
queue.getLimitingResourceQueueElements());
|
||||
final int size = elements.size();
|
||||
|
||||
// Iterate through queue elements
|
||||
for (int pos = 0; pos <= size; pos++) {
|
||||
|
||||
LimitingResourceQueueElementGap gap = getGapInQueueAtPosition(
|
||||
resource, elements, element, pos);
|
||||
|
||||
// The queue cannot hold this element (perhaps queue.resource
|
||||
// doesn't meet element.criteria)
|
||||
if (gap == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (canFitIntoGap(element, gap, resource)) {
|
||||
return gap;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean canFitIntoGap(LimitingResourceQueueElement element,
|
||||
LimitingResourceQueueElementGap gap, final Resource resource) {
|
||||
|
||||
final boolean canfit = gap.canFit(element);
|
||||
final ResourceAllocation<?> resourceAllocation = element
|
||||
.getResourceAllocation();
|
||||
|
||||
if (resourceAllocation instanceof SpecificResourceAllocation) {
|
||||
return canfit;
|
||||
} else if (resourceAllocation instanceof GenericResourceAllocation) {
|
||||
// Resource must satisfy element.criteria during for the
|
||||
// period of time the element will be allocated in the
|
||||
// queue
|
||||
final GenericResourceAllocation generic = (GenericResourceAllocation) resourceAllocation;
|
||||
List<DayAssignment> dayAssignments = generateDayAssignments(
|
||||
resourceAllocation, resource, gap.getStartTime());
|
||||
DateAndHour[] startAndEndTime = calculateStartAndEndTime(dayAssignments);
|
||||
return canfit
|
||||
&& (satisfiesCriteriaDuringInterval(resource, generic
|
||||
.getCriterions(), startAndEndTime));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates start and end date out of a list of day assignments.
|
||||
*
|
||||
* The first day is the day were the first day assignment happened.
|
||||
* The last day is the day were the last day assignment happened.
|
||||
* @param dayAssignments
|
||||
* @return
|
||||
*/
|
||||
public static DateAndHour[] calculateStartAndEndTime(List<DayAssignment> dayAssignments) {
|
||||
DateAndHour[] result = new DateAndHour[2];
|
||||
|
||||
final DayAssignment start = dayAssignments.get(0);
|
||||
final DayAssignment end = dayAssignments.get(dayAssignments.size() - 1);
|
||||
result[0] = new DateAndHour(start.getDay(), start.getHours());
|
||||
result[1] = new DateAndHour(end.getDay(), end.getHours());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean satisfiesCriteriaDuringInterval(Resource resource, Set<Criterion> criteria, DateAndHour[] interval) {
|
||||
final Date startDate = interval[0].getDate().toDateTimeAtStartOfDay().toDate();
|
||||
final Date endDate = interval[1].getDate().toDateTimeAtStartOfDay().toDate();
|
||||
return satisfiesCriteriaDuringInterval(resource, criteria, startDate, endDate);
|
||||
}
|
||||
|
||||
private static boolean satisfiesCriteriaDuringInterval(Resource resource, Set<Criterion> criteria, Date startDate, Date endDate) {
|
||||
ICriterion compositedCriterion = CriterionCompounder.buildAnd(criteria)
|
||||
.getResult();
|
||||
return compositedCriterion.isSatisfiedBy(resource, startDate, endDate);
|
||||
}
|
||||
|
||||
private static LimitingResourceQueueElementGap getGapInQueueAtPosition(
|
||||
Resource resource, List<LimitingResourceQueueElement> elements,
|
||||
LimitingResourceQueueElement element, int pos) {
|
||||
|
||||
final int size = elements.size();
|
||||
final DateAndHour startTimeBecauseOfGantt = getStartTimeBecauseOfGantt(element);
|
||||
|
||||
if (size > 0) {
|
||||
|
||||
if (pos == size) {
|
||||
return createLastGap(element, elements.get(size - 1), resource);
|
||||
}
|
||||
|
||||
LimitingResourceQueueElement current = elements.get(pos);
|
||||
// First element
|
||||
if (pos == 0
|
||||
&& startTimeBecauseOfGantt.getDate().isBefore(
|
||||
current.getStartDate())) {
|
||||
return LimitingResourceQueueElementGap.create(resource,
|
||||
startTimeBecauseOfGantt, current.getStartTime());
|
||||
}
|
||||
|
||||
// Rest of elements
|
||||
if (pos + 1 < size) {
|
||||
LimitingResourceQueueElement next = elements.get(pos + 1);
|
||||
if (startTimeBecauseOfGantt.isBefore(current.getEndTime())) {
|
||||
return LimitingResourceQueueElementGap.create(resource,
|
||||
current.getEndTime(), next.getStartTime());
|
||||
} else {
|
||||
return LimitingResourceQueueElementGap.create(resource,
|
||||
DateAndHour.Max(current.getEndTime(),
|
||||
startTimeBecauseOfGantt), next
|
||||
.getStartTime());
|
||||
}
|
||||
} else {
|
||||
// Current was the last element
|
||||
return createLastGap(element, current, resource);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DateAndHour getStartTimeBecauseOfGantt(LimitingResourceQueueElement element) {
|
||||
return new DateAndHour(new LocalDate(element.getEarlierStartDateBecauseOfGantt()), 0);
|
||||
}
|
||||
|
||||
private static LimitingResourceQueueElementGap createLastGap(
|
||||
LimitingResourceQueueElement candidate,
|
||||
LimitingResourceQueueElement element, Resource resource) {
|
||||
|
||||
DateAndHour startTime = DateAndHour.Max(
|
||||
getStartTimeBecauseOfGantt(candidate), element.getEndTime());
|
||||
return LimitingResourceQueueElementGap
|
||||
.create(resource, startTime, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a list of {@link DayAssignment} for {@link Resource} starting
|
||||
* from startTime
|
||||
*
|
||||
* The returned list is not associated to resouceAllocation.
|
||||
*
|
||||
* resourceAllocation is passed to know if the list of day assignments
|
||||
* should be {@link GenericDayAssignment} or {@link SpecificDayAssignment}
|
||||
*
|
||||
* @param resourceAllocation
|
||||
* @param resource
|
||||
* @param startTime
|
||||
* @return
|
||||
*/
|
||||
public static List<DayAssignment> generateDayAssignments(
|
||||
ResourceAllocation<?> resourceAllocation,
|
||||
Resource resource,
|
||||
DateAndHour startTime) {
|
||||
|
||||
List<DayAssignment> assignments = new ArrayList<DayAssignment>();
|
||||
|
||||
LocalDate date = startTime.getDate();
|
||||
int totalHours = resourceAllocation.getIntendedTotalHours();
|
||||
|
||||
// Generate first day assignment
|
||||
int hoursCanAllocate = hoursCanWorkOnDay(resource, date, startTime.getHour());
|
||||
if (hoursCanAllocate > 0) {
|
||||
int hoursToAllocate = Math.min(totalHours, hoursCanAllocate);
|
||||
DayAssignment dayAssignment = createDayAssignment(resourceAllocation, resource, date, hoursToAllocate);
|
||||
totalHours -= addDayAssignment(assignments, dayAssignment);
|
||||
}
|
||||
|
||||
// Generate rest of day assignments
|
||||
for (date = date.plusDays(1); totalHours > 0; date = date.plusDays(1)) {
|
||||
totalHours -= addDayAssignment(assignments, generateDayAssignment(
|
||||
resourceAllocation, resource, date, totalHours));
|
||||
}
|
||||
return assignments;
|
||||
}
|
||||
|
||||
private static DayAssignment createDayAssignment(ResourceAllocation<?> resourceAllocation,
|
||||
Resource resource, LocalDate date, int hoursToAllocate) {
|
||||
if (resourceAllocation instanceof SpecificResourceAllocation) {
|
||||
return SpecificDayAssignment.create(date, hoursToAllocate, resource);
|
||||
} else if (resourceAllocation instanceof GenericResourceAllocation) {
|
||||
return GenericDayAssignment.create(date, hoursToAllocate, resource);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int addDayAssignment(List<DayAssignment> list, DayAssignment dayAssignment) {
|
||||
if (dayAssignment != null) {
|
||||
list.add(dayAssignment);
|
||||
return dayAssignment.getHours();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int hoursCanWorkOnDay(final Resource resource,
|
||||
final LocalDate date, int alreadyWorked) {
|
||||
final ResourceCalendar calendar = resource.getCalendar();
|
||||
int hoursCanAllocate = calendar.toHours(date, ONE_RESOURCE_PER_DAY);
|
||||
return hoursCanAllocate - alreadyWorked;
|
||||
}
|
||||
|
||||
private static DayAssignment generateDayAssignment(
|
||||
final ResourceAllocation<?> resourceAllocation,
|
||||
Resource resource,
|
||||
final LocalDate date, int intentedHours) {
|
||||
|
||||
final ResourceCalendar calendar = resource.getCalendar();
|
||||
|
||||
int hoursCanAllocate = calendar.toHours(date, ONE_RESOURCE_PER_DAY);
|
||||
if (hoursCanAllocate > 0) {
|
||||
int hoursToAllocate = Math.min(intentedHours, hoursCanAllocate);
|
||||
return createDayAssignment(resourceAllocation, resource, date, hoursToAllocate);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
package org.navalplanner.business.planner.entities;
|
||||
|
||||
import static org.navalplanner.business.i18n.I18nHelper._;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
|
||||
|
||||
/**
|
||||
* Entity which represents the relationships between two
|
||||
* @{link LimitingResourceQueueElement}. One of the
|
||||
* @{link LimitingResourceQueueElement} is the origin of the relationship
|
||||
* and the other is the destiny of the relationship.
|
||||
*
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*
|
||||
*/
|
||||
public class LimitingResourceQueueDependency extends BaseEntity {
|
||||
|
||||
public static enum QueueDependencyType {
|
||||
START_START, END_START, END_END, START_END
|
||||
};
|
||||
|
||||
private static
|
||||
EnumMap<Dependency.Type,
|
||||
LimitingResourceQueueDependency.QueueDependencyType> translationMap;
|
||||
|
||||
static {
|
||||
translationMap = new EnumMap<Dependency.Type,
|
||||
LimitingResourceQueueDependency.
|
||||
QueueDependencyType>(Dependency.Type.class);
|
||||
translationMap.put(Dependency.Type.START_START,
|
||||
QueueDependencyType.START_START);
|
||||
translationMap.put(Dependency.Type.START_END,
|
||||
QueueDependencyType.START_END);
|
||||
translationMap.put(Dependency.Type.END_START,
|
||||
QueueDependencyType.END_START);
|
||||
translationMap.put(Dependency.Type.END_END,
|
||||
QueueDependencyType.END_END);
|
||||
}
|
||||
|
||||
private LimitingResourceQueueElement hasAsOrigin;
|
||||
private LimitingResourceQueueElement hasAsDestiny;
|
||||
private Dependency ganttDependency;
|
||||
private QueueDependencyType type;
|
||||
|
||||
public static LimitingResourceQueueDependency create(
|
||||
LimitingResourceQueueElement origin,
|
||||
LimitingResourceQueueElement destiny,
|
||||
Dependency ganttDependency,
|
||||
QueueDependencyType type) {
|
||||
LimitingResourceQueueDependency dependency = new
|
||||
LimitingResourceQueueDependency(origin,destiny,ganttDependency,type);
|
||||
dependency.setNewObject(true);
|
||||
origin.add(dependency);
|
||||
destiny.add(dependency);
|
||||
ganttDependency.setQueueDependency(dependency);
|
||||
return dependency;
|
||||
}
|
||||
|
||||
public static LimitingResourceQueueDependency.QueueDependencyType
|
||||
convertFromTypeToQueueDepedencyType(Dependency.Type type) {
|
||||
return translationMap.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contructor for Hibernate. Do not use !
|
||||
*/
|
||||
public LimitingResourceQueueDependency() {}
|
||||
|
||||
private LimitingResourceQueueDependency(LimitingResourceQueueElement origin,
|
||||
LimitingResourceQueueElement destiny,
|
||||
Dependency ganttDependency,
|
||||
QueueDependencyType type) {
|
||||
Validate.notNull(origin);
|
||||
Validate.notNull(destiny);
|
||||
Validate.notNull(ganttDependency);
|
||||
Validate.isTrue(!origin.equals(destiny), _("A queue dependency has to " +
|
||||
"have an origin different from destiny"));
|
||||
this.hasAsOrigin = origin;
|
||||
this.hasAsDestiny = destiny;
|
||||
this.ganttDependency = ganttDependency;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public LimitingResourceQueueElement getHasAsOrigin() {
|
||||
return hasAsOrigin;
|
||||
}
|
||||
|
||||
public LimitingResourceQueueElement getHasAsDestiny() {
|
||||
return hasAsDestiny;
|
||||
}
|
||||
|
||||
public QueueDependencyType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Dependency getGanttDependency() {
|
||||
return ganttDependency;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,16 +20,24 @@
|
|||
|
||||
package org.navalplanner.business.planner.entities;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Diego Pino Garcia <dpino@igalia.com>
|
||||
* Entity which represents an element in the queue which represents
|
||||
* the limiting resources.
|
||||
*
|
||||
* @author Diego Pino Garcia <dpino@igalia.com>
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*/
|
||||
public class LimitingResourceQueueElement extends BaseEntity {
|
||||
|
||||
|
|
@ -45,12 +53,22 @@ public class LimitingResourceQueueElement extends BaseEntity {
|
|||
|
||||
private long creationTimestamp;
|
||||
|
||||
private Set<LimitingResourceQueueDependency> dependenciesAsOrigin =
|
||||
new HashSet<LimitingResourceQueueDependency>();
|
||||
|
||||
private Set<LimitingResourceQueueDependency> dependenciesAsDestiny =
|
||||
new HashSet<LimitingResourceQueueDependency>();
|
||||
|
||||
public static LimitingResourceQueueElement create() {
|
||||
return create(new LimitingResourceQueueElement());
|
||||
}
|
||||
|
||||
protected LimitingResourceQueueElement() {
|
||||
creationTimestamp = (new Date()).getTime();
|
||||
startQueuePosition = new QueuePosition();
|
||||
startQueuePosition.setHour(0);
|
||||
endQueuePosition = new QueuePosition();
|
||||
endQueuePosition.setHour(0);
|
||||
}
|
||||
|
||||
public ResourceAllocation<?> getResourceAllocation() {
|
||||
|
|
@ -118,4 +136,52 @@ public class LimitingResourceQueueElement extends BaseEntity {
|
|||
this.creationTimestamp = creationTimestamp;
|
||||
}
|
||||
|
||||
public Resource getResource() {
|
||||
if (resourceAllocation instanceof SpecificResourceAllocation) {
|
||||
final SpecificResourceAllocation specific = (SpecificResourceAllocation) resourceAllocation;
|
||||
return specific.getResource();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getIntentedTotalHours() {
|
||||
return (getResourceAllocation() != null) ? getResourceAllocation()
|
||||
.getIntendedTotalHours() : null;
|
||||
}
|
||||
|
||||
public DateAndHour getStartTime() {
|
||||
return new DateAndHour(getStartDate(), getStartHour());
|
||||
}
|
||||
|
||||
public DateAndHour getEndTime() {
|
||||
return new DateAndHour(getEndDate(), getEndHour());
|
||||
}
|
||||
|
||||
public void add(LimitingResourceQueueDependency d) {
|
||||
Validate.notNull(d);
|
||||
if (d.getHasAsOrigin().equals(this)) {
|
||||
dependenciesAsOrigin.add(d);
|
||||
} else if (d.getHasAsDestiny().equals(this)) {
|
||||
dependenciesAsDestiny.add(d);
|
||||
} else {
|
||||
throw new IllegalArgumentException("It cannot be added a dependency" +
|
||||
" in which the current queue element is neither origin" +
|
||||
" not desinty");
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(LimitingResourceQueueDependency d) {
|
||||
if (dependenciesAsOrigin.contains(d))
|
||||
dependenciesAsOrigin.remove(d);
|
||||
if (dependenciesAsDestiny.contains(d))
|
||||
dependenciesAsDestiny.remove(d);
|
||||
}
|
||||
|
||||
public Set<LimitingResourceQueueDependency> getDependenciesAsOrigin() {
|
||||
return Collections.unmodifiableSet(dependenciesAsOrigin);
|
||||
}
|
||||
|
||||
public Set<LimitingResourceQueueDependency> getDependenciesAsDestiny() {
|
||||
return Collections.unmodifiableSet(dependenciesAsDestiny);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* 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.planner.entities;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.calendars.entities.ResourceCalendar;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Diego Pino Garcia <dpino@igalia.com>
|
||||
*
|
||||
*/
|
||||
public class LimitingResourceQueueElementGap implements Comparable<LimitingResourceQueueElementGap> {
|
||||
|
||||
private DateAndHour startTime;
|
||||
|
||||
private DateAndHour endTime;
|
||||
|
||||
private Integer hoursInGap;
|
||||
|
||||
public LimitingResourceQueueElementGap(Resource resource, DateAndHour startTime,
|
||||
DateAndHour endTime) {
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
hoursInGap = calculateHoursInGap(resource, startTime, endTime);
|
||||
}
|
||||
|
||||
private Integer calculateHoursInGap(Resource resource, DateAndHour startTime, DateAndHour endTime) {
|
||||
return (endTime == null) ? Integer.MAX_VALUE : calculateHoursInGap(
|
||||
resource, startTime.getDate(), startTime.getHour(), endTime
|
||||
.getDate(), endTime.getHour());
|
||||
}
|
||||
|
||||
public int getHoursInGap() {
|
||||
return hoursInGap;
|
||||
}
|
||||
|
||||
private Integer calculateHoursInGap(Resource resource, LocalDate startDate,
|
||||
int startHour, LocalDate endDate, int endHour) {
|
||||
|
||||
final ResourceCalendar calendar = resource.getCalendar();
|
||||
|
||||
if (startDate.equals(endDate)) {
|
||||
return calendar.getCapacityAt(startDate) - Math.max(startHour, endHour);
|
||||
} else {
|
||||
int hoursAtStart = calendar.getCapacityAt(startDate) - startHour;
|
||||
int hoursInBetween = calendar.getWorkableHours(startDate
|
||||
.plusDays(1), endDate.minusDays(1));
|
||||
return hoursAtStart + hoursInBetween + endHour;
|
||||
}
|
||||
}
|
||||
|
||||
public static LimitingResourceQueueElementGap create(Resource resource, DateAndHour startTime,
|
||||
DateAndHour endTime) {
|
||||
return new LimitingResourceQueueElementGap(resource, startTime, endTime);
|
||||
}
|
||||
|
||||
public DateAndHour getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public DateAndHour getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the gap starts after earlierStartDateBecauseOfGantt and
|
||||
* if it's big enough for fitting candidate
|
||||
*
|
||||
* @param hours
|
||||
* @return
|
||||
*/
|
||||
public boolean canFit(LimitingResourceQueueElement candidate) {
|
||||
final LocalDate earlierStartDateBecauseOfGantt = new LocalDate(
|
||||
candidate.getEarlierStartDateBecauseOfGantt());
|
||||
final LocalDate startDate = startTime.getDate();
|
||||
if (earlierStartDateBecauseOfGantt.isBefore(startDate)
|
||||
|| earlierStartDateBecauseOfGantt.isEqual(startDate)) {
|
||||
return hoursInGap - candidate.getIntentedTotalHours() >= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String result = startTime.getDate() + " - " + startTime.getHour();
|
||||
if (endTime != null) {
|
||||
result += "; " + endTime.getDate() + " - " + endTime.getHour();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(LimitingResourceQueueElementGap o) {
|
||||
if (o == null) {
|
||||
return 1;
|
||||
}
|
||||
return this.getStartTime().compareTo(o.getStartTime());
|
||||
}
|
||||
|
||||
public boolean isBefore(LimitingResourceQueueElementGap gap) {
|
||||
return (compareTo(gap) < 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -576,6 +576,10 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
return getLimitingResourceQueueElement() != null;
|
||||
}
|
||||
|
||||
public boolean isLimitingAndHasDayAssignments() {
|
||||
return isLimiting() && hasAssignments();
|
||||
}
|
||||
|
||||
public boolean isSatisfied() {
|
||||
return hasAssignments();
|
||||
}
|
||||
|
|
@ -594,6 +598,15 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
getDayAssignmentsState().addingAssignments(assignments);
|
||||
}
|
||||
|
||||
public void removeLimitingDayAssignments() {
|
||||
allocateLimitingDayAssignments(Collections.<T>emptyList());
|
||||
}
|
||||
|
||||
public void allocateLimitingDayAssignments(List<T> assignments) {
|
||||
assert isLimiting();
|
||||
resetAssignmentsTo(assignments);
|
||||
}
|
||||
|
||||
protected final void removingAssignments(
|
||||
List<? extends DayAssignment> assignments){
|
||||
getDayAssignmentsState().removingAssignments(assignments);
|
||||
|
|
@ -605,8 +618,12 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
}
|
||||
|
||||
private ResourcesPerDay calculateResourcesPerDayFromAssignments() {
|
||||
Map<LocalDate, List<T>> byDay = DayAssignment
|
||||
.byDay(getAssignments());
|
||||
return calculateResourcesPerDayFromAssignments(getAssignments());
|
||||
}
|
||||
|
||||
private ResourcesPerDay calculateResourcesPerDayFromAssignments(
|
||||
Collection<? extends T> assignments) {
|
||||
Map<LocalDate, List<T>> byDay = DayAssignment.byDay(assignments);
|
||||
int sumTotalHours = 0;
|
||||
int sumWorkableHours = 0;
|
||||
final ResourcesPerDay one = ResourcesPerDay.amount(1);
|
||||
|
|
@ -837,6 +854,14 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
|
||||
protected abstract DayAssignmentsState getDayAssignmentsState();
|
||||
|
||||
public int getConsolidatedHours() {
|
||||
return DayAssignment.sum(getConsolidatedAssignments());
|
||||
}
|
||||
|
||||
public int getNonConsolidatedHours() {
|
||||
return DayAssignment.sum(getNonConsolidatedAssignments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a list of {@link DayAssignment} ordered by date
|
||||
*/
|
||||
|
|
@ -844,6 +869,33 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
return getDayAssignmentsState().getOrderedDayAssignments();
|
||||
}
|
||||
|
||||
public List<? extends T> getNonConsolidatedAssignments(){
|
||||
return getDayAssignmentsByConsolidated(false);
|
||||
}
|
||||
|
||||
public List<? extends T> getConsolidatedAssignments() {
|
||||
return getDayAssignmentsByConsolidated(true);
|
||||
}
|
||||
|
||||
private List<T> getDayAssignmentsByConsolidated(
|
||||
boolean consolidated) {
|
||||
List<T> result = new ArrayList<T>();
|
||||
for (T day : getAssignments()) {
|
||||
if (day.isConsolidated() == consolidated) {
|
||||
result.add(day);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResourcesPerDay getNonConsolidatedResourcePerDay() {
|
||||
return calculateResourcesPerDayFromAssignments(getNonConsolidatedAssignments());
|
||||
}
|
||||
|
||||
public ResourcesPerDay getConsolidatedResourcePerDay() {
|
||||
return calculateResourcesPerDayFromAssignments(getConsolidatedAssignments());
|
||||
}
|
||||
|
||||
public ResourcesPerDay getResourcesPerDay() {
|
||||
return resourcesPerDay;
|
||||
}
|
||||
|
|
@ -879,11 +931,7 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
List<? extends DayAssignment> assignments = getAssignments();
|
||||
if (assignments.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return assignments.get(0).getDay();
|
||||
return LocalDate.fromDateFields(task.getStartDate());
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
|
|
@ -1006,8 +1054,10 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
|
||||
public void setLimitingResourceQueueElement(LimitingResourceQueueElement element) {
|
||||
limitingResourceQueueElements.clear();
|
||||
element.setResourceAllocation(this);
|
||||
limitingResourceQueueElements.add(element);
|
||||
if (element != null) {
|
||||
element.setResourceAllocation(this);
|
||||
limitingResourceQueueElements.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getIntendedTotalHours() {
|
||||
|
|
|
|||
|
|
@ -58,10 +58,25 @@ public class SpecificResourceAllocation extends
|
|||
task));
|
||||
}
|
||||
|
||||
public static SpecificResourceAllocation create(Resource resource, Task task) {
|
||||
/**
|
||||
* Creates a {@link SpecificResourceAllocation} for a
|
||||
* {@link LimitingResourceQueueElement}
|
||||
*
|
||||
* The process of creating a specific resource allocation for a queue
|
||||
* element is different as it's necessary to assign a resource and a number
|
||||
* of resources per day without allocating day assignments
|
||||
*
|
||||
* @param resource
|
||||
* @param task
|
||||
* @return
|
||||
*/
|
||||
public static SpecificResourceAllocation create(Resource resource,
|
||||
Task task) {
|
||||
assert resource.isLimitingResource();
|
||||
SpecificResourceAllocation result = create(new SpecificResourceAllocation(
|
||||
task));
|
||||
result.setResource(resource);
|
||||
result.setResourcesPerDay(ResourcesPerDay.amount(1));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,6 +183,16 @@ public class Task extends TaskElement {
|
|||
return !(getLimitingResourceAllocations().isEmpty());
|
||||
}
|
||||
|
||||
private ResourceAllocation<?> getAssociatedLimitingResourceAllocation() {
|
||||
Set<ResourceAllocation<?>> resourceAllocations = getLimitingResourceAllocations();
|
||||
return (resourceAllocations.size() > 0) ? resourceAllocations.iterator().next() : null;
|
||||
}
|
||||
|
||||
public boolean isLimitingAndHasDayAssignments() {
|
||||
ResourceAllocation<?> resourceAllocation = getAssociatedLimitingResourceAllocation();
|
||||
return (resourceAllocation != null) ? resourceAllocation.isLimitingAndHasDayAssignments() : false;
|
||||
}
|
||||
|
||||
public void addResourceAllocation(ResourceAllocation<?> resourceAllocation) {
|
||||
addResourceAllocation(resourceAllocation, true);
|
||||
}
|
||||
|
|
@ -559,7 +569,8 @@ public class Task extends TaskElement {
|
|||
|
||||
@Override
|
||||
protected boolean canBeResized() {
|
||||
return calculatedValue != CalculatedValue.END_DATE;
|
||||
return ((calculatedValue != CalculatedValue.END_DATE) || (resourceAllocations
|
||||
.isEmpty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -598,4 +609,13 @@ public class Task extends TaskElement {
|
|||
return consolidation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLimitedResourceAllocation() {
|
||||
return !getLimitingResourceAllocations().isEmpty();
|
||||
|
||||
}
|
||||
|
||||
public boolean hasConsolidations() {
|
||||
return ((consolidation != null) && (!consolidation.isEmpty()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -413,6 +413,19 @@ public abstract class TaskElement extends BaseEntity {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isLimiting() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isLimitingAndHasDayAssignments() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasConsolidations() {
|
||||
// Just Task could be consolidated
|
||||
return false;
|
||||
}
|
||||
|
||||
public TaskElement getTopMost() {
|
||||
TaskElement result = this;
|
||||
while (result.getParent() != null) {
|
||||
|
|
@ -446,4 +459,5 @@ public abstract class TaskElement extends BaseEntity {
|
|||
return "assigned";
|
||||
}
|
||||
|
||||
public abstract boolean hasLimitedResourceAllocation();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import org.navalplanner.business.scenarios.entities.Scenario;
|
|||
|
||||
/**
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*/
|
||||
public class TaskGroup extends TaskElement {
|
||||
|
||||
|
|
@ -176,4 +177,9 @@ public class TaskGroup extends TaskElement {
|
|||
public boolean isMilestone() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLimitedResourceAllocation() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import org.navalplanner.business.scenarios.entities.Scenario;
|
|||
|
||||
/**
|
||||
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*/
|
||||
public class TaskMilestone extends TaskElement {
|
||||
|
||||
|
|
@ -136,4 +137,9 @@ public class TaskMilestone extends TaskElement {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLimitedResourceAllocation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -103,4 +103,9 @@ public class CalculatedConsolidation extends Consolidation {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return consolidatedValues.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,6 +34,8 @@ public abstract class Consolidation extends BaseEntity {
|
|||
|
||||
public abstract boolean isCalculated();
|
||||
|
||||
public abstract boolean isEmpty();
|
||||
|
||||
private Task task;
|
||||
|
||||
protected Consolidation() {
|
||||
|
|
|
|||
|
|
@ -104,4 +104,8 @@ public class NonCalculatedConsolidation extends Consolidation {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return consolidatedValues.isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
package org.navalplanner.business.resources.entities;
|
||||
|
||||
import static org.navalplanner.business.i18n.I18nHelper._;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
|
@ -49,6 +50,8 @@ import org.navalplanner.business.resources.daos.ICriterionDAO;
|
|||
*/
|
||||
public class Criterion extends IntegrationEntity implements ICriterion {
|
||||
|
||||
private static final String ALL_WORKERS = _("[generic all workers]");
|
||||
|
||||
public static Criterion createUnvalidated(String code, String name,
|
||||
CriterionType type, Criterion parent, Boolean active) {
|
||||
|
||||
|
|
@ -104,6 +107,20 @@ public class Criterion extends IntegrationEntity implements ICriterion {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string of criterion names separated by comma
|
||||
*
|
||||
* @param criteria
|
||||
* @return
|
||||
*/
|
||||
public static String getNames(Collection<? extends Criterion> criteria) {
|
||||
List<String> names = new ArrayList<String>();
|
||||
for (Criterion each: criteria) {
|
||||
names.add(each.getName());
|
||||
}
|
||||
return (names.isEmpty()) ? Criterion.ALL_WORKERS : StringUtils.join(names, ",");
|
||||
}
|
||||
|
||||
public void updateUnvalidated(String name, Boolean active) {
|
||||
|
||||
if (!StringUtils.isBlank(name)) {
|
||||
|
|
@ -303,4 +320,5 @@ public class Criterion extends IntegrationEntity implements ICriterion {
|
|||
protected ICriterionDAO getIntegrationEntityDAO() {
|
||||
return Registry.getCriterionDAO();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ package org.navalplanner.business.resources.entities;
|
|||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
|
||||
/**
|
||||
|
|
@ -34,17 +35,24 @@ public class LimitingResourceQueueElementComparator implements
|
|||
@Override
|
||||
public int compare(LimitingResourceQueueElement arg0,
|
||||
LimitingResourceQueueElement arg1) {
|
||||
final int deltaHour = arg0.getStartHour() - arg1.getStartHour();
|
||||
if (deltaHour != 0) {
|
||||
return deltaHour / Math.abs(deltaHour);
|
||||
}
|
||||
if (arg0.getStartDate() == null) {
|
||||
int compareDates = compare(arg0.getStartDate(), arg1.getStartDate());
|
||||
return (compareDates != 0) ? compareDates : compare(
|
||||
arg0.getStartHour(), arg1.getStartHour());
|
||||
}
|
||||
|
||||
private int compare(LocalDate arg0, LocalDate arg1) {
|
||||
if (arg0 == null) {
|
||||
return -1;
|
||||
}
|
||||
if (arg1.getStartDate() == null) {
|
||||
if (arg1 == null) {
|
||||
return 1;
|
||||
}
|
||||
return arg0.getStartDate().compareTo(arg1.getStartDate());
|
||||
return arg0.compareTo(arg1);
|
||||
}
|
||||
|
||||
private int compare(int arg0, int arg1) {
|
||||
final int deltaHour = arg0 - arg1;
|
||||
return (deltaHour != 0) ? deltaHour / Math.abs(deltaHour) : 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
package org.navalplanner.business.workreports.daos;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.common.daos.IIntegrationEntityDAO;
|
||||
|
|
@ -41,4 +42,6 @@ public interface IWorkReportLineDAO extends
|
|||
|
||||
List<WorkReportLine> findByOrderElementAndChildren(OrderElement orderElement, boolean sortByDate);
|
||||
|
||||
List<WorkReportLine> findFilteredByDate(Date start, Date end);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
package org.navalplanner.business.workreports.daos;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
|
|
@ -74,4 +75,17 @@ public class WorkReportLineDAO extends IntegrationEntityDAO<WorkReportLine>
|
|||
return criteria.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<WorkReportLine> findFilteredByDate(Date start, Date end) {
|
||||
Criteria criteria = getSession().createCriteria(WorkReportLine.class);
|
||||
if(start != null) {
|
||||
criteria.add(Restrictions.ge("date", start));
|
||||
}
|
||||
if(end != null) {
|
||||
criteria.add(Restrictions.le("date", end));
|
||||
}
|
||||
return criteria.list();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
<property name="generateCodeForUnitTypes" not-null="true" />
|
||||
<property name="expandCompanyPlanningViewCharts" not-null="true" />
|
||||
<property name="expandOrderPlanningViewCharts" not-null="true" />
|
||||
<property name="expandResourceLoadViewCharts" not-null="true" />
|
||||
|
||||
</class>
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@
|
|||
</id>
|
||||
<version name="version" access="property" type="long" />
|
||||
|
||||
<many-to-one name="resourceAllocation" column="RESOURCE_ALLOCATION_ID" not-null="false" unique="true" />
|
||||
<many-to-one name="resourceAllocation" column="RESOURCE_ALLOCATION_ID" cascade="all" not-null="false" unique="true" />
|
||||
|
||||
<many-to-one name="limitingResourceQueue" column="LIMITING_RESOURCE_QUEUE_ID" />
|
||||
|
||||
|
|
@ -149,6 +149,48 @@
|
|||
<property name="hour" column="END_HOUR" />
|
||||
</component>
|
||||
|
||||
<set name="dependenciesAsOrigin" cascade="none" lazy="false">
|
||||
<key column="origin_queue_element_id"/>
|
||||
<one-to-many class="LimitingResourceQueueDependency"/>
|
||||
</set>
|
||||
|
||||
<set name="dependenciesAsDestiny" cascade="none" lazy="false">
|
||||
<key column="destiny_queue_element_id"/>
|
||||
<one-to-many class="LimitingResourceQueueDependency"/>
|
||||
</set>
|
||||
|
||||
</class>
|
||||
|
||||
<!-- LimitingResourceQueueDependency -->
|
||||
<class name="LimitingResourceQueueDependency" table="limiting_resource_queue_dependency">
|
||||
<id name="id" type="long" access="property">
|
||||
<generator class="hilo">
|
||||
<param name="max_lo">100</param>
|
||||
</generator>
|
||||
</id>
|
||||
|
||||
<property name="type">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
<param name="enumClass">org.navalplanner.business.planner.entities.LimitingResourceQueueDependency$QueueDependencyType</param>
|
||||
</type>
|
||||
</property>
|
||||
|
||||
<many-to-one name="hasAsOrigin" cascade="none"
|
||||
class="org.navalplanner.business.planner.entities.LimitingResourceQueueElement"
|
||||
column="origin_queue_element_id"
|
||||
not-null="false">
|
||||
</many-to-one>
|
||||
|
||||
<many-to-one name="hasAsDestiny" cascade="none"
|
||||
class="org.navalplanner.business.planner.entities.LimitingResourceQueueElement"
|
||||
column="destiny_queue_element_id"
|
||||
not-null="false">
|
||||
</many-to-one>
|
||||
|
||||
<one-to-one name="ganttDependency"
|
||||
class="Dependency"
|
||||
property-ref="queueDependency">
|
||||
</one-to-one>
|
||||
</class>
|
||||
|
||||
<!-- DayAssignment -->
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
<one-to-one name="taskSource" cascade="none"/>
|
||||
|
||||
<set name="dependenciesWithThisOrigin" cascade="all">
|
||||
<set name="dependenciesWithThisOrigin" cascade="all-delete-orphan">
|
||||
<key column="ORIGIN"></key>
|
||||
<one-to-many class="Dependency" />
|
||||
</set>
|
||||
|
||||
<set name="dependenciesWithThisDestination" cascade="all">
|
||||
<set name="dependenciesWithThisDestination" cascade="all-delete-orphan">
|
||||
<key column="DESTINATION"></key>
|
||||
<one-to-many class="Dependency" />
|
||||
</set>
|
||||
|
|
@ -87,6 +87,11 @@
|
|||
column="ORIGIN" />
|
||||
<many-to-one class="TaskElement" name="destination"
|
||||
column="DESTINATION" />
|
||||
<many-to-one class="LimitingResourceQueueDependency" cascade="all"
|
||||
name="queueDependency"
|
||||
column="queue_dependency"
|
||||
unique="false"
|
||||
/>
|
||||
<property name="type">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
<param name="enumClass">org.navalplanner.business.planner.entities.Dependency$Type</param>
|
||||
|
|
|
|||
|
|
@ -259,4 +259,29 @@ public class ResourceAllocationDAOTest {
|
|||
.list(GenericResourceAllocation.class);
|
||||
assertEquals(previous + 2, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAllocationsRelatedToResourcesWithDateFilter() {
|
||||
ResourceAllocation<?> resourceAllocation1 = createValidSpecificResourceAllocation();
|
||||
resourceAllocationDAO.save(resourceAllocation1);
|
||||
|
||||
Date intervalInitDate = resourceAllocation1.getTask().getStartDate();
|
||||
Date intervalEndDate = resourceAllocation1.getTask().getEndDate();
|
||||
List<Resource> resources = resourceAllocation1.getAssociatedResources();
|
||||
|
||||
assertTrue(resourceAllocationDAO.findAllocationsRelatedToAnyOf(resources,
|
||||
intervalInitDate, intervalEndDate).contains(resourceAllocation1));
|
||||
|
||||
intervalEndDate.setDate(intervalInitDate.getDate());
|
||||
intervalInitDate.setMonth(intervalInitDate.getMonth()-1);
|
||||
assertTrue(resourceAllocationDAO.findAllocationsRelatedToAnyOf(resources,
|
||||
intervalInitDate, intervalEndDate).contains(resourceAllocation1));
|
||||
|
||||
intervalEndDate.setMonth(intervalEndDate.getMonth()-1);
|
||||
assertFalse(resourceAllocationDAO.findAllocationsRelatedToAnyOf(resources,
|
||||
intervalInitDate, intervalEndDate).contains(resourceAllocation1));
|
||||
|
||||
assertTrue(resourceAllocationDAO.findAllocationsRelatedToAnyOf(resources,
|
||||
intervalInitDate, null).contains(resourceAllocation1));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,4 +366,14 @@ public class ConfigurationController extends GenericForwardComposer {
|
|||
return configurationModel.isExpandOrderPlanningViewCharts();
|
||||
}
|
||||
|
||||
public void setExpandResourceLoadViewCharts(
|
||||
Boolean expandResourceLoadViewCharts) {
|
||||
configurationModel
|
||||
.setExpandResourceLoadViewCharts(expandResourceLoadViewCharts);
|
||||
}
|
||||
|
||||
public Boolean isExpandResourceLoadViewCharts() {
|
||||
return configurationModel.isExpandResourceLoadViewCharts();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -373,4 +373,22 @@ public class ConfigurationModel implements IConfigurationModel {
|
|||
return configuration.isExpandOrderPlanningViewCharts();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setExpandResourceLoadViewCharts(
|
||||
Boolean expandResourceLoadViewCharts) {
|
||||
if (configuration != null) {
|
||||
configuration
|
||||
.setExpandResourceLoadViewCharts(expandResourceLoadViewCharts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isExpandResourceLoadViewCharts() {
|
||||
if (configuration == null) {
|
||||
return null;
|
||||
}
|
||||
return configuration.isExpandResourceLoadViewCharts();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -85,6 +85,10 @@ public interface IConfigurationModel {
|
|||
|
||||
Boolean isExpandOrderPlanningViewCharts();
|
||||
|
||||
void setExpandResourceLoadViewCharts(Boolean expandResourceLoadViewCharts);
|
||||
|
||||
Boolean isExpandResourceLoadViewCharts();
|
||||
|
||||
/*
|
||||
* Final conversation steps
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -23,28 +23,100 @@ package org.navalplanner.web.limitingresources;
|
|||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
|
||||
import org.zkoss.ganttz.util.Interval;
|
||||
|
||||
/**
|
||||
* Contains operations for showing {@link LimitingResourceQueue} and its
|
||||
* elements ({@link LimitingResourceQueueElement}), plus showing all
|
||||
* {@link LimitingResourceQueueElement} which are not assigned to any
|
||||
* {@link LimitingResourceQueue}
|
||||
*
|
||||
* <strong>Conversational protocol:</strong>
|
||||
* <ul>
|
||||
* <li>
|
||||
* Initial conversation step: <code>initGlobalView</code></li>
|
||||
* <li>
|
||||
* Intermediate conversation steps:
|
||||
* <code>assignLimitingResourceQueueElement</code>,
|
||||
* <code>getLimitingResourceQueues</code>,
|
||||
* <code>getUnassignedLimitingResourceQueueElements</code></li>
|
||||
* <li>
|
||||
* Final conversation step: <code>confirm</code></li>
|
||||
*
|
||||
*
|
||||
* @author Diego Pino Garcia <dpino@igalia.com>
|
||||
*
|
||||
*/
|
||||
public interface ILimitingResourceQueueModel {
|
||||
|
||||
/**
|
||||
* Assigns a {@link LimitingResourceQueueElement} to its corresponding
|
||||
* {@link LimitingResourceQueue}
|
||||
*
|
||||
* There is one and only one queue for every limiting resource. An element
|
||||
* is assigned to its queue searching by element.resource.
|
||||
*
|
||||
* Allocation within the queue is done by finding the first gap in the queue
|
||||
* that fits the initial intented hours assigned to
|
||||
* element.resourceallocation.
|
||||
*
|
||||
* The method also generates {@link DayAssignment} once the allocation is
|
||||
* done
|
||||
*
|
||||
* Returns true if the process was successful. The only case were an
|
||||
* allocation cannot be done is if there's not any queue that can hold the
|
||||
* element (only for a generic allocation, there's not any queue that
|
||||
* matches the criteria of the element)
|
||||
*
|
||||
* @param element
|
||||
*/
|
||||
boolean assignLimitingResourceQueueElement(LimitingResourceQueueElement element);
|
||||
|
||||
ZoomLevel calculateInitialZoomLevel();
|
||||
|
||||
/**
|
||||
* Saves all {@link LimitingResourceQueue}
|
||||
*/
|
||||
void confirm();
|
||||
|
||||
/**
|
||||
* Return all {@link LimitingResourceQueue}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<LimitingResourceQueue> getLimitingResourceQueues();
|
||||
|
||||
Order getOrderByTask(TaskElement task);
|
||||
|
||||
/**
|
||||
* Returns all existing {@link LimitingResourceQueueElement} which are not
|
||||
* assigned to any {@link LimitingResourceQueue}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<LimitingResourceQueueElement> getUnassignedLimitingResourceQueueElements();
|
||||
|
||||
Interval getViewInterval();
|
||||
|
||||
/**
|
||||
* Loads {@link LimitingResourceQueue} and unassigned {@link LimitingResourceQueueElement} from DB
|
||||
*
|
||||
* @param filterByResources
|
||||
*/
|
||||
void initGlobalView(boolean filterByResources);
|
||||
|
||||
void initGlobalView(Order filterBy, boolean filterByResources);
|
||||
|
||||
List<LimitingResourceQueue> getLimitingResourceQueues();
|
||||
|
||||
Interval getViewInterval();
|
||||
|
||||
ZoomLevel calculateInitialZoomLevel();
|
||||
|
||||
Order getOrderByTask(TaskElement task);
|
||||
|
||||
boolean userCanRead(Order order, String loginName);
|
||||
|
||||
List<LimitingResourceQueueElement> getUnassignedLimitingResourceQueueElements();
|
||||
void unschedule(LimitingResourceQueueElement element);
|
||||
|
||||
void removeUnassignedLimitingResourceQueueElement(
|
||||
LimitingResourceQueueElement element);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,15 +25,12 @@ import java.beans.PropertyChangeListener;
|
|||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.zkoss.ganttz.TaskComponent;
|
||||
import org.zkoss.ganttz.data.Dependency;
|
||||
import org.zkoss.ganttz.data.DependencyType;
|
||||
import org.zkoss.ganttz.data.Task;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
|
||||
import org.zkoss.zk.au.out.AuInvoke;
|
||||
import org.zkoss.zk.ui.ext.AfterCompose;
|
||||
import org.zkoss.zul.Div;
|
||||
import org.zkoss.zul.impl.XulElement;
|
||||
|
||||
/**
|
||||
|
|
@ -44,9 +41,9 @@ import org.zkoss.zul.impl.XulElement;
|
|||
public class LimitingDependencyComponent extends XulElement implements
|
||||
AfterCompose {
|
||||
|
||||
private Div source;
|
||||
private QueueTask source;
|
||||
|
||||
private Div destination;
|
||||
private QueueTask destination;
|
||||
|
||||
private DependencyType type;
|
||||
|
||||
|
|
@ -54,13 +51,15 @@ public class LimitingDependencyComponent extends XulElement implements
|
|||
|
||||
private IConstraintViolationListener<Date> violationListener;
|
||||
|
||||
public LimitingDependencyComponent(Div source, Div destination) {
|
||||
public LimitingDependencyComponent(QueueTask source, QueueTask destination,
|
||||
DependencyType type) {
|
||||
this(source, destination);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public LimitingDependencyComponent(QueueTask source, QueueTask destination) {
|
||||
Validate.notNull(source);
|
||||
Validate.notNull(destination);
|
||||
// Validate.isTrue(source.getTask() == dependency.getSource());
|
||||
// Validate.isTrue(destination.getTask() ==
|
||||
// dependency.getDestination());
|
||||
// this.type = dependency.getType();
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
// this.dependency = dependency;
|
||||
|
|
@ -100,8 +99,8 @@ public class LimitingDependencyComponent extends XulElement implements
|
|||
|
||||
}
|
||||
|
||||
private TaskComponent findTaskComponent(String idTaskOrig) {
|
||||
return (TaskComponent) getFellow(idTaskOrig);
|
||||
private QueueTask findTaskComponent(String idTaskOrig) {
|
||||
return (QueueTask) getFellow(idTaskOrig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -123,18 +122,18 @@ public class LimitingDependencyComponent extends XulElement implements
|
|||
response("zoomChanged", new AuInvoke(this, "draw"));
|
||||
}
|
||||
|
||||
public boolean contains(Task task) {
|
||||
public boolean contains(QueueTask task) {
|
||||
return false;
|
||||
// Task sourceTask = getSource().getTask();
|
||||
// Task destinationTask = getDestination().getTask();
|
||||
// return task.equals(sourceTask) || task.equals(destinationTask);
|
||||
}
|
||||
|
||||
public Div getSource() {
|
||||
public QueueTask getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public Div getDestination() {
|
||||
public QueueTask getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,18 +20,16 @@
|
|||
|
||||
package org.navalplanner.web.limitingresources;
|
||||
|
||||
import static org.zkoss.ganttz.i18n.I18nHelper._;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueDependency;
|
||||
import org.zkoss.ganttz.DependencyList;
|
||||
import org.zkoss.ganttz.FunctionalityExposedForExtensions;
|
||||
import org.zkoss.ganttz.GanttPanel;
|
||||
import org.zkoss.ganttz.TaskComponent;
|
||||
import org.zkoss.ganttz.data.Dependency;
|
||||
import org.zkoss.ganttz.data.DependencyType;
|
||||
|
|
@ -41,12 +39,9 @@ import org.zkoss.ganttz.timetracker.TimeTrackerComponent;
|
|||
import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
|
||||
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
|
||||
import org.zkoss.ganttz.util.ComponentsFinder;
|
||||
import org.zkoss.ganttz.util.MenuBuilder;
|
||||
import org.zkoss.ganttz.util.MenuBuilder.ItemAction;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.ext.AfterCompose;
|
||||
import org.zkoss.zul.Div;
|
||||
import org.zkoss.zul.Menupopup;
|
||||
import org.zkoss.zul.impl.XulElement;
|
||||
|
||||
/**
|
||||
|
|
@ -95,7 +90,6 @@ public class LimitingDependencyList extends XulElement implements AfterCompose {
|
|||
void toggleDependencyExistence(boolean visible) {
|
||||
if (visible) {
|
||||
appendChild(dependencyComponent);
|
||||
addContextMenu(dependencyComponent);
|
||||
} else {
|
||||
removeChild(dependencyComponent);
|
||||
}
|
||||
|
|
@ -114,43 +108,31 @@ public class LimitingDependencyList extends XulElement implements AfterCompose {
|
|||
|
||||
private transient IZoomLevelChangedListener listener;
|
||||
|
||||
private final FunctionalityExposedForExtensions<?> context;
|
||||
private final LimitingResourcesPanel panel;
|
||||
|
||||
public LimitingDependencyList(FunctionalityExposedForExtensions<?> context) {
|
||||
this.context = context;
|
||||
public LimitingDependencyList(LimitingResourcesPanel panel) {
|
||||
this.panel = panel;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<LimitingDependencyComponent> getLimitingDependencyComponents() {
|
||||
List<Object> children = getChildren();
|
||||
return ComponentsFinder.findComponentsOfType(
|
||||
LimitingDependencyComponent.class, children);
|
||||
LimitingDependencyComponent.class, getChildren());
|
||||
}
|
||||
|
||||
void addDependencyComponent(
|
||||
public void addDependencyComponent(
|
||||
final LimitingDependencyComponent dependencyComponent) {
|
||||
Div source = dependencyComponent.getSource();
|
||||
Div destination = dependencyComponent.getDestination();
|
||||
// DependencyVisibilityToggler visibilityToggler = new
|
||||
// DependencyVisibilityToggler(
|
||||
// source.getTask(), destination.getTask(), dependencyComponent);
|
||||
// source.getTask().addVisibilityPropertiesChangeListener(
|
||||
// visibilityToggler);
|
||||
// destination.getTask().addVisibilityPropertiesChangeListener(
|
||||
// visibilityToggler);
|
||||
// boolean dependencyMustBeVisible = visibilityToggler
|
||||
// .dependencyMustBeVisible();
|
||||
// visibilityToggler.toggleDependencyExistence(dependencyMustBeVisible);
|
||||
// if (dependencyMustBeVisible) {
|
||||
// dependencyComponent.redrawDependency();
|
||||
// }
|
||||
dependencyComponent.redrawDependency();
|
||||
dependencyComponent.setParent(this);
|
||||
}
|
||||
|
||||
private void addContextMenu(LimitingDependencyComponent dependencyComponent) {
|
||||
dependencyComponent.setContext(getContextMenu());
|
||||
}
|
||||
|
||||
private GanttPanel getGanttPanel() {
|
||||
return (GanttPanel) getParent();
|
||||
public void removeDependencyComponents(QueueTask queueTask) {
|
||||
for (LimitingDependencyComponent dependency : getLimitingDependencyComponents()) {
|
||||
if (dependency.getSource().equals(queueTask)
|
||||
|| dependency.getDestination().equals(queueTask)) {
|
||||
removeChild(dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setDependencyComponents(
|
||||
|
|
@ -166,72 +148,31 @@ public class LimitingDependencyList extends XulElement implements AfterCompose {
|
|||
listener = new IZoomLevelChangedListener() {
|
||||
@Override
|
||||
public void zoomLevelChanged(ZoomLevel detailLevel) {
|
||||
if (!isInPage()) {
|
||||
return;
|
||||
}
|
||||
for (LimitingDependencyComponent dependencyComponent : getLimitingDependencyComponents()) {
|
||||
dependencyComponent.zoomChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
// getTimeTracker().addZoomListener(listener);
|
||||
getTimeTracker().addZoomListener(listener);
|
||||
}
|
||||
// addContextMenu();
|
||||
}
|
||||
|
||||
private boolean isInPage() {
|
||||
return getParent() != null && getGanttPanel() != null
|
||||
&& getGanttPanel().getParent() != null;
|
||||
redrawDependencies();
|
||||
}
|
||||
|
||||
private TimeTracker getTimeTracker() {
|
||||
return getTimeTrackerComponent().getTimeTracker();
|
||||
}
|
||||
|
||||
private void addContextMenu() {
|
||||
for (LimitingDependencyComponent dependencyComponent : getLimitingDependencyComponents()) {
|
||||
addContextMenu(dependencyComponent);
|
||||
}
|
||||
}
|
||||
|
||||
private Menupopup contextMenu;
|
||||
|
||||
private Menupopup getContextMenu() {
|
||||
if (contextMenu == null) {
|
||||
MenuBuilder<LimitingDependencyComponent> contextMenuBuilder = MenuBuilder
|
||||
.on(getPage(), getLimitingDependencyComponents()).item(_("Erase"),
|
||||
"/common/img/ico_borrar.png",
|
||||
new ItemAction<LimitingDependencyComponent>() {
|
||||
@Override
|
||||
public void onEvent(
|
||||
final LimitingDependencyComponent choosen,
|
||||
Event event) {
|
||||
// context
|
||||
// .removeDependency(choosen.getDependency());
|
||||
}
|
||||
});
|
||||
contextMenuBuilder.item(_("Set End-Start"), null,
|
||||
new ChangeTypeAction(
|
||||
DependencyType.END_START));
|
||||
|
||||
contextMenuBuilder.item(_("Set Start-Start"), null,
|
||||
new ChangeTypeAction(
|
||||
DependencyType.START_START));
|
||||
|
||||
contextMenuBuilder.item(_("Set End-End"), null,
|
||||
new ChangeTypeAction(
|
||||
DependencyType.END_END));
|
||||
|
||||
contextMenu = contextMenuBuilder.create();
|
||||
|
||||
}
|
||||
return contextMenu;
|
||||
}
|
||||
|
||||
private TimeTrackerComponent getTimeTrackerComponent() {
|
||||
return getGanttPanel().getTimeTrackerComponent();
|
||||
return panel.getTimeTrackerComponent();
|
||||
}
|
||||
|
||||
|
||||
// private boolean isInPage() {
|
||||
// return getParent() != null && getGanttPanel() != null
|
||||
// && getGanttPanel().getParent() != null;
|
||||
// }
|
||||
|
||||
|
||||
public void redrawDependenciesConnectedTo(TaskComponent taskComponent) {
|
||||
redrawDependencyComponents(getDependencyComponentsConnectedTo(taskComponent));
|
||||
}
|
||||
|
|
@ -261,7 +202,7 @@ public class LimitingDependencyList extends XulElement implements AfterCompose {
|
|||
}
|
||||
}
|
||||
|
||||
public void taskRemoved(Task task) {
|
||||
public void taskRemoved(QueueTask task) {
|
||||
for (LimitingDependencyComponent dependencyComponent : LimitingDependencyList.this
|
||||
.getLimitingDependencyComponents()) {
|
||||
if (dependencyComponent.contains(task)) {
|
||||
|
|
@ -278,4 +219,5 @@ public class LimitingDependencyList extends XulElement implements AfterCompose {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,33 +20,46 @@
|
|||
|
||||
package org.navalplanner.web.limitingresources;
|
||||
|
||||
import static org.navalplanner.web.I18nHelper._;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
import org.navalplanner.business.calendars.entities.BaseCalendar;
|
||||
import org.navalplanner.business.calendars.entities.CalendarAvailability;
|
||||
import org.navalplanner.business.calendars.entities.CalendarData;
|
||||
import org.navalplanner.business.calendars.entities.CalendarException;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.orders.daos.IOrderDAO;
|
||||
import org.navalplanner.business.orders.daos.IOrderElementDAO;
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.orders.entities.OrderElement;
|
||||
import org.navalplanner.business.planner.daos.IDependencyDAO;
|
||||
import org.navalplanner.business.planner.daos.ILimitingResourceQueueDAO;
|
||||
import org.navalplanner.business.planner.daos.ILimitingResourceQueueDependencyDAO;
|
||||
import org.navalplanner.business.planner.daos.ILimitingResourceQueueElementDAO;
|
||||
import org.navalplanner.business.planner.daos.IResourceAllocationDAO;
|
||||
import org.navalplanner.business.planner.daos.ITaskElementDAO;
|
||||
import org.navalplanner.business.planner.entities.DateAndHour;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.Dependency;
|
||||
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceAllocator;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueDependency;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElementGap;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.Task;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.resources.daos.IResourceDAO;
|
||||
import org.navalplanner.business.resources.entities.Criterion;
|
||||
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.business.users.daos.IOrderAuthorizationDAO;
|
||||
|
|
@ -61,7 +74,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
|||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.zkoss.ganttz.data.resourceload.TimeLineRole;
|
||||
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
|
||||
import org.zkoss.ganttz.util.Interval;
|
||||
|
||||
|
|
@ -69,18 +81,9 @@ import org.zkoss.ganttz.util.Interval;
|
|||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
||||
|
||||
@Autowired
|
||||
private IResourceDAO resourcesDAO;
|
||||
|
||||
@Autowired
|
||||
private IOrderElementDAO orderElementDAO;
|
||||
|
||||
@Autowired
|
||||
private IOrderDAO orderDAO;
|
||||
|
||||
@Autowired
|
||||
private IResourceAllocationDAO resourceAllocationDAO;
|
||||
|
||||
@Autowired
|
||||
private IUserDAO userDAO;
|
||||
|
||||
|
|
@ -90,30 +93,222 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
|||
@Autowired
|
||||
private ILimitingResourceQueueElementDAO limitingResourceQueueElementDAO;
|
||||
|
||||
private List<LimitingResourceQueue> limitingResourceQueues = new ArrayList<LimitingResourceQueue>();
|
||||
@Autowired
|
||||
private ILimitingResourceQueueDAO limitingResourceQueueDAO;
|
||||
|
||||
@Autowired
|
||||
private ITaskElementDAO taskDAO;
|
||||
|
||||
@Autowired
|
||||
private ILimitingResourceQueueDependencyDAO limitingResourceQueueDependencyDAO;
|
||||
|
||||
private Interval viewInterval;
|
||||
|
||||
private Order filterBy;
|
||||
private List<LimitingResourceQueue> limitingResourceQueues = new ArrayList<LimitingResourceQueue>();
|
||||
|
||||
private boolean filterByResources = true;
|
||||
private List<LimitingResourceQueueElement> unassignedLimitingResourceQueueElements = new ArrayList<LimitingResourceQueueElement>();
|
||||
|
||||
private Set<LimitingResourceQueueElement> toBeRemoved = new HashSet<LimitingResourceQueueElement>();
|
||||
|
||||
private Set<LimitingResourceQueueElement> toBeSaved = new HashSet<LimitingResourceQueueElement>();
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public void initGlobalView(boolean filterByResources) {
|
||||
filterBy = null;
|
||||
this.filterByResources = filterByResources;
|
||||
doGlobalView();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public void initGlobalView(Order filterBy, boolean filterByResources) {
|
||||
this.filterBy = orderDAO.findExistingEntity(filterBy.getId());
|
||||
this.filterByResources = filterByResources;
|
||||
doGlobalView();
|
||||
}
|
||||
|
||||
private void doGlobalView() {
|
||||
loadUnassignedLimitingResourceQueueElements();
|
||||
loadLimitingResourceQueues();
|
||||
final Date startingDate = getEarliestDate();
|
||||
viewInterval = new Interval(startingDate, plusFiveYears(startingDate));
|
||||
}
|
||||
|
||||
private Date getEarliestDate() {
|
||||
final LimitingResourceQueueElement element = getEarliestQueueElement();
|
||||
return (element != null) ? element.getStartDate()
|
||||
.toDateTimeAtCurrentTime().toDate() : new Date();
|
||||
}
|
||||
|
||||
private LimitingResourceQueueElement getEarliestQueueElement() {
|
||||
LimitingResourceQueueElement earliestQueueElement = null;
|
||||
|
||||
if (!limitingResourceQueues.isEmpty()) {
|
||||
for (LimitingResourceQueue each : limitingResourceQueues) {
|
||||
LimitingResourceQueueElement element = getFirstLimitingResourceQueueElement(each);
|
||||
if (element == null) {
|
||||
continue;
|
||||
}
|
||||
if (earliestQueueElement == null
|
||||
|| isEarlier(element, earliestQueueElement)) {
|
||||
earliestQueueElement = element;
|
||||
}
|
||||
}
|
||||
}
|
||||
return earliestQueueElement;
|
||||
}
|
||||
|
||||
private boolean isEarlier(LimitingResourceQueueElement arg1,
|
||||
LimitingResourceQueueElement arg2) {
|
||||
return (arg1.getStartDate().isBefore(arg2.getStartDate()));
|
||||
}
|
||||
|
||||
private LimitingResourceQueueElement getFirstLimitingResourceQueueElement(
|
||||
LimitingResourceQueue queue) {
|
||||
return getFirstChild(queue.getLimitingResourceQueueElements());
|
||||
}
|
||||
|
||||
private LimitingResourceQueueElement getFirstChild(
|
||||
SortedSet<LimitingResourceQueueElement> elements) {
|
||||
return (elements.isEmpty()) ? null : elements.iterator().next();
|
||||
}
|
||||
|
||||
private Date plusFiveYears(Date date) {
|
||||
return (new LocalDate(date)).plusYears(5).toDateTimeAtCurrentTime()
|
||||
.toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads unassigned {@link LimitingResourceQueueElement} from DB
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private void loadUnassignedLimitingResourceQueueElements() {
|
||||
unassignedLimitingResourceQueueElements.clear();
|
||||
unassignedLimitingResourceQueueElements
|
||||
.addAll(initializeLimitingResourceQueueElements(limitingResourceQueueElementDAO
|
||||
.getUnassigned()));
|
||||
}
|
||||
|
||||
private List<LimitingResourceQueueElement> initializeLimitingResourceQueueElements(
|
||||
List<LimitingResourceQueueElement> elements) {
|
||||
for (LimitingResourceQueueElement each : elements) {
|
||||
initializeLimitingResourceQueueElement(each);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
private void initializeLimitingResourceQueueElement(
|
||||
LimitingResourceQueueElement element) {
|
||||
ResourceAllocation<?> resourceAllocation = element
|
||||
.getResourceAllocation();
|
||||
resourceAllocation = initializeResourceAllocationIfNecessary(resourceAllocation);
|
||||
element.setResourceAllocation(resourceAllocation);
|
||||
initializeTask(resourceAllocation.getTask());
|
||||
initializeResourceIfAny(element.getResource());
|
||||
}
|
||||
|
||||
private void initializeTask(Task task) {
|
||||
Hibernate.initialize(task);
|
||||
for (ResourceAllocation<?> each: task.getAllResourceAllocations()) {
|
||||
Hibernate.initialize(each);
|
||||
}
|
||||
for (Dependency each: task.getDependenciesWithThisOrigin()) {
|
||||
Hibernate.initialize(each);
|
||||
}
|
||||
for (Dependency each: task.getDependenciesWithThisDestination()) {
|
||||
Hibernate.initialize(each);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeCalendarIfAny(BaseCalendar calendar) {
|
||||
if (calendar != null) {
|
||||
Hibernate.initialize(calendar);
|
||||
initializeCalendarAvailabilities(calendar);
|
||||
initializeCalendarExceptions(calendar);
|
||||
initializeCalendarDataVersions(calendar);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeCalendarAvailabilities(BaseCalendar calendar) {
|
||||
for (CalendarAvailability each : calendar.getCalendarAvailabilities()) {
|
||||
Hibernate.initialize(each);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeCalendarExceptions(BaseCalendar calendar) {
|
||||
for (CalendarException each : calendar.getExceptions()) {
|
||||
Hibernate.initialize(each);
|
||||
Hibernate.initialize(each.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeCalendarDataVersions(BaseCalendar calendar) {
|
||||
for (CalendarData each : calendar.getCalendarDataVersions()) {
|
||||
Hibernate.initialize(each);
|
||||
Hibernate.initialize(each.getHoursPerDay());
|
||||
initializeCalendarIfAny(each.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
private ResourceAllocation<?> initializeResourceAllocationIfNecessary(
|
||||
ResourceAllocation<?> resourceAllocation) {
|
||||
if (resourceAllocation instanceof HibernateProxy) {
|
||||
resourceAllocation = (ResourceAllocation<?>) ((HibernateProxy) resourceAllocation)
|
||||
.getHibernateLazyInitializer().getImplementation();
|
||||
if (resourceAllocation instanceof GenericResourceAllocation) {
|
||||
GenericResourceAllocation generic = (GenericResourceAllocation) resourceAllocation;
|
||||
initializeCriteria(generic.getCriterions());
|
||||
}
|
||||
Hibernate.initialize(resourceAllocation.getAssignments());
|
||||
Hibernate.initialize(resourceAllocation.getLimitingResourceQueueElement());
|
||||
}
|
||||
return resourceAllocation;
|
||||
}
|
||||
|
||||
private void initializeCriteria(Set<Criterion> criteria) {
|
||||
for (Criterion each: criteria) {
|
||||
initializeCriterion(each);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeCriterion(Criterion criterion) {
|
||||
Hibernate.initialize(criterion);
|
||||
Hibernate.initialize(criterion.getType());
|
||||
}
|
||||
|
||||
private void loadLimitingResourceQueues() {
|
||||
limitingResourceQueues.clear();
|
||||
limitingResourceQueues
|
||||
.addAll(initializeLimitingResourceQueues(limitingResourceQueueDAO
|
||||
.getAll()));
|
||||
}
|
||||
|
||||
private List<LimitingResourceQueue> initializeLimitingResourceQueues(
|
||||
List<LimitingResourceQueue> queues) {
|
||||
for (LimitingResourceQueue each : queues) {
|
||||
initializeLimitingResourceQueue(each);
|
||||
}
|
||||
return queues;
|
||||
}
|
||||
|
||||
private void initializeLimitingResourceQueue(LimitingResourceQueue queue) {
|
||||
initializeResourceIfAny(queue.getResource());
|
||||
for (LimitingResourceQueueElement each : queue
|
||||
.getLimitingResourceQueueElements()) {
|
||||
initializeLimitingResourceQueueElement(each);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeResourceIfAny(Resource resource) {
|
||||
if (resource != null) {
|
||||
Hibernate.initialize(resource);
|
||||
for (CriterionSatisfaction each : resource
|
||||
.getCriterionSatisfactions()) {
|
||||
Hibernate.initialize(each);
|
||||
initializeCriterion(each.getCriterion());
|
||||
initializeCalendarIfAny(resource.getCalendar());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Order getOrderByTask(TaskElement task) {
|
||||
|
|
@ -121,6 +316,11 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
|||
.loadOrderAvoidingProxyFor(task.getOrderElement());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interval getViewInterval() {
|
||||
return viewInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public boolean userCanRead(Order order, String loginName) {
|
||||
|
|
@ -145,142 +345,14 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void doGlobalView() {
|
||||
limitingResourceQueues = calculateLimitingResourceQueues();
|
||||
if (!limitingResourceQueues.isEmpty()) {
|
||||
// Build interval
|
||||
// viewInterval =
|
||||
// LimitingResourceQueue.getIntervalFrom(limitingResourceQueues);
|
||||
viewInterval = new Interval(new Date(), plusFiveYears(new Date()));
|
||||
} else {
|
||||
viewInterval = new Interval(new Date(), plusFiveYears(new Date()));
|
||||
}
|
||||
}
|
||||
|
||||
private Date plusFiveYears(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.YEAR, 5);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
private List<LimitingResourceQueue> calculateLimitingResourceQueues() {
|
||||
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
|
||||
result.addAll(groupsFor(resourcesToShow()));
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Resource> resourcesToShow() {
|
||||
if (filter()) {
|
||||
return resourcesForActiveTasks();
|
||||
} else {
|
||||
return allLimitingResources();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean filter() {
|
||||
return filterBy != null;
|
||||
}
|
||||
|
||||
private List<Resource> resourcesForActiveTasks() {
|
||||
return Resource.sortByName(resourcesDAO
|
||||
.findResourcesRelatedTo(justTasks(filterBy
|
||||
.getAllChildrenAssociatedTaskElements())));
|
||||
}
|
||||
|
||||
private List<Task> justTasks(Collection<? extends TaskElement> tasks) {
|
||||
List<Task> result = new ArrayList<Task>();
|
||||
for (TaskElement taskElement : tasks) {
|
||||
if (taskElement instanceof Task) {
|
||||
result.add((Task) taskElement);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Resource> allLimitingResources() {
|
||||
List<Resource> result = Resource.sortByName(resourcesDAO
|
||||
.getAllLimitingResources());
|
||||
for (Resource each : result) {
|
||||
each.getLimitingResourceQueue().getLimitingResourceQueueElements()
|
||||
.size();
|
||||
limitingResourceQueues.add(each.getLimitingResourceQueue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private TimeLineRole<BaseEntity> getCurrentTimeLineRole(BaseEntity entity) {
|
||||
return new TimeLineRole<BaseEntity>(entity);
|
||||
}
|
||||
|
||||
private List<LimitingResourceQueue> groupsFor(List<Resource> allResources) {
|
||||
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
|
||||
for (Resource resource : allResources) {
|
||||
LimitingResourceQueue group = resource.getLimitingResourceQueue();
|
||||
result.add(group);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void initializeIfNeeded(
|
||||
Map<Order, List<ResourceAllocation<?>>> result, Order order) {
|
||||
if (!result.containsKey(order)) {
|
||||
result.put(order, new ArrayList<ResourceAllocation<?>>());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Map<Order, List<ResourceAllocation<?>>> byOrder(
|
||||
Collection<ResourceAllocation<?>> allocations) {
|
||||
Map<Order, List<ResourceAllocation<?>>> result = new HashMap<Order, List<ResourceAllocation<?>>>();
|
||||
for (ResourceAllocation<?> resourceAllocation : allocations) {
|
||||
if ((resourceAllocation.isSatisfied())
|
||||
&& (resourceAllocation.getTask() != null)) {
|
||||
OrderElement orderElement = resourceAllocation.getTask()
|
||||
.getOrderElement();
|
||||
Order order = orderElementDAO
|
||||
.loadOrderAvoidingProxyFor(orderElement);
|
||||
initializeIfNeeded(result, order);
|
||||
result.get(order).add(resourceAllocation);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private List<GenericResourceAllocation> onlyGeneric(
|
||||
List<ResourceAllocation<?>> sortedByStartDate) {
|
||||
return ResourceAllocation.getOfType(GenericResourceAllocation.class,
|
||||
sortedByStartDate);
|
||||
}
|
||||
|
||||
public static String getName(Collection<? extends Criterion> criterions,
|
||||
Task task) {
|
||||
String prefix = task.getName();
|
||||
return (prefix + " :: " + getName(criterions));
|
||||
}
|
||||
|
||||
public static String getName(Collection<? extends Criterion> criterions) {
|
||||
if (criterions.isEmpty()) {
|
||||
return _("[generic all workers]");
|
||||
}
|
||||
String[] names = new String[criterions.size()];
|
||||
int i = 0;
|
||||
for (Criterion criterion : criterions) {
|
||||
names[i++] = criterion.getName();
|
||||
}
|
||||
return (Arrays.toString(names));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<LimitingResourceQueue> getLimitingResourceQueues() {
|
||||
return limitingResourceQueues;
|
||||
return Collections.unmodifiableList(limitingResourceQueues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interval getViewInterval() {
|
||||
return viewInterval;
|
||||
public List<LimitingResourceQueueElement> getUnassignedLimitingResourceQueueElements() {
|
||||
return Collections
|
||||
.unmodifiableList(unassignedLimitingResourceQueueElements);
|
||||
}
|
||||
|
||||
public ZoomLevel calculateInitialZoomLevel() {
|
||||
|
|
@ -290,15 +362,307 @@ public class LimitingResourceQueueModel implements ILimitingResourceQueueModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly=true)
|
||||
public List<LimitingResourceQueueElement> getUnassignedLimitingResourceQueueElements() {
|
||||
List<LimitingResourceQueueElement> result = limitingResourceQueueElementDAO
|
||||
.getUnassigned();
|
||||
for (LimitingResourceQueueElement each : result) {
|
||||
limitingResourceQueueElementDAO.reattach(each);
|
||||
each.getResourceAllocation().getTask().getName();
|
||||
public boolean assignLimitingResourceQueueElement(
|
||||
LimitingResourceQueueElement element) {
|
||||
|
||||
LimitingResourceQueue queue = null;
|
||||
DateAndHour startTime = null;
|
||||
|
||||
LimitingResourceQueueElement queueElement = retrieveQueueElementFromModel(element);
|
||||
|
||||
final ResourceAllocation<?> resourceAllocation = queueElement
|
||||
.getResourceAllocation();
|
||||
if (resourceAllocation instanceof SpecificResourceAllocation) {
|
||||
// Retrieve queue
|
||||
queue = retrieveQueueByResourceFromModel(queueElement.getResource());
|
||||
// Set start time
|
||||
final LimitingResourceQueueElementGap firstGap = LimitingResourceAllocator
|
||||
.getFirstValidGap(queue, queueElement);
|
||||
startTime = firstGap.getStartTime();
|
||||
} else if (resourceAllocation instanceof GenericResourceAllocation) {
|
||||
// Get the first gap for all the queues that can allocate the
|
||||
// element during a certain interval of time
|
||||
Map<LimitingResourceQueueElementGap, LimitingResourceQueue> firstGapsForQueues = findFirstGapsInAllQueues(
|
||||
limitingResourceQueues, element);
|
||||
// Among those queues, get the earliest gap
|
||||
LimitingResourceQueueElementGap earliestGap = findEarliestGap(firstGapsForQueues
|
||||
.keySet());
|
||||
if (earliestGap == null) {
|
||||
return false;
|
||||
}
|
||||
// Select queue and start time
|
||||
queue = firstGapsForQueues.get(earliestGap);
|
||||
startTime = earliestGap.getStartTime();
|
||||
}
|
||||
|
||||
// Generate day assignments and adjust start and end times for element
|
||||
List<DayAssignment> dayAssignments = LimitingResourceAllocator
|
||||
.generateDayAssignments(queueElement.getResourceAllocation(),
|
||||
queue.getResource(), startTime);
|
||||
DateAndHour[] startAndEndTime = LimitingResourceAllocator
|
||||
.calculateStartAndEndTime(dayAssignments);
|
||||
updateStartAndEndTimes(queueElement, startAndEndTime);
|
||||
|
||||
// Add element to queue
|
||||
addLimitingResourceQueueElement(queue, queueElement);
|
||||
markAsModified(queueElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
private LimitingResourceQueueElementGap findEarliestGap(Set<LimitingResourceQueueElementGap> gaps) {
|
||||
LimitingResourceQueueElementGap earliestGap = null;
|
||||
for (LimitingResourceQueueElementGap each: gaps) {
|
||||
if (earliestGap == null || each.isBefore(earliestGap)) {
|
||||
earliestGap = each;
|
||||
}
|
||||
}
|
||||
return earliestGap;
|
||||
}
|
||||
|
||||
private Map<LimitingResourceQueueElementGap, LimitingResourceQueue> findFirstGapsInAllQueues(
|
||||
List<LimitingResourceQueue> queues,
|
||||
LimitingResourceQueueElement element) {
|
||||
|
||||
Map<LimitingResourceQueueElementGap, LimitingResourceQueue> result = new HashMap<LimitingResourceQueueElementGap, LimitingResourceQueue>();
|
||||
|
||||
for (LimitingResourceQueue each : queues) {
|
||||
LimitingResourceQueueElementGap gap = LimitingResourceAllocator
|
||||
.getFirstValidGap(each, element);
|
||||
if (gap != null) {
|
||||
result.put(gap, each);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void markAsModified(LimitingResourceQueueElement element) {
|
||||
if (!toBeSaved.contains(element)) {
|
||||
toBeSaved.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
public LimitingResourceQueueElementGap createGap(Resource resource, DateAndHour startTime,
|
||||
DateAndHour endTime) {
|
||||
return LimitingResourceQueueElementGap.create(resource, startTime, endTime);
|
||||
}
|
||||
|
||||
private void updateStartAndEndTimes(LimitingResourceQueueElement element,
|
||||
DateAndHour[] startAndEndTime) {
|
||||
|
||||
final DateAndHour startTime = startAndEndTime[0];
|
||||
final DateAndHour endTime = startAndEndTime[1];
|
||||
|
||||
element.setStartDate(startTime.getDate());
|
||||
element.setStartHour(startTime.getHour());
|
||||
element.setEndDate(endTime.getDate());
|
||||
element.setEndHour(endTime.getHour());
|
||||
|
||||
// Update starting and ending dates for associated Task
|
||||
Task task = element.getResourceAllocation().getTask();
|
||||
updateStartingAndEndingDate(task, startTime.getDate(), endTime
|
||||
.getDate());
|
||||
}
|
||||
|
||||
private void updateStartingAndEndingDate(Task task, LocalDate startDate,
|
||||
LocalDate endDate) {
|
||||
task.setStartDate(toDate(startDate));
|
||||
task.setEndDate(endDate.toDateTimeAtStartOfDay().toDate());
|
||||
task.explicityMoved(toDate(startDate));
|
||||
}
|
||||
|
||||
private Date toDate(LocalDate date) {
|
||||
return date.toDateTimeAtStartOfDay().toDate();
|
||||
}
|
||||
|
||||
private void addLimitingResourceQueueElement(LimitingResourceQueue queue,
|
||||
LimitingResourceQueueElement element) {
|
||||
queue.addLimitingResourceQueueElement(element);
|
||||
unassignedLimitingResourceQueueElements.remove(element);
|
||||
}
|
||||
|
||||
private LimitingResourceQueue retrieveQueueByResourceFromModel(Resource resource) {
|
||||
return findQueueByResource(limitingResourceQueues, resource);
|
||||
}
|
||||
|
||||
private LimitingResourceQueue findQueueByResource(
|
||||
List<LimitingResourceQueue> queues, Resource resource) {
|
||||
for (LimitingResourceQueue each : queues) {
|
||||
if (each.getResource().getId().equals(resource.getId())) {
|
||||
return each;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private LimitingResourceQueue retrieveQueueFromModel(LimitingResourceQueue queue) {
|
||||
return findQueue(limitingResourceQueues, queue);
|
||||
}
|
||||
|
||||
private LimitingResourceQueue findQueue(List<LimitingResourceQueue> queues,
|
||||
LimitingResourceQueue queue) {
|
||||
for (LimitingResourceQueue each : limitingResourceQueues) {
|
||||
if (each.getId().equals(queue.getId())) {
|
||||
return each;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private LimitingResourceQueueElement retrieveQueueElementFromModel(
|
||||
LimitingResourceQueueElement element) {
|
||||
final LimitingResourceQueue queue = element.getLimitingResourceQueue();
|
||||
if (queue != null) {
|
||||
return findQueueElement(queue.getLimitingResourceQueueElements(),
|
||||
element);
|
||||
} else {
|
||||
return findQueueElement(unassignedLimitingResourceQueueElements,
|
||||
element);
|
||||
}
|
||||
}
|
||||
|
||||
private LimitingResourceQueueElement findQueueElement(
|
||||
Collection<LimitingResourceQueueElement> elements,
|
||||
LimitingResourceQueueElement element) {
|
||||
for (LimitingResourceQueueElement each : elements) {
|
||||
if (each.getId().equals(element.getId())) {
|
||||
return each;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void confirm() {
|
||||
applyChanges();
|
||||
}
|
||||
|
||||
private void applyChanges() {
|
||||
removeQueueElements();
|
||||
saveQueueElements();
|
||||
}
|
||||
|
||||
private void saveQueueElements() {
|
||||
for (LimitingResourceQueueElement each: toBeSaved) {
|
||||
if (each != null) {
|
||||
saveQueueElement(each);
|
||||
}
|
||||
}
|
||||
toBeSaved.clear();
|
||||
}
|
||||
|
||||
private void saveQueueElement(LimitingResourceQueueElement element) {
|
||||
limitingResourceQueueElementDAO.save(element);
|
||||
taskDAO.save(getAssociatedTask(element));
|
||||
}
|
||||
|
||||
private Task getAssociatedTask(LimitingResourceQueueElement element) {
|
||||
return element.getResourceAllocation().getTask();
|
||||
}
|
||||
|
||||
private void removeQueueElements() {
|
||||
for (LimitingResourceQueueElement each: toBeRemoved) {
|
||||
removeQueueElement(each);
|
||||
}
|
||||
toBeRemoved.clear();
|
||||
}
|
||||
|
||||
private void removeQueueElement(LimitingResourceQueueElement element) {
|
||||
Task task = getAssociatedTask(element);
|
||||
removeQueueDependenciesIfAny(task);
|
||||
removeQueueElementById(element.getId());
|
||||
}
|
||||
|
||||
private void removeQueueElementById(Long id) {
|
||||
try {
|
||||
limitingResourceQueueElementDAO.remove(id);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Trying to remove non-existing entity");
|
||||
}
|
||||
}
|
||||
|
||||
private void removeQueueDependenciesIfAny(Task task) {
|
||||
for (Dependency each: task.getDependenciesWithThisOrigin()) {
|
||||
removeQueueDependencyIfAny(each);
|
||||
}
|
||||
for (Dependency each: task.getDependenciesWithThisDestination()) {
|
||||
removeQueueDependencyIfAny(each);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeQueueDependencyIfAny(Dependency dependency) {
|
||||
LimitingResourceQueueDependency queueDependency = dependency.getQueueDependency();
|
||||
if (queueDependency != null) {
|
||||
queueDependency.getHasAsOrigin().remove(queueDependency);
|
||||
queueDependency.getHasAsDestiny().remove(queueDependency);
|
||||
dependency.setQueueDependency(null);
|
||||
dependencyDAO.save(dependency);
|
||||
removeQueueDependencyById(queueDependency.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private IDependencyDAO dependencyDAO;
|
||||
|
||||
private void removeQueueDependencyById(Long id) {
|
||||
try {
|
||||
limitingResourceQueueDependencyDAO.remove(id);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Trying to remove non-existing entity");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unschedules an element from the list of queue elements. The element is
|
||||
* later added to the list of unassigned elements
|
||||
*/
|
||||
@Override
|
||||
public void unschedule(LimitingResourceQueueElement element) {
|
||||
LimitingResourceQueueElement queueElement = retrieveQueueElementFromModel(element);
|
||||
LimitingResourceQueue queue = retrieveQueueFromModel(element.getLimitingResourceQueue());
|
||||
|
||||
queue.removeLimitingResourceQueueElement(queueElement);
|
||||
|
||||
// Set as unassigned element
|
||||
queueElement.setLimitingResourceQueue(null);
|
||||
queueElement.setStartDate(null);
|
||||
queueElement.setStartHour(0);
|
||||
queueElement.setEndDate(null);
|
||||
queueElement.setEndHour(0);
|
||||
|
||||
queueElement.getResourceAllocation().removeLimitingDayAssignments();
|
||||
unassignedLimitingResourceQueueElements.add(queueElement);
|
||||
markAsModified(queueElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an {@link LimitingResourceQueueElement} from the list of
|
||||
* unassigned elements
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void removeUnassignedLimitingResourceQueueElement(
|
||||
LimitingResourceQueueElement element) {
|
||||
LimitingResourceQueueElement queueElement = retrieveQueueElementFromModel(element);
|
||||
|
||||
queueElement.getResourceAllocation().setLimitingResourceQueueElement(null);
|
||||
queueElement.getResourceAllocation().getTask()
|
||||
.removeAllResourceAllocations();
|
||||
unassignedLimitingResourceQueueElements.remove(queueElement);
|
||||
markAsRemoved(queueElement);
|
||||
}
|
||||
|
||||
private void markAsRemoved(LimitingResourceQueueElement element) {
|
||||
if (toBeSaved.contains(element)) {
|
||||
toBeSaved.remove(element);
|
||||
}
|
||||
if (!toBeRemoved.contains(element)) {
|
||||
toBeRemoved.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,14 +22,26 @@ package org.navalplanner.web.limitingresources;
|
|||
|
||||
import static org.navalplanner.web.I18nHelper._;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.jfree.util.Log;
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.Task;
|
||||
import org.navalplanner.business.resources.entities.Criterion;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.web.common.Util;
|
||||
import org.navalplanner.web.limitingresources.LimitingResourcesPanel.IToolbarCommand;
|
||||
import org.navalplanner.web.planner.order.BankHolidaysMarker;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -45,6 +57,9 @@ import org.zkoss.zk.ui.event.Events;
|
|||
import org.zkoss.zk.ui.util.Composer;
|
||||
import org.zkoss.zul.Button;
|
||||
import org.zkoss.zul.Checkbox;
|
||||
import org.zkoss.zul.Div;
|
||||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Hbox;
|
||||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.Messagebox;
|
||||
import org.zkoss.zul.Row;
|
||||
|
|
@ -71,6 +86,8 @@ public class LimitingResourcesController implements Composer {
|
|||
|
||||
private TimeTracker timeTracker;
|
||||
|
||||
private Grid gridUnassignedLimitingResourceQueueElements;
|
||||
|
||||
private final LimitingResourceQueueElementsRenderer limitingResourceQueueElementsRenderer =
|
||||
new LimitingResourceQueueElementsRenderer();
|
||||
|
||||
|
|
@ -111,6 +128,8 @@ public class LimitingResourcesController implements Composer {
|
|||
this.parent.getChildren().clear();
|
||||
this.parent.appendChild(limitingResourcesPanel);
|
||||
limitingResourcesPanel.afterCompose();
|
||||
gridUnassignedLimitingResourceQueueElements = (Grid) limitingResourcesPanel
|
||||
.getFellowIfAny("gridUnassignedLimitingResourceQueueElements");
|
||||
addCommands(limitingResourcesPanel);
|
||||
} catch (IllegalArgumentException e) {
|
||||
try {
|
||||
|
|
@ -151,21 +170,126 @@ public class LimitingResourcesController implements Composer {
|
|||
}
|
||||
|
||||
private LimitingResourcesPanel buildLimitingResourcesPanel() {
|
||||
LimitingResourcesPanel result = new LimitingResourcesPanel(
|
||||
limitingResourceQueueModel.getLimitingResourceQueues(),
|
||||
timeTracker);
|
||||
result.setVariable("limitingResourcesController", this, true);
|
||||
return new LimitingResourcesPanel(this, timeTracker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns unassigned {@link LimitingResourceQueueElement}
|
||||
*
|
||||
* It's necessary to convert elements to a DTO that encapsulates properties
|
||||
* such as task name or order name, since the only way of sorting by these
|
||||
* fields is by having properties getTaskName or getOrderName on the
|
||||
* elements returned
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<LimitingResourceQueueElementDTO> getUnassignedLimitingResourceQueueElements() {
|
||||
List<LimitingResourceQueueElementDTO> result = new ArrayList<LimitingResourceQueueElementDTO>();
|
||||
for (LimitingResourceQueueElement each : limitingResourceQueueModel
|
||||
.getUnassignedLimitingResourceQueueElements()) {
|
||||
result.add(toLimitingResourceQueueElementDTO(each));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<LimitingResourceQueueElement> getUnassignedLimitingResourceQueueElements() {
|
||||
return limitingResourceQueueModel.getUnassignedLimitingResourceQueueElements();
|
||||
private LimitingResourceQueueElementDTO toLimitingResourceQueueElementDTO(
|
||||
LimitingResourceQueueElement element) {
|
||||
final Task task = element.getResourceAllocation().getTask();
|
||||
final Order order = limitingResourceQueueModel.getOrderByTask(task);
|
||||
return new LimitingResourceQueueElementDTO(element, order
|
||||
.getName(), task.getName(), element
|
||||
.getEarlierStartDateBecauseOfGantt());
|
||||
}
|
||||
|
||||
/**
|
||||
* DTO for list of unassigned {@link LimitingResourceQueueElement}
|
||||
*
|
||||
* @author Diego Pino Garcia <dpino@igalia.com>
|
||||
*
|
||||
*/
|
||||
public class LimitingResourceQueueElementDTO {
|
||||
|
||||
private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");
|
||||
|
||||
private LimitingResourceQueueElement original;
|
||||
|
||||
private String orderName;
|
||||
|
||||
private String taskName;
|
||||
|
||||
private String date;
|
||||
|
||||
private Integer hoursToAllocate;
|
||||
|
||||
private String resourceOrCriteria;
|
||||
|
||||
public LimitingResourceQueueElementDTO(
|
||||
LimitingResourceQueueElement element, String orderName,
|
||||
String taskName, Date date) {
|
||||
this.original = element;
|
||||
this.orderName = orderName;
|
||||
this.taskName = taskName;
|
||||
this.date = DATE_FORMAT.format(date);
|
||||
this.hoursToAllocate = element.getIntentedTotalHours();
|
||||
this.resourceOrCriteria = getResourceOrCriteria(element.getResourceAllocation());
|
||||
}
|
||||
|
||||
private String getResourceOrCriteria(ResourceAllocation<?> resourceAllocation) {
|
||||
if (resourceAllocation instanceof SpecificResourceAllocation) {
|
||||
final Resource resource = ((SpecificResourceAllocation) resourceAllocation)
|
||||
.getResource();
|
||||
return (resource != null) ? resource.getName() : "";
|
||||
} else if (resourceAllocation instanceof GenericResourceAllocation) {
|
||||
Set<Criterion> criteria = ((GenericResourceAllocation) resourceAllocation).getCriterions();
|
||||
return Criterion.getNames(criteria);
|
||||
}
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
public LimitingResourceQueueElement getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
public String getOrderName() {
|
||||
return orderName;
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public Integer getHoursToAllocate() {
|
||||
return (hoursToAllocate != null) ? hoursToAllocate : 0;
|
||||
}
|
||||
|
||||
public String getResourceOrCriteria() {
|
||||
return resourceOrCriteria;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void filterBy(Order order) {
|
||||
this.filterBy = order;
|
||||
}
|
||||
|
||||
public void saveQueues() {
|
||||
limitingResourceQueueModel.confirm();
|
||||
notifyUserThatSavingIsDone();
|
||||
}
|
||||
|
||||
private void notifyUserThatSavingIsDone() {
|
||||
try {
|
||||
Messagebox.show(_("Scheduling saved"), _("Information"), Messagebox.OK,
|
||||
Messagebox.INFORMATION);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public LimitingResourceQueueElementsRenderer getLimitingResourceQueueElementsRenderer() {
|
||||
return limitingResourceQueueElementsRenderer;
|
||||
}
|
||||
|
|
@ -174,29 +298,86 @@ public class LimitingResourcesController implements Composer {
|
|||
|
||||
@Override
|
||||
public void render(Row row, Object data) throws Exception {
|
||||
LimitingResourceQueueElement element = (LimitingResourceQueueElement) data;
|
||||
LimitingResourceQueueElementDTO element = (LimitingResourceQueueElementDTO) data;
|
||||
|
||||
row.appendChild(label(getTaskName(element)));
|
||||
row.appendChild(label(getOrderName(element)));
|
||||
row.appendChild(assignButton(element));
|
||||
row.appendChild(label(element.getOrderName()));
|
||||
row.appendChild(label(element.getTaskName()));
|
||||
row.appendChild(label(element.getResourceOrCriteria()));
|
||||
row.appendChild(label(element.getDate()));
|
||||
row.appendChild(label(element.getHoursToAllocate().toString()));
|
||||
row.appendChild(operations(element));
|
||||
row.appendChild(automaticQueueing(element));
|
||||
}
|
||||
|
||||
private Button assignButton(final LimitingResourceQueueElement element) {
|
||||
private Hbox operations(LimitingResourceQueueElementDTO element) {
|
||||
Hbox hbox = new Hbox();
|
||||
hbox.appendChild(assignButton(element));
|
||||
hbox.appendChild(removeButton(element));
|
||||
return hbox;
|
||||
}
|
||||
|
||||
private Button removeButton(final LimitingResourceQueueElementDTO element) {
|
||||
Button result = new Button();
|
||||
result.setLabel("Assign");
|
||||
result.setTooltiptext(_("Assign to queue"));
|
||||
result.setLabel(_("Remove"));
|
||||
result.setTooltiptext(_("Remove limiting resource element"));
|
||||
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
// FIXME: assign element to queue
|
||||
removeUnassignedLimitingResourceQueueElement(element);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private Checkbox automaticQueueing(final LimitingResourceQueueElement element) {
|
||||
private void removeUnassignedLimitingResourceQueueElement(
|
||||
LimitingResourceQueueElementDTO dto) {
|
||||
|
||||
LimitingResourceQueueElement element = dto.getOriginal();
|
||||
limitingResourceQueueModel
|
||||
.removeUnassignedLimitingResourceQueueElement(element);
|
||||
Util.reloadBindings(gridUnassignedLimitingResourceQueueElements);
|
||||
}
|
||||
|
||||
private Button assignButton(
|
||||
final LimitingResourceQueueElementDTO element) {
|
||||
Button result = new Button();
|
||||
result.setLabel(_("Assign"));
|
||||
result.setTooltiptext(_("Assign to queue"));
|
||||
result.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
assignLimitingResourceQueueElement(element);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private void assignLimitingResourceQueueElement(
|
||||
LimitingResourceQueueElementDTO dto) {
|
||||
|
||||
LimitingResourceQueueElement element = dto.getOriginal();
|
||||
if (limitingResourceQueueModel
|
||||
.assignLimitingResourceQueueElement(element)) {
|
||||
Util.reloadBindings(gridUnassignedLimitingResourceQueueElements);
|
||||
limitingResourcesPanel.appendQueueElementToQueue(element);
|
||||
} else {
|
||||
showErrorMessage(_("Cannot allocate selected element. There is not any queue " +
|
||||
"that matches resource allocation criteria at any interval of time"));
|
||||
}
|
||||
}
|
||||
|
||||
private void showErrorMessage(String error) {
|
||||
try {
|
||||
Messagebox.show(error, _("Error"), Messagebox.OK, Messagebox.ERROR);
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Checkbox automaticQueueing(
|
||||
final LimitingResourceQueueElementDTO element) {
|
||||
Checkbox result = new Checkbox();
|
||||
result.setTooltiptext(_("Select for automatic queuing"));
|
||||
return result;
|
||||
|
|
@ -206,22 +387,15 @@ public class LimitingResourcesController implements Composer {
|
|||
return new Label(value);
|
||||
}
|
||||
|
||||
private TaskElement getTask(LimitingResourceQueueElement element) {
|
||||
return element.getResourceAllocation().getTask();
|
||||
}
|
||||
}
|
||||
|
||||
private String getTaskName(LimitingResourceQueueElement element) {
|
||||
return getTask(element).getName();
|
||||
}
|
||||
|
||||
private Order getOrder(LimitingResourceQueueElement element) {
|
||||
return limitingResourceQueueModel.getOrderByTask(getTask(element));
|
||||
}
|
||||
|
||||
private String getOrderName(LimitingResourceQueueElement element) {
|
||||
return getOrder(element).getName();
|
||||
}
|
||||
public List<LimitingResourceQueue> getLimitingResourceQueues() {
|
||||
return limitingResourceQueueModel.getLimitingResourceQueues();
|
||||
}
|
||||
|
||||
public void unschedule(QueueTask task) {
|
||||
limitingResourceQueueModel.unschedule(task.getLimitingResourceQueueElement());
|
||||
Util.reloadBindings(gridUnassignedLimitingResourceQueueElements);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
package org.navalplanner.web.limitingresources;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
|
|
@ -32,7 +31,6 @@ import org.zkoss.zul.Div;
|
|||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.Popup;
|
||||
import org.zkoss.zul.Treecell;
|
||||
import org.zkoss.zul.Treechildren;
|
||||
import org.zkoss.zul.Treeitem;
|
||||
import org.zkoss.zul.TreeitemRenderer;
|
||||
import org.zkoss.zul.Treerow;
|
||||
|
|
@ -41,11 +39,11 @@ import org.zkoss.zul.api.Tree;
|
|||
public class LimitingResourcesLeftPane extends HtmlMacroComponent {
|
||||
|
||||
private MutableTreeModel<LimitingResourceQueue> modelForTree;
|
||||
private final LimitingResourcesList limitingResourcesList;
|
||||
private final QueueListComponent limitingResourcesList;
|
||||
|
||||
public LimitingResourcesLeftPane(
|
||||
MutableTreeModel<LimitingResourceQueue> treeModel,
|
||||
LimitingResourcesList resourceLoadList) {
|
||||
QueueListComponent resourceLoadList) {
|
||||
this.limitingResourcesList = resourceLoadList;
|
||||
this.modelForTree = treeModel;
|
||||
}
|
||||
|
|
@ -87,35 +85,26 @@ public class LimitingResourcesLeftPane extends HtmlMacroComponent {
|
|||
};
|
||||
}
|
||||
|
||||
private void collapse(LimitingResourceQueue line) {
|
||||
// unnecesary
|
||||
limitingResourcesList.collapse(line);
|
||||
}
|
||||
|
||||
private void expand(LimitingResourceQueue line,
|
||||
List<LimitingResourceQueue> closed) {
|
||||
// unnecesary
|
||||
// limitingResourcesList.expand(line, closed);
|
||||
}
|
||||
|
||||
private List<LimitingResourceQueue> calculatedClosedItems(Treeitem item) {
|
||||
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
|
||||
Treechildren treeChildren = item.getTreechildren();
|
||||
if (treeChildren != null) {
|
||||
List<Treeitem> myTreeItems = (List<Treeitem>) treeChildren
|
||||
.getChildren();
|
||||
Iterator<Treeitem> iterator = myTreeItems.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Treeitem child = (Treeitem) iterator.next();
|
||||
if (!child.isOpen()) {
|
||||
result.addAll(getLineChildrenBy(child));
|
||||
} else {
|
||||
result.addAll(calculatedClosedItems(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// private List<LimitingResourceQueue> calculatedClosedItems(Treeitem item)
|
||||
// {
|
||||
// List<LimitingResourceQueue> result = new
|
||||
// ArrayList<LimitingResourceQueue>();
|
||||
// Treechildren treeChildren = item.getTreechildren();
|
||||
// if (treeChildren != null) {
|
||||
// List<Treeitem> myTreeItems = (List<Treeitem>) treeChildren
|
||||
// .getChildren();
|
||||
// Iterator<Treeitem> iterator = myTreeItems.iterator();
|
||||
// while (iterator.hasNext()) {
|
||||
// Treeitem child = (Treeitem) iterator.next();
|
||||
// if (!child.isOpen()) {
|
||||
// result.addAll(getLineChildrenBy(child));
|
||||
// } else {
|
||||
// result.addAll(calculatedClosedItems(child));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
|
||||
private List<LimitingResourceQueue> getLineChildrenBy(Treeitem item) {
|
||||
List<LimitingResourceQueue> result = new ArrayList<LimitingResourceQueue>();
|
||||
|
|
|
|||
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* 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.web.limitingresources;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
|
||||
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
|
||||
import org.zkoss.ganttz.util.MutableTreeModel;
|
||||
import org.zkoss.zk.au.out.AuInvoke;
|
||||
import org.zkoss.zk.ui.HtmlMacroComponent;
|
||||
import org.zkoss.zk.ui.ext.AfterCompose;
|
||||
|
||||
/**
|
||||
* Component to include a list of ResourceLoads inside the ResourcesLoadPanel.
|
||||
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
|
||||
*/
|
||||
public class LimitingResourcesList extends HtmlMacroComponent implements
|
||||
AfterCompose {
|
||||
|
||||
private final IZoomLevelChangedListener zoomListener;
|
||||
|
||||
private Map<LimitingResourceQueue, LimitingResourcesComponent> fromTimeLineToComponent = new HashMap<LimitingResourceQueue, LimitingResourcesComponent>();
|
||||
|
||||
private final MutableTreeModel<LimitingResourceQueue> timelinesTree;
|
||||
|
||||
private List<LimitingResourcesComponent> limitingResourcesComponents = new ArrayList<LimitingResourcesComponent>();
|
||||
|
||||
public LimitingResourcesList(TimeTracker timeTracker,
|
||||
MutableTreeModel<LimitingResourceQueue> timelinesTree) {
|
||||
this.timelinesTree = timelinesTree;
|
||||
zoomListener = adjustTimeTrackerSizeListener();
|
||||
timeTracker.addZoomListener(zoomListener);
|
||||
LimitingResourceQueue current = timelinesTree.getRoot();
|
||||
List<LimitingResourceQueue> toInsert = new ArrayList<LimitingResourceQueue>();
|
||||
fill(timelinesTree, current, toInsert);
|
||||
insertAsComponents(timeTracker, toInsert);
|
||||
}
|
||||
|
||||
private void fill(MutableTreeModel<LimitingResourceQueue> timelinesTree,
|
||||
LimitingResourceQueue current, List<LimitingResourceQueue> result) {
|
||||
final int length = timelinesTree.getChildCount(current);
|
||||
for (int i = 0; i < length; i++) {
|
||||
LimitingResourceQueue child = timelinesTree.getChild(current, i);
|
||||
result.add(child);
|
||||
fill(timelinesTree, child, result);
|
||||
}
|
||||
}
|
||||
|
||||
private IZoomLevelChangedListener adjustTimeTrackerSizeListener() {
|
||||
return new IZoomLevelChangedListener() {
|
||||
|
||||
@Override
|
||||
public void zoomLevelChanged(ZoomLevel detailLevel) {
|
||||
response(null, new AuInvoke(LimitingResourcesList.this,
|
||||
"adjustTimeTrackerSize"));
|
||||
response(null, new AuInvoke(LimitingResourcesList.this,
|
||||
"adjustResourceLoadRows"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void insertAsComponents(TimeTracker timetracker,
|
||||
List<LimitingResourceQueue> children) {
|
||||
for (LimitingResourceQueue LimitingResourceQueue : children) {
|
||||
LimitingResourcesComponent component = LimitingResourcesComponent
|
||||
.create(timetracker, LimitingResourceQueue);
|
||||
limitingResourcesComponents.add(component);
|
||||
appendChild(component);
|
||||
fromTimeLineToComponent.put(LimitingResourceQueue, component);
|
||||
}
|
||||
}
|
||||
|
||||
public void collapse(LimitingResourceQueue line) {
|
||||
}
|
||||
|
||||
private LimitingResourcesComponent getComponentFor(LimitingResourceQueue l) {
|
||||
LimitingResourcesComponent resourceLoadComponent = fromTimeLineToComponent
|
||||
.get(l);
|
||||
return resourceLoadComponent;
|
||||
}
|
||||
|
||||
public void expand(LimitingResourceQueue line,
|
||||
List<LimitingResourceQueue> closed) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompose() {
|
||||
super.afterCompose();
|
||||
for (LimitingResourcesComponent each : limitingResourcesComponents) {
|
||||
each.afterCompose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,12 +20,14 @@
|
|||
|
||||
package org.navalplanner.web.limitingresources;
|
||||
|
||||
import static org.zkoss.ganttz.i18n.I18nHelper._;
|
||||
import static org.navalplanner.web.I18nHelper._;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueDependency;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.navalplanner.business.resources.daos.IResourceDAO;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -43,7 +45,6 @@ import org.zkoss.zk.ui.event.Event;
|
|||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zul.Button;
|
||||
import org.zkoss.zul.Div;
|
||||
import org.zkoss.zul.ListModel;
|
||||
import org.zkoss.zul.Listbox;
|
||||
import org.zkoss.zul.Separator;
|
||||
|
|
@ -59,23 +60,18 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
|
|||
public String getImage();
|
||||
}
|
||||
|
||||
private LimitingResourcesController limitingResourcesController;
|
||||
|
||||
private TimeTrackerComponent timeTrackerComponent;
|
||||
|
||||
private LimitingResourcesLeftPane leftPane;
|
||||
|
||||
private LimitingResourcesList limitingResourcesList;
|
||||
|
||||
private List<LimitingResourceQueue> limitingResourceQueues = new ArrayList<LimitingResourceQueue>();
|
||||
private QueueListComponent queueListComponent;
|
||||
|
||||
private MutableTreeModel<LimitingResourceQueue> treeModel;
|
||||
|
||||
private TimeTracker timeTracker;
|
||||
|
||||
// private LimitingDependencyList dependencyList;
|
||||
|
||||
// private WeakReferencedListeners<IFilterChangedListener> zoomListeners =
|
||||
// WeakReferencedListeners.create();
|
||||
|
||||
private Listbox listZoomLevels;
|
||||
|
||||
@Autowired
|
||||
|
|
@ -85,24 +81,64 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
|
|||
private static final String filterCriterions = _("Filter by criterions");
|
||||
private boolean filterbyResources = true;
|
||||
|
||||
public LimitingResourcesPanel(List<LimitingResourceQueue> groups,
|
||||
TimeTracker timeTracker) {
|
||||
init(groups, timeTracker);
|
||||
private LimitingDependencyList dependencyList = new LimitingDependencyList(this);
|
||||
|
||||
/**
|
||||
* Returns the closest upper {@link LimitingResourcesPanel} instance going
|
||||
* all the way up from comp
|
||||
*
|
||||
* @param comp
|
||||
* @return
|
||||
*/
|
||||
public static LimitingResourcesPanel getLimitingResourcesPanel(Component comp) {
|
||||
if (comp == null) {
|
||||
return null;
|
||||
}
|
||||
if (comp instanceof LimitingResourcesPanel) {
|
||||
return (LimitingResourcesPanel) comp;
|
||||
}
|
||||
return getLimitingResourcesPanel(comp.getParent());
|
||||
}
|
||||
|
||||
public void init(List<LimitingResourceQueue> groups, TimeTracker timeTracker) {
|
||||
this.limitingResourceQueues = groups;
|
||||
public LimitingResourcesPanel(LimitingResourcesController limitingResourcesController,
|
||||
TimeTracker timeTracker) {
|
||||
init(limitingResourcesController, timeTracker);
|
||||
}
|
||||
|
||||
public void init(LimitingResourcesController limitingResourcesController,
|
||||
TimeTracker timeTracker) {
|
||||
this.limitingResourcesController = limitingResourcesController;
|
||||
this.timeTracker = timeTracker;
|
||||
this.setVariable("limitingResourcesController",
|
||||
limitingResourcesController, true);
|
||||
|
||||
treeModel = createModelForTree();
|
||||
timeTrackerComponent = timeTrackerForResourcesLoadPanel(timeTracker);
|
||||
limitingResourcesList = new LimitingResourcesList(timeTracker,
|
||||
queueListComponent = new QueueListComponent(timeTracker,
|
||||
treeModel);
|
||||
|
||||
leftPane = new LimitingResourcesLeftPane(treeModel,
|
||||
limitingResourcesList);
|
||||
queueListComponent);
|
||||
registerNeededScripts();
|
||||
}
|
||||
|
||||
public void appendQueueElementToQueue(LimitingResourceQueueElement element) {
|
||||
queueListComponent.appendQueueElement(element);
|
||||
}
|
||||
|
||||
private MutableTreeModel<LimitingResourceQueue> createModelForTree() {
|
||||
MutableTreeModel<LimitingResourceQueue> result = MutableTreeModel
|
||||
.create(LimitingResourceQueue.class);
|
||||
for (LimitingResourceQueue LimitingResourceQueue : getLimitingResourceQueues()) {
|
||||
result.addToRoot(LimitingResourceQueue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<LimitingResourceQueue> getLimitingResourceQueues() {
|
||||
return limitingResourcesController.getLimitingResourceQueues();
|
||||
}
|
||||
|
||||
public ListModel getFilters() {
|
||||
String[] filters = new String[] { filterResources, filterCriterions };
|
||||
return new SimpleListModel(filters);
|
||||
|
|
@ -175,7 +211,8 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
|
|||
}
|
||||
|
||||
private void registerNeededScripts() {
|
||||
// getScriptsRegister().register(ScriptsRequiredByResourceLoadPanel.class);
|
||||
// getScriptsRegister().register(
|
||||
// ScriptsRequiredByLimitingResourcesPanel.class);
|
||||
}
|
||||
|
||||
private IScriptsRegister getScriptsRegister() {
|
||||
|
|
@ -183,22 +220,12 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
|
|||
.retrieve();
|
||||
}
|
||||
|
||||
private MutableTreeModel<LimitingResourceQueue> createModelForTree() {
|
||||
MutableTreeModel<LimitingResourceQueue> result = MutableTreeModel
|
||||
.create(LimitingResourceQueue.class);
|
||||
for (LimitingResourceQueue LimitingResourceQueue : this.limitingResourceQueues) {
|
||||
result.addToRoot(LimitingResourceQueue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private TimeTrackerComponent timeTrackerForResourcesLoadPanel(
|
||||
TimeTracker timeTracker) {
|
||||
return new TimeTrackerComponent(timeTracker) {
|
||||
@Override
|
||||
protected void scrollHorizontalPercentage(int pixelsDisplacement) {
|
||||
response("", new AuInvoke(limitingResourcesList,
|
||||
response("", new AuInvoke(queueListComponent,
|
||||
"adjustScrollHorizontalPosition", pixelsDisplacement
|
||||
+ ""));
|
||||
}
|
||||
|
|
@ -210,28 +237,19 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
|
|||
|
||||
super.afterCompose();
|
||||
|
||||
// Insert resourcesList left pane component
|
||||
// Insert leftPane component with limitingresources list
|
||||
getFellow("insertionPointLeftPanel").appendChild(leftPane);
|
||||
leftPane.afterCompose();
|
||||
|
||||
// Insert timetracker watermarks and limitingResourcesQueues
|
||||
getFellow("insertionPointRightPanel").appendChild(timeTrackerComponent);
|
||||
getFellow("insertionPointRightPanel")
|
||||
.appendChild(limitingResourcesList);
|
||||
limitingResourcesList.afterCompose();
|
||||
getFellow("insertionPointRightPanel").appendChild(queueListComponent);
|
||||
queueListComponent.afterCompose();
|
||||
|
||||
Div source = new Div();
|
||||
Div destination = new Div();
|
||||
|
||||
LimitingDependencyComponent limitingDependencyComponent = new LimitingDependencyComponent(
|
||||
source, destination);
|
||||
|
||||
LimitingDependencyList dependencyList = new LimitingDependencyList(null);
|
||||
dependencyList.addDependencyComponent(limitingDependencyComponent);
|
||||
|
||||
getFellow("insertionPointRightPanel").appendChild(dependencyList);
|
||||
|
||||
dependencyList.afterCompose();
|
||||
dependencyList = generateDependencyComponentsList();
|
||||
if (dependencyList != null) {
|
||||
dependencyList.afterCompose();
|
||||
getFellow("insertionPointRightPanel").appendChild(dependencyList);
|
||||
}
|
||||
|
||||
// Insert timetracker headers
|
||||
TimeTrackerComponent timeTrackerHeader = createTimeTrackerHeader();
|
||||
|
|
@ -243,20 +261,77 @@ public class LimitingResourcesPanel extends HtmlMacroComponent {
|
|||
listZoomLevels.setSelectedIndex(timeTracker.getDetailLevel().ordinal());
|
||||
}
|
||||
|
||||
private LimitingDependencyList generateDependencyComponentsList() {
|
||||
final Map<LimitingResourceQueueElement, QueueTask> queueElementsMap = queueListComponent
|
||||
.getLimitingResourceElementToQueueTaskMap();
|
||||
|
||||
for (LimitingResourceQueueElement queueElement : queueElementsMap
|
||||
.keySet()) {
|
||||
for (LimitingResourceQueueDependency dependency : queueElement
|
||||
.getDependenciesAsOrigin()) {
|
||||
addDependencyComponent(dependencyList, queueElementsMap, dependency);
|
||||
}
|
||||
}
|
||||
return dependencyList;
|
||||
}
|
||||
|
||||
public void addDependencyComponent(LimitingResourceQueueDependency dependency) {
|
||||
final Map<LimitingResourceQueueElement, QueueTask> queueElementsMap = queueListComponent
|
||||
.getLimitingResourceElementToQueueTaskMap();
|
||||
addDependencyComponent(dependencyList, queueElementsMap, dependency);
|
||||
}
|
||||
|
||||
private void addDependencyComponent(
|
||||
LimitingDependencyList dependencyList,
|
||||
Map<LimitingResourceQueueElement, QueueTask> queueElementsMap,
|
||||
LimitingResourceQueueDependency dependency) {
|
||||
|
||||
LimitingDependencyComponent component = createDependencyComponent(queueElementsMap, dependency);
|
||||
if (component != null) {
|
||||
dependencyList.addDependencyComponent(component);
|
||||
}
|
||||
}
|
||||
|
||||
private LimitingDependencyComponent createDependencyComponent(
|
||||
Map<LimitingResourceQueueElement, QueueTask> queueElementsMap,
|
||||
LimitingResourceQueueDependency dependency) {
|
||||
|
||||
final QueueTask origin = queueElementsMap.get(dependency
|
||||
.getHasAsOrigin());
|
||||
final QueueTask destination = queueElementsMap.get(dependency
|
||||
.getHasAsDestiny());
|
||||
return (origin != null && destination != null) ? new LimitingDependencyComponent(
|
||||
origin, destination)
|
||||
: null;
|
||||
}
|
||||
|
||||
public void clearComponents() {
|
||||
getFellow("insertionPointLeftPanel").getChildren().clear();
|
||||
getFellow("insertionPointRightPanel").getChildren().clear();
|
||||
getFellow("insertionPointTimetracker").getChildren().clear();
|
||||
}
|
||||
|
||||
private TimeTrackerComponent createTimeTrackerHeader() {
|
||||
return new TimeTrackerComponent(
|
||||
timeTracker) {
|
||||
public TimeTrackerComponent getTimeTrackerComponent() {
|
||||
return timeTrackerComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scrollHorizontalPercentage(int pixelsDisplacement) {
|
||||
}
|
||||
private TimeTrackerComponent createTimeTrackerHeader() {
|
||||
return new TimeTrackerComponent(timeTracker) {
|
||||
|
||||
@Override
|
||||
protected void scrollHorizontalPercentage(int pixelsDisplacement) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
public void unschedule(QueueTask task) {
|
||||
limitingResourcesController.unschedule(task);
|
||||
removeQueueTask(task);
|
||||
}
|
||||
|
||||
private void removeQueueTask(QueueTask task) {
|
||||
task.detach();
|
||||
dependencyList.removeDependencyComponents(task);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,16 +27,17 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.exceptions.ValidationException;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.zkoss.ganttz.DatesMapperOnInterval;
|
||||
import org.zkoss.ganttz.IDatesMapper;
|
||||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
|
||||
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
|
||||
import org.zkoss.ganttz.util.MenuBuilder;
|
||||
import org.zkoss.ganttz.util.MenuBuilder.ItemAction;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.ext.AfterCompose;
|
||||
import org.zkoss.zul.Div;
|
||||
|
|
@ -46,21 +47,25 @@ import org.zkoss.zul.impl.XulElement;
|
|||
* This class wraps ResourceLoad data inside an specific HTML Div component.
|
||||
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
|
||||
*/
|
||||
public class LimitingResourcesComponent extends XulElement implements
|
||||
public class QueueComponent extends XulElement implements
|
||||
AfterCompose {
|
||||
|
||||
public static LimitingResourcesComponent create(TimeTracker timeTracker,
|
||||
public static QueueComponent create(TimeTracker timeTracker,
|
||||
LimitingResourceQueue limitingResourceQueue) {
|
||||
return new LimitingResourcesComponent(timeTracker,
|
||||
return new QueueComponent(timeTracker,
|
||||
limitingResourceQueue);
|
||||
}
|
||||
|
||||
private final LimitingResourceQueue limitingResourceQueue;
|
||||
private final TimeTracker timeTracker;
|
||||
private transient IZoomLevelChangedListener zoomChangedListener;
|
||||
private List<Div> queueElementDivs = new ArrayList<Div>();
|
||||
private List<QueueTask> queueTasks = new ArrayList<QueueTask>();
|
||||
|
||||
private LimitingResourcesComponent(final TimeTracker timeTracker,
|
||||
public List<QueueTask> getQueueTasks() {
|
||||
return queueTasks;
|
||||
}
|
||||
|
||||
private QueueComponent(final TimeTracker timeTracker,
|
||||
final LimitingResourceQueue limitingResourceQueue) {
|
||||
this.limitingResourceQueue = limitingResourceQueue;
|
||||
this.timeTracker = timeTracker;
|
||||
|
|
@ -79,64 +84,44 @@ public class LimitingResourcesComponent extends XulElement implements
|
|||
|
||||
private void createChildren(LimitingResourceQueue limitingResourceQueue,
|
||||
IDatesMapper mapper) {
|
||||
List<Div> divs = createDivsForQueueElements(mapper,
|
||||
List<QueueTask> queueTasks = createQueueTasks(mapper,
|
||||
limitingResourceQueue.getLimitingResourceQueueElements());
|
||||
if (divs != null) {
|
||||
for (Div div : divs) {
|
||||
appendChild(div);
|
||||
}
|
||||
queueElementDivs.addAll(divs);
|
||||
if (queueTasks != null) {
|
||||
appendQueueTasks(queueTasks);
|
||||
}
|
||||
}
|
||||
|
||||
public String getResourceName() {
|
||||
return limitingResourceQueue.getResource().getName();
|
||||
private void appendQueueTasks(List<QueueTask> queueTasks) {
|
||||
for (QueueTask each: queueTasks) {
|
||||
appendQueueTask(each);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Div> createDivsForQueueElements(
|
||||
private void appendQueueTask(QueueTask queueTask) {
|
||||
queueTasks.add(queueTask);
|
||||
appendChild(queueTask);
|
||||
}
|
||||
|
||||
private static List<QueueTask> createQueueTasks(
|
||||
IDatesMapper datesMapper,
|
||||
Set<LimitingResourceQueueElement> list) {
|
||||
List<Div> result = new ArrayList<Div>();
|
||||
|
||||
for (LimitingResourceQueueElement queueElement : list) {
|
||||
validateQueueElement(queueElement);
|
||||
result.add(createDivForQueueElement(datesMapper, queueElement));
|
||||
List<QueueTask> result = new ArrayList<QueueTask>();
|
||||
for (LimitingResourceQueueElement each : list) {
|
||||
result.add(createQueueTask(datesMapper, each));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void validateQueueElement(
|
||||
private static QueueTask createQueueTask(IDatesMapper datesMapper, LimitingResourceQueueElement element) {
|
||||
validateQueueElement(element);
|
||||
return createDivForElement(datesMapper, element);
|
||||
}
|
||||
|
||||
private static QueueTask createDivForElement(IDatesMapper datesMapper,
|
||||
LimitingResourceQueueElement queueElement) {
|
||||
if ((queueElement.getStartDate() == null)
|
||||
|| (queueElement.getStartDate() == null)) {
|
||||
throw new ValidationException(_("Invalid queue element"));
|
||||
}
|
||||
}
|
||||
|
||||
private void appendMenu(Div divElement) {
|
||||
if (divElement.getPage() != null) {
|
||||
MenuBuilder<Div> menuBuilder = MenuBuilder.on(divElement.getPage(),
|
||||
queueElementDivs);
|
||||
menuBuilder.item(_("Unassign"), "/common/img/ico_borrar.png",
|
||||
new ItemAction<Div>() {
|
||||
@Override
|
||||
public void onEvent(Div choosen, Event event) {
|
||||
unnasign(choosen);
|
||||
}
|
||||
});
|
||||
divElement.setContext(menuBuilder.createWithoutSettingContext());
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Implement real unnasign operation
|
||||
private void unnasign(Div choosen) {
|
||||
choosen.detach();
|
||||
}
|
||||
|
||||
private static Div createDivForQueueElement(IDatesMapper datesMapper,
|
||||
LimitingResourceQueueElement queueElement) {
|
||||
Div result = new Div();
|
||||
QueueTask result = new QueueTask(queueElement);
|
||||
result.setClass("queue-element");
|
||||
|
||||
result.setTooltiptext(queueElement.getLimitingResourceQueue()
|
||||
|
|
@ -145,19 +130,55 @@ public class LimitingResourcesComponent extends XulElement implements
|
|||
result.setLeft(forCSS(getStartPixels(datesMapper, queueElement)));
|
||||
result.setWidth(forCSS(getWidthPixels(datesMapper, queueElement)));
|
||||
|
||||
result.appendChild(generateNonWorkableShade(datesMapper, queueElement));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int getWidthPixels(IDatesMapper datesMapper,
|
||||
LimitingResourceQueueElement loadPeriod) {
|
||||
LocalDate start = loadPeriod.getStartDate();
|
||||
LocalDate end = loadPeriod.getEndDate();
|
||||
return datesMapper
|
||||
.toPixels(toMilliseconds(end) - toMilliseconds(start));
|
||||
private static Div generateNonWorkableShade(IDatesMapper datesMapper,
|
||||
LimitingResourceQueueElement queueElement) {
|
||||
|
||||
int workableHours = queueElement.getLimitingResourceQueue()
|
||||
.getResource().getCalendar().getCapacityAt(
|
||||
queueElement.getEndDate());
|
||||
|
||||
int shadeWidth = new Long((24 - workableHours)
|
||||
* DatesMapperOnInterval.MILISECONDS_PER_HOUR
|
||||
/ datesMapper.getMilisecondsPerPixel()).intValue();
|
||||
|
||||
int shadeLeft = new Long((workableHours - queueElement.getEndHour())
|
||||
* DatesMapperOnInterval.MILISECONDS_PER_HOUR
|
||||
/ datesMapper.getMilisecondsPerPixel()).intValue()
|
||||
+ shadeWidth;
|
||||
;
|
||||
|
||||
Div notWorkableHoursShade = new Div();
|
||||
notWorkableHoursShade
|
||||
.setTooltiptext(_("Workable capacity for this period ")
|
||||
+ workableHours + _(" hours"));
|
||||
|
||||
notWorkableHoursShade.setContext("");
|
||||
notWorkableHoursShade.setSclass("not-workable-hours");
|
||||
|
||||
notWorkableHoursShade.setStyle("left: " + shadeLeft + "px; width: "
|
||||
+ shadeWidth + "px;");
|
||||
return notWorkableHoursShade;
|
||||
}
|
||||
|
||||
private static long toMilliseconds(LocalDate localDate) {
|
||||
return localDate.toDateMidnight().getMillis();
|
||||
private static int getWidthPixels(IDatesMapper datesMapper,
|
||||
LimitingResourceQueueElement queueElement) {
|
||||
return datesMapper.toPixels(getEndMillis(queueElement)
|
||||
- getStartMillis(queueElement));
|
||||
}
|
||||
|
||||
private static long getStartMillis(LimitingResourceQueueElement queueElement) {
|
||||
return queueElement.getStartDate().toDateMidnight().getMillis()
|
||||
+ (queueElement.getStartHour() * DatesMapperOnInterval.MILISECONDS_PER_HOUR);
|
||||
}
|
||||
|
||||
private static long getEndMillis(LimitingResourceQueueElement queueElement) {
|
||||
return queueElement.getEndDate().toDateMidnight().getMillis()
|
||||
+ (queueElement.getEndHour() * DatesMapperOnInterval.MILISECONDS_PER_HOUR);
|
||||
}
|
||||
|
||||
private static String forCSS(int pixels) {
|
||||
|
|
@ -166,12 +187,58 @@ public class LimitingResourcesComponent extends XulElement implements
|
|||
|
||||
private static int getStartPixels(IDatesMapper datesMapper,
|
||||
LimitingResourceQueueElement queueElement) {
|
||||
return datesMapper.toPixels(queueElement.getStartDate().toDateMidnight()
|
||||
.toDate());
|
||||
return datesMapper
|
||||
.toPixelsAbsolute((queueElement.getStartDate().toDateMidnight()
|
||||
.getMillis() + queueElement.getStartHour()
|
||||
* DatesMapperOnInterval.MILISECONDS_PER_HOUR));
|
||||
}
|
||||
|
||||
public void appendQueueElement(LimitingResourceQueueElement element) {
|
||||
QueueTask queueTask = createQueueTask(element);
|
||||
appendQueueTask(queueTask);
|
||||
appendMenu(queueTask);
|
||||
}
|
||||
|
||||
private QueueTask createQueueTask(LimitingResourceQueueElement element) {
|
||||
validateQueueElement(element);
|
||||
return createDivForElement(timeTracker.getMapper(), element);
|
||||
}
|
||||
|
||||
public String getResourceName() {
|
||||
return limitingResourceQueue.getResource().getName();
|
||||
}
|
||||
|
||||
private static void validateQueueElement(
|
||||
LimitingResourceQueueElement queueElement) {
|
||||
if ((queueElement.getStartDate() == null)
|
||||
|| (queueElement.getEndDate() == null)) {
|
||||
throw new ValidationException(_("Invalid queue element"));
|
||||
}
|
||||
}
|
||||
|
||||
private void appendMenu(QueueTask divElement) {
|
||||
if (divElement.getPage() != null) {
|
||||
MenuBuilder<QueueTask> menuBuilder = MenuBuilder.on(divElement
|
||||
.getPage(), divElement);
|
||||
menuBuilder.item(_("Unassign"), "/common/img/ico_borrar.png",
|
||||
new ItemAction<QueueTask>() {
|
||||
@Override
|
||||
public void onEvent(QueueTask choosen, Event event) {
|
||||
unnasign(choosen);
|
||||
}
|
||||
});
|
||||
divElement.setContext(menuBuilder.createWithoutSettingContext());
|
||||
}
|
||||
}
|
||||
|
||||
private void unnasign(QueueTask choosen) {
|
||||
final LimitingResourcesPanel panel = LimitingResourcesPanel
|
||||
.getLimitingResourcesPanel(choosen.getParent());
|
||||
panel.unschedule(choosen);
|
||||
}
|
||||
|
||||
private void appendContextMenus() {
|
||||
for (Div each : queueElementDivs) {
|
||||
for (QueueTask each : queueTasks) {
|
||||
appendMenu(each);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* 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.web.limitingresources;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueDependency;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.navalplanner.business.resources.entities.LimitingResourceQueue;
|
||||
import org.zkoss.ganttz.timetracker.TimeTracker;
|
||||
import org.zkoss.ganttz.timetracker.zoom.IZoomLevelChangedListener;
|
||||
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
|
||||
import org.zkoss.ganttz.util.MutableTreeModel;
|
||||
import org.zkoss.zk.au.out.AuInvoke;
|
||||
import org.zkoss.zk.ui.HtmlMacroComponent;
|
||||
import org.zkoss.zk.ui.ext.AfterCompose;
|
||||
|
||||
/**
|
||||
* Component to include a list of {@link LimitingResourceQueue} inside the {@link LimitingResourcesPanel}
|
||||
*
|
||||
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
|
||||
* @author Diego Pino Garcia <dpino@igalia.com>
|
||||
*/
|
||||
public class QueueListComponent extends HtmlMacroComponent implements
|
||||
AfterCompose {
|
||||
|
||||
private final IZoomLevelChangedListener zoomListener;
|
||||
|
||||
private MutableTreeModel<LimitingResourceQueue> model;
|
||||
|
||||
private TimeTracker timeTracker;
|
||||
|
||||
private Map<LimitingResourceQueue, QueueComponent> fromQueueToComponent = new HashMap<LimitingResourceQueue, QueueComponent>();
|
||||
|
||||
public QueueListComponent(TimeTracker timeTracker,
|
||||
MutableTreeModel<LimitingResourceQueue> timelinesTree) {
|
||||
|
||||
this.model = timelinesTree;
|
||||
|
||||
zoomListener = adjustTimeTrackerSizeListener();
|
||||
timeTracker.addZoomListener(zoomListener);
|
||||
this.timeTracker = timeTracker;
|
||||
|
||||
insertAsComponents(timelinesTree.asList());
|
||||
}
|
||||
|
||||
private void insertAsComponents(List<LimitingResourceQueue> children) {
|
||||
for (LimitingResourceQueue each : children) {
|
||||
insertAsComponent(each);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertAsComponent(LimitingResourceQueue queue) {
|
||||
QueueComponent component = QueueComponent.create(timeTracker, queue);
|
||||
this.appendChild(component);
|
||||
fromQueueToComponent.put(queue, component);
|
||||
}
|
||||
|
||||
public void setModel(MutableTreeModel<LimitingResourceQueue> model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
fromQueueToComponent.clear();
|
||||
this.getChildren().clear();
|
||||
insertAsComponents(model.asList());
|
||||
super.invalidate();
|
||||
}
|
||||
|
||||
public void appendQueueElement(LimitingResourceQueueElement element) {
|
||||
QueueComponent queueComponent = fromQueueToComponent.get(element
|
||||
.getLimitingResourceQueue());
|
||||
queueComponent.appendQueueElement(element);
|
||||
addDependenciesInPanel(element);
|
||||
}
|
||||
|
||||
private void addDependenciesInPanel(LimitingResourceQueueElement element) {
|
||||
LimitingResourcesPanel panel = LimitingResourcesPanel
|
||||
.getLimitingResourcesPanel(this);
|
||||
for (LimitingResourceQueueDependency each : element
|
||||
.getDependenciesAsDestiny()) {
|
||||
panel.addDependencyComponent(each);
|
||||
}
|
||||
for (LimitingResourceQueueDependency each : element
|
||||
.getDependenciesAsOrigin()) {
|
||||
panel.addDependencyComponent(each);
|
||||
}
|
||||
}
|
||||
|
||||
private IZoomLevelChangedListener adjustTimeTrackerSizeListener() {
|
||||
return new IZoomLevelChangedListener() {
|
||||
|
||||
@Override
|
||||
public void zoomLevelChanged(ZoomLevel detailLevel) {
|
||||
response(null, new AuInvoke(QueueListComponent.this,
|
||||
"adjustTimeTrackerSize"));
|
||||
response(null, new AuInvoke(QueueListComponent.this,
|
||||
"adjustResourceLoadRows"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompose() {
|
||||
super.afterCompose();
|
||||
for (QueueComponent each : fromQueueToComponent.values()) {
|
||||
each.afterCompose();
|
||||
}
|
||||
}
|
||||
|
||||
public List<QueueTask> getQueueTasks() {
|
||||
List<QueueTask> result = new ArrayList<QueueTask>();
|
||||
for (QueueComponent each : fromQueueToComponent.values()) {
|
||||
result.addAll(each.getQueueTasks());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<LimitingResourceQueueElement, QueueTask> getLimitingResourceElementToQueueTaskMap() {
|
||||
Map<LimitingResourceQueueElement, QueueTask> result = new HashMap<LimitingResourceQueueElement, QueueTask>();
|
||||
for (QueueTask each : getQueueTasks()) {
|
||||
result.put(each.getLimitingResourceQueueElement(), each);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* This file is part of NavalPlan
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* 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.web.limitingresources;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
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.Div;
|
||||
|
||||
public class QueueTask extends Div {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(QueueTask.class);
|
||||
|
||||
private final LocalDate start;
|
||||
|
||||
private final LocalDate end;
|
||||
|
||||
private final LimitingResourceQueueElement element;
|
||||
|
||||
public QueueTask(LimitingResourceQueueElement element) {
|
||||
Validate.notNull(element.getStartDate());
|
||||
Validate.notNull(element.getEndDate());
|
||||
Validate
|
||||
.isTrue(!(element.getStartDate()).isAfter(element.getEndDate()));
|
||||
this.start = element.getStartDate();
|
||||
this.end = element.getEndDate();
|
||||
this.element = element;
|
||||
setAction("onmouseover: zkLimitingDependencies.showDependenciesForQueueElement('"
|
||||
+ getUuid()
|
||||
+ "');onmouseout: zkLimitingDependencies.hideDependenciesForQueueElement('"
|
||||
+ getUuid() + "')");
|
||||
|
||||
final String taskUid = this.getUuid();
|
||||
this.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
Clients
|
||||
.evalJavaScript("zkLimitingDependencies.toggleDependenciesForQueueElement('"
|
||||
+ taskUid + "')");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LocalDate getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public LocalDate getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this);
|
||||
}
|
||||
|
||||
public LimitingResourceQueueElement getLimitingResourceQueueElement() {
|
||||
return element;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
package org.navalplanner.web.limitingresources;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
|
@ -33,7 +32,6 @@ import org.apache.commons.lang.Validate;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.SpecificDayAssignment;
|
||||
|
|
@ -42,8 +40,6 @@ import org.navalplanner.business.resources.entities.Criterion;
|
|||
import org.navalplanner.business.resources.entities.CriterionCompounder;
|
||||
import org.navalplanner.business.resources.entities.ICriterion;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.zkoss.ganttz.data.limitingresource.QueueTask;
|
||||
import org.zkoss.ganttz.data.resourceload.LoadLevel;
|
||||
|
||||
interface QueueTaskGeneratorFactory {
|
||||
QueueTaskGenerator create(ResourceAllocation<?> allocation);
|
||||
|
|
@ -201,24 +197,8 @@ abstract class QueueTaskGenerator {
|
|||
&& other.end.compareTo(end) <= 0;
|
||||
}
|
||||
|
||||
public QueueTask build() {
|
||||
return new QueueTask(start, end, getTotalWorkHours(),
|
||||
getHoursAssigned(), new LoadLevel(
|
||||
calculateLoadPercentage()));
|
||||
}
|
||||
|
||||
protected abstract int getTotalWorkHours();
|
||||
|
||||
private int calculateLoadPercentage() {
|
||||
final int totalResourceWorkHours = getTotalWorkHours();
|
||||
int assigned = getHoursAssigned();
|
||||
if (totalResourceWorkHours == 0) {
|
||||
return assigned == 0 ? 0 : Integer.MAX_VALUE;
|
||||
}
|
||||
double proportion = assigned / (double) totalResourceWorkHours;
|
||||
return new BigDecimal(proportion).scaleByPowerOfTen(2).intValue();
|
||||
}
|
||||
|
||||
protected abstract int getHoursAssigned();
|
||||
|
||||
protected final int sumAllocations() {
|
||||
|
|
@ -344,22 +324,4 @@ class QueueTaskGeneratorOnCriterion extends QueueTaskGenerator {
|
|||
|
||||
private Map<Resource, List<SpecificDayAssignment>> specificByResourceCached = new HashMap<Resource, List<SpecificDayAssignment>>();
|
||||
|
||||
private List<SpecificDayAssignment> getSpecificOrderedAssignmentsFor(
|
||||
Resource resource) {
|
||||
if (!specificByResourceCached.containsKey(resource)) {
|
||||
specificByResourceCached.put(resource, DayAssignment
|
||||
.specific(DayAssignment.orderedByDay(resource
|
||||
.getAssignments())));
|
||||
}
|
||||
return specificByResourceCached.get(resource);
|
||||
}
|
||||
|
||||
private int sum(List<SpecificDayAssignment> specific) {
|
||||
int result = 0;
|
||||
for (SpecificDayAssignment s : specific) {
|
||||
result += s.getHours();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ import org.zkoss.zul.Listcell;
|
|||
import org.zkoss.zul.Listitem;
|
||||
import org.zkoss.zul.ListitemRenderer;
|
||||
import org.zkoss.zul.Radio;
|
||||
import org.zkoss.zul.Tabbox;
|
||||
import org.zkoss.zul.XYModel;
|
||||
|
||||
/**
|
||||
|
|
@ -94,6 +95,8 @@ public class ManageOrderElementAdvancesController extends
|
|||
|
||||
private Component messagesContainerAdvances;
|
||||
|
||||
private Tabbox tabboxOrderElement;
|
||||
|
||||
@Override
|
||||
public void doAfterCompose(Component comp) throws Exception {
|
||||
super.doAfterCompose(comp);
|
||||
|
|
@ -139,6 +142,7 @@ public class ManageOrderElementAdvancesController extends
|
|||
Level.ERROR, e.getMessage());
|
||||
LOG.error(_("Couldn't find element: {0}", e.getKey()), e);
|
||||
}
|
||||
increaseScreenHeight();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -165,6 +169,20 @@ public class ManageOrderElementAdvancesController extends
|
|||
return orderElementModel.getOrderElement();
|
||||
}
|
||||
|
||||
private void increaseScreenHeight() {
|
||||
if (tabboxOrderElement != null) {
|
||||
tabboxOrderElement.setHeight("680px");
|
||||
tabboxOrderElement.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetScreenHeight() {
|
||||
if (tabboxOrderElement != null) {
|
||||
tabboxOrderElement.setHeight("620px");
|
||||
tabboxOrderElement.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetAdvancesGrid() {
|
||||
manageOrderElementAdvancesModel.resetAdvanceAssignment();
|
||||
this.indexSelectedItem = -1;
|
||||
|
|
@ -173,6 +191,7 @@ public class ManageOrderElementAdvancesController extends
|
|||
|
||||
private void reloadAdvances() {
|
||||
Util.reloadBindings(self);
|
||||
resetScreenHeight();
|
||||
if (indexSelectedItem > -1) {
|
||||
editAdvances.setSelectedItem(editAdvances
|
||||
.getItemAtIndex(indexSelectedItem));
|
||||
|
|
@ -522,7 +541,8 @@ public class ManageOrderElementAdvancesController extends
|
|||
new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
setReportGlobalAdvance(listItem);
|
||||
resetScreenHeight();
|
||||
setReportGlobalAdvance(listItem);
|
||||
}
|
||||
});
|
||||
Listcell listCell = new Listcell();
|
||||
|
|
@ -1135,6 +1155,7 @@ public class ManageOrderElementAdvancesController extends
|
|||
break;
|
||||
}
|
||||
if (!StringUtils.isBlank(message)) {
|
||||
increaseScreenHeight();
|
||||
messagesForUser.showMessage(Level.ERROR, message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -320,7 +320,6 @@ public class ManageOrderElementAdvancesModel implements
|
|||
@Override
|
||||
public void cleanAdvance(DirectAdvanceAssignment advanceAssignment) {
|
||||
if (advanceAssignment != null) {
|
||||
advanceAssignment.setReportGlobalAdvance(false);
|
||||
advanceAssignment.getAdvanceMeasurements().clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@
|
|||
|
||||
package org.navalplanner.web.orders;
|
||||
|
||||
import static org.navalplanner.web.I18nHelper._;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.orders.entities.OrderElement;
|
||||
import org.navalplanner.business.orders.entities.OrderLine;
|
||||
|
|
@ -109,6 +112,15 @@ public class OrderElementController extends GenericForwardComposer {
|
|||
}
|
||||
}
|
||||
|
||||
public String getOrderElementName() {
|
||||
String name = "";
|
||||
if ((getOrderElement() != null)
|
||||
&& (!StringUtils.isBlank(getOrderElement().getName()))) {
|
||||
name = ": " + getOrderElement().getName();
|
||||
}
|
||||
return _("Edit order element {0}", name);
|
||||
}
|
||||
|
||||
public void setupManageOrderElementAdvancesController()
|
||||
throws Exception {
|
||||
if (manageOrderElementAdvancesController == null) {
|
||||
|
|
@ -188,6 +200,7 @@ public class OrderElementController extends GenericForwardComposer {
|
|||
assignedTaskQualityFormsController = null;
|
||||
|
||||
try {
|
||||
((Window) self).setTitle(getOrderElementName());
|
||||
((Window) self).doModal();
|
||||
} catch (SuspendNotAllowedException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
|
|||
|
|
@ -60,14 +60,12 @@ import org.zkoss.zk.ui.Executions;
|
|||
import org.zkoss.zk.ui.WrongValueException;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zk.ui.event.KeyEvent;
|
||||
import org.zkoss.zul.Button;
|
||||
import org.zkoss.zul.Constraint;
|
||||
import org.zkoss.zul.Datebox;
|
||||
import org.zkoss.zul.Hbox;
|
||||
import org.zkoss.zul.Intbox;
|
||||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.Messagebox;
|
||||
import org.zkoss.zul.Tab;
|
||||
import org.zkoss.zul.Textbox;
|
||||
|
|
@ -320,7 +318,7 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
|
|||
}
|
||||
|
||||
private void registerKeyboardListener(final InputElement inputElement) {
|
||||
inputElement.setCtrlKeys("#up#down#left#right");
|
||||
inputElement.setCtrlKeys("#up#down");
|
||||
inputElement.addEventListener("onCtrlKey", new EventListener() {
|
||||
private Treerow treerow = getCurrentTreeRow();
|
||||
|
||||
|
|
|
|||
|
|
@ -195,20 +195,14 @@ public class OrderPredicate implements IPredicate {
|
|||
if ((initDate == null) && (startDate == null)) {
|
||||
return true;
|
||||
}
|
||||
return isInTheRangeFilterDates(initDate);
|
||||
return isLowerToFinishDate(initDate, finishDate);
|
||||
}
|
||||
|
||||
protected boolean acceptFinishDate(Date deadLine) {
|
||||
if ((deadLine == null) && (finishDate == null)) {
|
||||
return true;
|
||||
}
|
||||
return isInTheRangeFilterDates(deadLine);
|
||||
}
|
||||
|
||||
private boolean isInTheRangeFilterDates(Date date) {
|
||||
// Check if date is into interval between the startdate and finish date
|
||||
return (isGreaterToStartDate(date, startDate) && isLowerToFinishDate(
|
||||
date, finishDate));
|
||||
return isGreaterToStartDate(deadLine, startDate);
|
||||
}
|
||||
|
||||
private boolean isGreaterToStartDate(Date date, Date startDate) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
package org.navalplanner.web.planner;
|
||||
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.scenarios.entities.Scenario;
|
||||
import org.zkoss.ganttz.adapters.IAdapterToTaskFundamentalProperties;
|
||||
|
|
@ -31,14 +30,5 @@ import org.zkoss.ganttz.adapters.IAdapterToTaskFundamentalProperties;
|
|||
*/
|
||||
public interface ITaskElementAdapter extends IAdapterToTaskFundamentalProperties<TaskElement>{
|
||||
|
||||
public interface IOnMoveListener {
|
||||
public void moved(TaskElement taskElement);
|
||||
}
|
||||
|
||||
public void addListener(IOnMoveListener moveListener);
|
||||
|
||||
public void removeListener(IOnMoveListener moveListener);
|
||||
|
||||
void initialize(Order order, Scenario scenario);
|
||||
|
||||
void useScenario(Scenario scenario);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import static org.navalplanner.web.I18nHelper._;
|
|||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
|
@ -35,7 +36,6 @@ import java.util.Set;
|
|||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.Hibernate;
|
||||
|
|
@ -44,8 +44,8 @@ import org.navalplanner.business.common.IAdHocTransactionService;
|
|||
import org.navalplanner.business.common.IOnTransaction;
|
||||
import org.navalplanner.business.labels.entities.Label;
|
||||
import org.navalplanner.business.orders.daos.IOrderElementDAO;
|
||||
import org.navalplanner.business.orders.entities.Order;
|
||||
import org.navalplanner.business.orders.entities.OrderElement;
|
||||
import org.navalplanner.business.orders.entities.OrderStatusEnum;
|
||||
import org.navalplanner.business.planner.daos.IResourceAllocationDAO;
|
||||
import org.navalplanner.business.planner.daos.ITaskElementDAO;
|
||||
import org.navalplanner.business.planner.entities.Dependency;
|
||||
|
|
@ -86,8 +86,6 @@ public class TaskElementAdapter implements ITaskElementAdapter {
|
|||
|
||||
private static final Log LOG = LogFactory.getLog(TaskElementAdapter.class);
|
||||
|
||||
private Order order;
|
||||
|
||||
@Autowired
|
||||
private IAdHocTransactionService transactionService;
|
||||
|
||||
|
|
@ -106,13 +104,11 @@ public class TaskElementAdapter implements ITaskElementAdapter {
|
|||
@Autowired
|
||||
private IResourceAllocationDAO resourceAllocationDAO;
|
||||
|
||||
private List<IOnMoveListener> listeners = new ArrayList<IOnMoveListener>();
|
||||
|
||||
private Scenario scenario;
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(Order order, Scenario scenario) {
|
||||
this.order = order;
|
||||
public void useScenario(Scenario scenario) {
|
||||
this.scenario = scenario;
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +165,6 @@ public class TaskElementAdapter implements ITaskElementAdapter {
|
|||
public Long execute() {
|
||||
stepsBeforePossibleReallocation();
|
||||
Long result = setBeginDateInsideTransaction(beginDate);
|
||||
fireTaskElementMoved(taskElement);
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
|
@ -220,7 +215,6 @@ public class TaskElementAdapter implements ITaskElementAdapter {
|
|||
return null;
|
||||
}
|
||||
});
|
||||
fireTaskElementMoved(taskElement);
|
||||
}
|
||||
|
||||
private void updateEndDate(long lengthMilliseconds) {
|
||||
|
|
@ -481,6 +475,7 @@ public class TaskElementAdapter implements ITaskElementAdapter {
|
|||
result.append(_("Hours invested") + ": ").append(
|
||||
getHoursAdvancePercentage().multiply(new BigDecimal(100)))
|
||||
.append("% <br/>");
|
||||
result.append(_("State") +": ").append(getOrderState());
|
||||
String labels = buildLabelsText();
|
||||
if (!labels.equals("")) {
|
||||
result.append("<div class='tooltip-labels'>" + _("Labels")
|
||||
|
|
@ -489,6 +484,29 @@ public class TaskElementAdapter implements ITaskElementAdapter {
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
private String getOrderState() {
|
||||
String cssClass;
|
||||
OrderStatusEnum state = taskElement.getOrderElement().getOrder().getState();
|
||||
|
||||
if(Arrays.asList(OrderStatusEnum.ACCEPTED,
|
||||
OrderStatusEnum.OFFERED,OrderStatusEnum.STARTED,
|
||||
OrderStatusEnum.SUBCONTRACTED_PENDING_ORDER)
|
||||
.contains(state)) {
|
||||
if(taskElement.getAssignedStatus() == "assigned") {
|
||||
cssClass="order-open-assigned";
|
||||
}
|
||||
else {
|
||||
cssClass="order-open-unassigned";
|
||||
}
|
||||
}
|
||||
else {
|
||||
cssClass="order-closed";
|
||||
}
|
||||
return "<font class='" + cssClass + "'>"
|
||||
+ state.toString()
|
||||
+ "</font>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Constraint<Date>> getStartConstraints() {
|
||||
if (taskElement instanceof Task) {
|
||||
|
|
@ -540,6 +558,20 @@ public class TaskElementAdapter implements ITaskElementAdapter {
|
|||
return taskElement.isSubcontracted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLimiting() {
|
||||
return taskElement.isLimiting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLimitingAndHasDayAssignments() {
|
||||
return taskElement.isLimitingAndHasDayAssignments();
|
||||
}
|
||||
|
||||
public boolean hasConsolidations() {
|
||||
return taskElement.hasConsolidations();
|
||||
}
|
||||
|
||||
private void stepsBeforePossibleReallocation() {
|
||||
taskDAO.reattach(taskElement);
|
||||
reattachAllResourcesForTask();
|
||||
|
|
@ -637,21 +669,4 @@ public class TaskElementAdapter implements ITaskElementAdapter {
|
|||
type);
|
||||
}
|
||||
|
||||
private void fireTaskElementMoved(TaskElement taskElement) {
|
||||
for (IOnMoveListener moveListener : listeners) {
|
||||
moveListener.moved(taskElement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(IOnMoveListener moveListener) {
|
||||
Validate.notNull(moveListener);
|
||||
listeners.add(moveListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(IOnMoveListener moveListener) {
|
||||
listeners.remove(moveListener);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import org.navalplanner.business.planner.entities.ResourceAllocation;
|
|||
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.TaskElement;
|
||||
import org.navalplanner.business.planner.entities.StretchesFunction.Type;
|
||||
import org.navalplanner.business.resources.entities.Criterion;
|
||||
import org.navalplanner.web.common.IMessagesForUser;
|
||||
import org.navalplanner.web.common.Level;
|
||||
import org.navalplanner.web.common.MessagesForUser;
|
||||
|
|
@ -754,15 +755,19 @@ public class AdvancedAllocationController extends GenericForwardComposer {
|
|||
}
|
||||
rowsCached = new ArrayList<Row>();
|
||||
for (AllocationInput allocationInput : allocationInputs) {
|
||||
Row groupingRow = buildGroupingRow(allocationInput);
|
||||
groupingRows.put(allocationInput, groupingRow);
|
||||
rowsCached.add(groupingRow);
|
||||
List<Row> genericRows = genericRows(allocationInput);
|
||||
groupingRow.listenTo(genericRows);
|
||||
rowsCached.addAll(genericRows);
|
||||
List<Row> specificRows = specificRows(allocationInput);
|
||||
groupingRow.listenTo(specificRows);
|
||||
rowsCached.addAll(specificRows);
|
||||
if (allocationInput.getAggregate()
|
||||
.getAllocationsSortedByStartDate().isEmpty()) {
|
||||
} else {
|
||||
Row groupingRow = buildGroupingRow(allocationInput);
|
||||
groupingRows.put(allocationInput, groupingRow);
|
||||
rowsCached.add(groupingRow);
|
||||
List<Row> genericRows = genericRows(allocationInput);
|
||||
groupingRow.listenTo(genericRows);
|
||||
rowsCached.addAll(genericRows);
|
||||
List<Row> specificRows = specificRows(allocationInput);
|
||||
groupingRow.listenTo(specificRows);
|
||||
rowsCached.addAll(specificRows);
|
||||
}
|
||||
}
|
||||
return filterRows(rowsCached);
|
||||
}
|
||||
|
|
@ -808,7 +813,8 @@ public class AdvancedAllocationController extends GenericForwardComposer {
|
|||
specificResourceAllocation.getResource()
|
||||
.getName(), 1, Arrays
|
||||
.asList(specificResourceAllocation), specificResourceAllocation
|
||||
.getResource().getShortDescription());
|
||||
.getResource().getShortDescription(),
|
||||
specificResourceAllocation.getResource().isLimitingResource());
|
||||
}
|
||||
|
||||
private List<Row> genericRows(AllocationInput allocationInput) {
|
||||
|
|
@ -824,10 +830,10 @@ public class AdvancedAllocationController extends GenericForwardComposer {
|
|||
private Row buildGenericRow(
|
||||
GenericResourceAllocation genericResourceAllocation,
|
||||
Restriction restriction) {
|
||||
return Row.createRow(messages, restriction,
|
||||
ResourceLoadModel
|
||||
.getName(genericResourceAllocation.getCriterions()), 1, Arrays
|
||||
.asList(genericResourceAllocation));
|
||||
return Row.createRow(messages, restriction, Criterion
|
||||
.getNames(genericResourceAllocation.getCriterions()), 1, Arrays
|
||||
.asList(genericResourceAllocation), genericResourceAllocation
|
||||
.isLimiting());
|
||||
}
|
||||
|
||||
private Row buildGroupingRow(AllocationInput allocationInput) {
|
||||
|
|
@ -835,7 +841,7 @@ public class AdvancedAllocationController extends GenericForwardComposer {
|
|||
.createRestriction();
|
||||
String taskName = _("{0}", allocationInput.getTaskName());
|
||||
Row groupingRow = Row.createRow(messages, restriction, taskName, 0,
|
||||
allocationInput.getAllocationsSortedByStartDate());
|
||||
allocationInput.getAllocationsSortedByStartDate(), false);
|
||||
return groupingRow;
|
||||
}
|
||||
|
||||
|
|
@ -951,16 +957,19 @@ class Row {
|
|||
AdvancedAllocationController.Restriction restriction,
|
||||
String name, int level,
|
||||
List<? extends ResourceAllocation<?>> allocations,
|
||||
String description) {
|
||||
Row newRow = new Row(messages, restriction, name, level, allocations);
|
||||
String description, boolean limiting) {
|
||||
Row newRow = new Row(messages, restriction, name, level, allocations,
|
||||
limiting);
|
||||
newRow.setDescription(description);
|
||||
return newRow;
|
||||
}
|
||||
|
||||
static Row createRow(IMessagesForUser messages,
|
||||
AdvancedAllocationController.Restriction restriction, String name,
|
||||
int level, List<? extends ResourceAllocation<?>> allocations) {
|
||||
return new Row(messages, restriction, name, level, allocations);
|
||||
int level, List<? extends ResourceAllocation<?>> allocations,
|
||||
boolean limiting) {
|
||||
return new Row(messages, restriction, name, level, allocations,
|
||||
limiting);
|
||||
}
|
||||
|
||||
public void markErrorOnTotal(String message) {
|
||||
|
|
@ -1040,11 +1049,12 @@ class Row {
|
|||
}
|
||||
|
||||
private Component buildAllHours() {
|
||||
return isGroupingRow() ? new Label() : noNegativeIntbox();
|
||||
return (isGroupingRow() || isLimiting) ? new Label()
|
||||
: noNegativeIntbox();
|
||||
}
|
||||
|
||||
private void addListenerIfNeeded(Component allHoursComponent) {
|
||||
if (isGroupingRow()) {
|
||||
if (isGroupingRow() || isLimiting) {
|
||||
return;
|
||||
}
|
||||
final Intbox intbox = (Intbox) allHoursComponent;
|
||||
|
|
@ -1072,7 +1082,7 @@ class Row {
|
|||
}
|
||||
|
||||
private void reloadAllHours() {
|
||||
if (isGroupingRow()) {
|
||||
if (isGroupingRow() || isLimiting) {
|
||||
Label label = (Label) allHoursInput;
|
||||
int totalHours = aggregate.getTotalHours();
|
||||
if (label != null) {
|
||||
|
|
@ -1085,12 +1095,17 @@ class Row {
|
|||
} else {
|
||||
Intbox intbox = (Intbox) allHoursInput;
|
||||
intbox.setValue(aggregate.getTotalHours());
|
||||
if (isLimiting) {
|
||||
intbox.setDisabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component getFunction() {
|
||||
if (isGroupingRow()) {
|
||||
return new Label();
|
||||
} else if (isLimiting) {
|
||||
return new Label(_("Limiting assignment"));
|
||||
} else {
|
||||
Hbox hbox = new Hbox();
|
||||
|
||||
|
|
@ -1238,6 +1253,8 @@ class Row {
|
|||
private IAssignmentFunctionConfiguration[] functions = { none,
|
||||
defaultStrechesFunction, strechesWithInterpolation };
|
||||
|
||||
private boolean isLimiting;
|
||||
|
||||
private Combobox getAssignmentFunctionsCombo() {
|
||||
AssignmentFunction assignmentFunction = getAllocation()
|
||||
.getAssignmentFunction();
|
||||
|
|
@ -1289,11 +1306,13 @@ class Row {
|
|||
private Row(IMessagesForUser messages,
|
||||
AdvancedAllocationController.Restriction restriction,
|
||||
String name, int level,
|
||||
List<? extends ResourceAllocation<?>> allocations) {
|
||||
List<? extends ResourceAllocation<?>> allocations,
|
||||
boolean limiting) {
|
||||
this.messages = messages;
|
||||
this.restriction = restriction;
|
||||
this.name = name;
|
||||
this.level = level;
|
||||
this.isLimiting = limiting;
|
||||
this.aggregate = new AggregateOfResourceAllocations(
|
||||
new ArrayList<ResourceAllocation<?>>(allocations));
|
||||
}
|
||||
|
|
@ -1358,6 +1377,9 @@ class Row {
|
|||
} else {
|
||||
Intbox intbox = (Intbox) component;
|
||||
intbox.setValue(getHoursForDetailItem(item));
|
||||
if (isLimiting) {
|
||||
intbox.setDisabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ import org.navalplanner.web.planner.allocation.ResourceAllocationController.Deri
|
|||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zul.Checkbox;
|
||||
import org.zkoss.zul.Constraint;
|
||||
import org.zkoss.zul.Decimalbox;
|
||||
import org.zkoss.zul.Detail;
|
||||
|
|
@ -73,7 +72,7 @@ public abstract class AllocationRow {
|
|||
ResourcesPerDay[] resourcesPerDay) {
|
||||
int i = 0;
|
||||
for (AllocationRow each : rows) {
|
||||
each.setResourcesPerDay(resourcesPerDay[i++]);
|
||||
each.setNonConsolidatedResourcesPerDay(resourcesPerDay[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +168,19 @@ public abstract class AllocationRow {
|
|||
|
||||
private String name;
|
||||
|
||||
private ResourcesPerDay resourcesPerDay;
|
||||
private int originalHours;
|
||||
|
||||
private int totalHours;
|
||||
|
||||
private int consolidatedHours;
|
||||
|
||||
private int nonConsolidatedHours;
|
||||
|
||||
private ResourcesPerDay totalResourcesPerDay;
|
||||
|
||||
private ResourcesPerDay nonConsolidatedResourcesPerDay;
|
||||
|
||||
private ResourcesPerDay consolidatedResourcesPerDay;
|
||||
|
||||
private Intbox hoursInput = new Intbox();
|
||||
|
||||
|
|
@ -177,16 +188,15 @@ public abstract class AllocationRow {
|
|||
|
||||
private Grid derivedAllocationsGrid;
|
||||
|
||||
private Checkbox satisfiedCheckbox;
|
||||
|
||||
private void initializeResourcesPerDayInput() {
|
||||
resourcesPerDayInput.setConstraint(new SimpleConstraint(
|
||||
SimpleConstraint.NO_NEGATIVE));
|
||||
resourcesPerDayInput.setWidth("80px");
|
||||
Util.bind(resourcesPerDayInput, new Util.Getter<BigDecimal>() {
|
||||
|
||||
@Override
|
||||
public BigDecimal get() {
|
||||
return getResourcesPerDay().getAmount();
|
||||
return getNonConsolidatedResourcesPerDay().getAmount();
|
||||
}
|
||||
|
||||
}, new Util.Setter<BigDecimal>() {
|
||||
|
|
@ -194,15 +204,23 @@ public abstract class AllocationRow {
|
|||
@Override
|
||||
public void set(BigDecimal value) {
|
||||
BigDecimal amount = value == null ? new BigDecimal(0) : value;
|
||||
resourcesPerDay = ResourcesPerDay.amount(amount);
|
||||
setNonConsolidatedResourcesPerDay(ResourcesPerDay
|
||||
.amount(amount));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public AllocationRow() {
|
||||
resourcesPerDay = ResourcesPerDay.amount(0);
|
||||
originalHours = 0;
|
||||
totalHours = 0;
|
||||
consolidatedHours = 0;
|
||||
nonConsolidatedHours = 0;
|
||||
consolidatedResourcesPerDay = ResourcesPerDay.amount(0);
|
||||
setNonConsolidatedResourcesPerDay(ResourcesPerDay.amount(0));
|
||||
totalResourcesPerDay = ResourcesPerDay.amount(0);
|
||||
initializeResourcesPerDayInput();
|
||||
hoursInput.setValue(0);
|
||||
hoursInput.setWidth("80px");
|
||||
hoursInput.setDisabled(true);
|
||||
hoursInput.setConstraint(new SimpleConstraint(
|
||||
SimpleConstraint.NO_NEGATIVE));
|
||||
|
|
@ -254,8 +272,8 @@ public abstract class AllocationRow {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public ResourcesPerDay getResourcesPerDay() {
|
||||
return this.resourcesPerDay;
|
||||
public ResourcesPerDay getNonConsolidatedResourcesPerDay() {
|
||||
return this.nonConsolidatedResourcesPerDay;
|
||||
}
|
||||
|
||||
public ResourcesPerDay getResourcesPerDayFromInput() {
|
||||
|
|
@ -264,8 +282,9 @@ public abstract class AllocationRow {
|
|||
return ResourcesPerDay.amount(value);
|
||||
}
|
||||
|
||||
public void setResourcesPerDay(ResourcesPerDay resourcesPerDay) {
|
||||
this.resourcesPerDay = resourcesPerDay;
|
||||
public void setNonConsolidatedResourcesPerDay(
|
||||
ResourcesPerDay resourcesPerDay) {
|
||||
this.nonConsolidatedResourcesPerDay = resourcesPerDay;
|
||||
resourcesPerDayInput.setValue(getAmount(resourcesPerDay));
|
||||
}
|
||||
|
||||
|
|
@ -282,7 +301,7 @@ public abstract class AllocationRow {
|
|||
public abstract boolean isGeneric();
|
||||
|
||||
public boolean isEmptyResourcesPerDay() {
|
||||
return getResourcesPerDay().isZero();
|
||||
return getNonConsolidatedResourcesPerDay().isZero();
|
||||
}
|
||||
|
||||
public abstract List<Resource> getAssociatedResources();
|
||||
|
|
@ -311,10 +330,10 @@ public abstract class AllocationRow {
|
|||
|
||||
private Integer getHours() {
|
||||
if (temporal != null) {
|
||||
return temporal.getAssignedHours();
|
||||
return temporal.getNonConsolidatedHours();
|
||||
}
|
||||
if (origin != null) {
|
||||
return origin.getAssignedHours();
|
||||
return origin.getNonConsolidatedHours();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -419,19 +438,53 @@ public abstract class AllocationRow {
|
|||
}
|
||||
}
|
||||
|
||||
public Checkbox getSatisfiedCheckbox() {
|
||||
if (satisfiedCheckbox != null) {
|
||||
satisfiedCheckbox.setChecked(isSatisfied());
|
||||
return satisfiedCheckbox;
|
||||
}
|
||||
Checkbox result = new Checkbox();
|
||||
result.setChecked(isSatisfied());
|
||||
result.setDisabled(true);
|
||||
return satisfiedCheckbox = result;
|
||||
public void setOriginalHours(int originalHours) {
|
||||
this.originalHours = originalHours;
|
||||
}
|
||||
|
||||
public void loadSatisfied() {
|
||||
satisfiedCheckbox.setChecked(isSatisfied());
|
||||
public int getOriginalHours() {
|
||||
return originalHours;
|
||||
}
|
||||
|
||||
public void setTotalHours(int totalHours) {
|
||||
this.totalHours = totalHours;
|
||||
}
|
||||
|
||||
public int getTotalHours() {
|
||||
return totalHours;
|
||||
}
|
||||
|
||||
public void setConsolidatedHours(int consolidatedHours) {
|
||||
this.consolidatedHours = consolidatedHours;
|
||||
}
|
||||
|
||||
public int getConsolidatedHours() {
|
||||
return consolidatedHours;
|
||||
}
|
||||
|
||||
public void setNonConsolidatedHours(int nonConsolidatedHours) {
|
||||
this.nonConsolidatedHours = nonConsolidatedHours;
|
||||
}
|
||||
|
||||
public int getNonConsolidatedHours() {
|
||||
return nonConsolidatedHours;
|
||||
}
|
||||
|
||||
public void setTotalResourcesPerDay(ResourcesPerDay totalResourcesPerDay) {
|
||||
this.totalResourcesPerDay = totalResourcesPerDay;
|
||||
}
|
||||
|
||||
public ResourcesPerDay getTotalResourcesPerDay() {
|
||||
return totalResourcesPerDay;
|
||||
}
|
||||
|
||||
public void setConsolidatedResourcesPerDay(
|
||||
ResourcesPerDay consolidatedResourcesPerDay) {
|
||||
this.consolidatedResourcesPerDay = consolidatedResourcesPerDay;
|
||||
}
|
||||
|
||||
public ResourcesPerDay getConsolidatedResourcesPerDay() {
|
||||
return consolidatedResourcesPerDay;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ import org.zkoss.zul.Datebox;
|
|||
import org.zkoss.zul.Decimalbox;
|
||||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Intbox;
|
||||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.SimpleConstraint;
|
||||
import org.zkoss.zul.Tab;
|
||||
import org.zkoss.zul.impl.api.InputElement;
|
||||
|
|
@ -69,14 +70,19 @@ public class FormBinder {
|
|||
|
||||
private Intbox allHoursInput;
|
||||
|
||||
private Label allOriginalHours;
|
||||
private Label allTotalHours;
|
||||
private Label allConsolidatedHours;
|
||||
|
||||
private Label allTotalResourcesPerDay;
|
||||
private Label allConsolidatedResourcesPerDay;
|
||||
|
||||
private final AllocationRowsHandler allocationRowsHandler;
|
||||
|
||||
private AggregateOfResourceAllocations aggregate;
|
||||
|
||||
private AllocationResult lastAllocation;
|
||||
|
||||
private Datebox taskStartDateBox;
|
||||
|
||||
private Datebox endDate;
|
||||
|
||||
private Button applyButton;
|
||||
|
|
@ -244,22 +250,34 @@ public class FormBinder {
|
|||
return result;
|
||||
}
|
||||
|
||||
private int sumAllOriginalHours() {
|
||||
int result = 0;
|
||||
for (AllocationRow each : rows) {
|
||||
result += each.getOriginalHours();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int sumAllTotalHours() {
|
||||
int result = 0;
|
||||
for (AllocationRow each : rows) {
|
||||
result += each.getTotalHours();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int sumAllConsolidatedHours() {
|
||||
int result = 0;
|
||||
for (AllocationRow each : rows) {
|
||||
result += each.getConsolidatedHours();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public CalculatedValue getCalculatedValue() {
|
||||
return allocationRowsHandler.getCalculatedValue();
|
||||
}
|
||||
|
||||
public void setTaskStartDateBox(Datebox taskStartDateBox) {
|
||||
this.taskStartDateBox = taskStartDateBox;
|
||||
this.taskStartDateBox.setDisabled(true);
|
||||
loadValueForTaskStartDateBox();
|
||||
onChangeEnableApply(taskStartDateBox);
|
||||
}
|
||||
|
||||
private void loadValueForTaskStartDateBox() {
|
||||
this.taskStartDateBox.setValue(allocationRowsHandler.getTask()
|
||||
.getStartDate());
|
||||
}
|
||||
|
||||
private void onChangeEnableApply(InputElement inputElement) {
|
||||
inputElement.addEventListener(Events.ON_CHANGE, onChangeEnableApply);
|
||||
|
||||
|
|
@ -331,6 +349,7 @@ public class FormBinder {
|
|||
allHoursInputComponentDisabilityRule();
|
||||
bindAllResourcesPerDayToRows();
|
||||
allResourcesPerDayVisibilityRule();
|
||||
loadAggregatedCalculations();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -367,11 +386,29 @@ public class FormBinder {
|
|||
|
||||
private void reloadValues() {
|
||||
loadHoursValues();
|
||||
loadIsSatisfiedValues();
|
||||
loadValueForAssignedHoursComponent();
|
||||
loadValueForTaskStartDateBox();
|
||||
loadValueForEndDate();
|
||||
loadDerivedAllocations();
|
||||
loadSclassRowSatisfied();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void loadSclassRowSatisfied() {
|
||||
try {
|
||||
List<org.zkoss.zul.Row> rows = (List<org.zkoss.zul.Row>) allocationsGrid
|
||||
.getRows().getChildren();
|
||||
for (org.zkoss.zul.Row row : rows) {
|
||||
if (row.getValue() instanceof AllocationRow) {
|
||||
if (!((AllocationRow) row.getValue()).isSatisfied()) {
|
||||
row.setSclass("allocation-not-satisfied");
|
||||
} else {
|
||||
row.setSclass("allocation-satisfied");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadHoursValues() {
|
||||
|
|
@ -380,12 +417,6 @@ public class FormBinder {
|
|||
}
|
||||
}
|
||||
|
||||
private void loadIsSatisfiedValues() {
|
||||
for (AllocationRow each : rows) {
|
||||
each.loadSatisfied();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDerivedAllocations() {
|
||||
for (AllocationRow each : rows) {
|
||||
each.reloadDerivedAllocationsGrid();
|
||||
|
|
@ -459,13 +490,13 @@ public class FormBinder {
|
|||
Level.ERROR,
|
||||
_(
|
||||
"there are no resources for required criteria: {0}. So the generic allocation can't be added",
|
||||
ResourceLoadModel.getName(criterions)));
|
||||
Criterion.getNames(criterions)));
|
||||
}
|
||||
|
||||
public void markThereisAlreadyAssignmentWith(Set<Criterion> criterions) {
|
||||
messagesForUser.showMessage(Level.ERROR, _(
|
||||
"already exists an allocation for criteria {0}",
|
||||
ResourceLoadModel.getName(criterions)));
|
||||
Criterion.getNames(criterions)));
|
||||
}
|
||||
|
||||
public void markEndDateMustBeAfterStartDate() {
|
||||
|
|
@ -606,9 +637,72 @@ public class FormBinder {
|
|||
return sum;
|
||||
}
|
||||
|
||||
public void setStartDate(Date date) {
|
||||
taskStartDateBox.setValue(date);
|
||||
doApply();
|
||||
private BigDecimal sumAllTotalResourcesPerDay() {
|
||||
BigDecimal sum = BigDecimal.ZERO;
|
||||
for (AllocationRow each : rows) {
|
||||
sum = sum.add(each.getTotalResourcesPerDay().getAmount());
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private BigDecimal sumAllConsolidatedResourcesPerDay() {
|
||||
BigDecimal sum = BigDecimal.ZERO;
|
||||
for (AllocationRow each : rows) {
|
||||
sum = sum.add(each.getConsolidatedResourcesPerDay().getAmount());
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public void setAllOriginalHours(Label allOriginalHours) {
|
||||
this.allOriginalHours = allOriginalHours;
|
||||
}
|
||||
|
||||
public Label getAllOriginalHours() {
|
||||
return allOriginalHours;
|
||||
}
|
||||
|
||||
public void setAllTotalHours(Label allTotalHours) {
|
||||
this.allTotalHours = allTotalHours;
|
||||
}
|
||||
|
||||
public Label getAllTotalHours() {
|
||||
return allTotalHours;
|
||||
}
|
||||
|
||||
public void setAllConsolidatedHours(Label alCo1nsolidatedHours) {
|
||||
this.allConsolidatedHours = alCo1nsolidatedHours;
|
||||
}
|
||||
|
||||
public Label getAllConsolidatedHours() {
|
||||
return allConsolidatedHours;
|
||||
}
|
||||
|
||||
public void setAllTotalResourcesPerDay(Label allTotalResourcesPerDay) {
|
||||
this.allTotalResourcesPerDay = allTotalResourcesPerDay;
|
||||
}
|
||||
|
||||
public Label getAllTotalResourcesPerDay() {
|
||||
return allTotalResourcesPerDay;
|
||||
}
|
||||
|
||||
public void setAllConsolidatedResourcesPerDay(
|
||||
Label allConsolidatedResourcesPerDay) {
|
||||
this.allConsolidatedResourcesPerDay = allConsolidatedResourcesPerDay;
|
||||
}
|
||||
|
||||
public Label getAllConsolidatedResourcesPerDay() {
|
||||
return allConsolidatedResourcesPerDay;
|
||||
}
|
||||
|
||||
public void loadAggregatedCalculations() {
|
||||
allOriginalHours.setValue(Integer.toString(sumAllOriginalHours()));
|
||||
allTotalHours.setValue(Integer.toString(sumAllTotalHours()));
|
||||
allConsolidatedHours.setValue(Integer
|
||||
.toString(sumAllConsolidatedHours()));
|
||||
allTotalResourcesPerDay.setValue(sumAllTotalResourcesPerDay()
|
||||
.toString());
|
||||
allConsolidatedResourcesPerDay
|
||||
.setValue(sumAllConsolidatedResourcesPerDay().toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import org.navalplanner.business.resources.daos.IResourceDAO;
|
|||
import org.navalplanner.business.resources.entities.Criterion;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
import org.navalplanner.web.resourceload.ResourceLoadModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* The information required for creating a {@link GenericResourceAllocation}
|
||||
|
|
@ -49,7 +48,7 @@ public class GenericAllocationRow extends AllocationRow {
|
|||
private static GenericAllocationRow createDefault() {
|
||||
GenericAllocationRow result = new GenericAllocationRow();
|
||||
result.setName(_("Generic"));
|
||||
result.setResourcesPerDay(ResourcesPerDay.amount(0));
|
||||
result.setNonConsolidatedResourcesPerDay(ResourcesPerDay.amount(0));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -60,18 +59,30 @@ public class GenericAllocationRow extends AllocationRow {
|
|||
GenericAllocationRow result = createDefault();
|
||||
result.criterions = criterions;
|
||||
result.resources = new ArrayList<Resource>(resources);
|
||||
result.setName(ResourceLoadModel.getName(criterions));
|
||||
result.setName(Criterion.getNames(criterions));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static GenericAllocationRow from(
|
||||
GenericResourceAllocation resourceAllocation, IResourceDAO resourceDAO) {
|
||||
GenericAllocationRow result = createDefault();
|
||||
result.setResourcesPerDay(resourceAllocation.getResourcesPerDay());
|
||||
result.setOrigin(resourceAllocation);
|
||||
|
||||
result.setOriginalHours(resourceAllocation.getOriginalTotalAssigment());
|
||||
result.setTotalHours(resourceAllocation.getAssignedHours());
|
||||
result.setConsolidatedHours(resourceAllocation.getConsolidatedHours());
|
||||
result.setNonConsolidatedHours(resourceAllocation
|
||||
.getNonConsolidatedHours());
|
||||
|
||||
result.setNonConsolidatedResourcesPerDay(resourceAllocation
|
||||
.getNonConsolidatedResourcePerDay());
|
||||
result.setConsolidatedResourcesPerDay(resourceAllocation
|
||||
.getConsolidatedResourcePerDay());
|
||||
result.setTotalResourcesPerDay(resourceAllocation.getResourcesPerDay());
|
||||
|
||||
result.criterions = resourceAllocation.getCriterions();
|
||||
result.resources = resourceDAO.findSatisfyingCriterionsAtSomePoint(result.criterions);
|
||||
result.setName(ResourceLoadModel.getName(result.criterions));
|
||||
result.setName(Criterion.getNames(result.criterions));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +109,7 @@ public class GenericAllocationRow extends AllocationRow {
|
|||
public ResourcesPerDayModification toResourcesPerDayModification(Task task) {
|
||||
GenericResourceAllocation newGeneric = createGenericAllocation(task);
|
||||
return ResourcesPerDayModification
|
||||
.create(newGeneric, getResourcesPerDay(), this.resources);
|
||||
.create(newGeneric, getNonConsolidatedResourcesPerDay(), this.resources);
|
||||
}
|
||||
|
||||
private GenericResourceAllocation createGenericAllocation(Task task) {
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ public interface IResourceAllocationModel extends INewAllocationsAdder {
|
|||
|
||||
ProportionalDistributor addDefaultAllocations();
|
||||
|
||||
Date getTaskStart();
|
||||
|
||||
void setStartDate(Date date);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,20 +74,30 @@ public class LimitingAllocationRow {
|
|||
|
||||
private LimitingAllocationRow(ResourceAllocation<?> resourceAllocation,
|
||||
Task task) {
|
||||
init(resourceAllocation, task);
|
||||
}
|
||||
|
||||
private void init(ResourceAllocation<?> resourceAllocation,
|
||||
Task task) {
|
||||
initializeIntentedTotalHoursIfNeeded(resourceAllocation, task);
|
||||
this.resourceAllocation = resourceAllocation;
|
||||
this.task = task;
|
||||
this.hours = calculateTotalHours();
|
||||
this.hours = resourceAllocation.getIntendedTotalHours();
|
||||
this.priority = task.getPriority();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns initial total hours
|
||||
* Sets resourceAllocation.intentedTotalHours to task.totalHours if null
|
||||
*
|
||||
* @return
|
||||
* @param resourceAllocation
|
||||
* @param task
|
||||
*/
|
||||
private Integer calculateTotalHours() {
|
||||
return (resourceAllocation != null && resourceAllocation.getIntendedTotalHours() != null) ?
|
||||
resourceAllocation.getIntendedTotalHours() : task.getTotalHours();
|
||||
private void initializeIntentedTotalHoursIfNeeded(
|
||||
ResourceAllocation<?> resourceAllocation, Task task) {
|
||||
Integer intentedTotalHours = resourceAllocation.getIntendedTotalHours();
|
||||
if (intentedTotalHours == null) {
|
||||
resourceAllocation.setIntendedTotalHours(task.getTotalHours());
|
||||
}
|
||||
}
|
||||
|
||||
public static LimitingAllocationRow create(Set<Criterion> criteria,
|
||||
|
|
@ -111,13 +121,8 @@ public class LimitingAllocationRow {
|
|||
|
||||
private LimitingAllocationRow(ResourceAllocation<?> resourceAllocation,
|
||||
Task task, int priority) {
|
||||
|
||||
this.resourceAllocation = resourceAllocation;
|
||||
this.task = task;
|
||||
this.hours = calculateTotalHours();
|
||||
|
||||
task.setPriority(priority);
|
||||
this.priority = task.getPriority();
|
||||
init(resourceAllocation, task);
|
||||
}
|
||||
|
||||
public AllocationType getAllocationType() {
|
||||
|
|
@ -133,7 +138,7 @@ public class LimitingAllocationRow {
|
|||
final AllocationType type = getAllocationType();
|
||||
if (AllocationType.GENERIC.equals(type)) {
|
||||
final GenericResourceAllocation generic = (GenericResourceAllocation) resourceAllocation;
|
||||
return formatCriteria(generic.getCriterions());
|
||||
return Criterion.getNames(generic.getCriterions());
|
||||
}
|
||||
if (AllocationType.SPECIFIC.equals(type)) {
|
||||
return formatResources(resourceAllocation.getAssociatedResources());
|
||||
|
|
@ -141,14 +146,6 @@ public class LimitingAllocationRow {
|
|||
return "";
|
||||
}
|
||||
|
||||
private String formatCriteria(Set<Criterion> criteria) {
|
||||
List<String> criteriaNames = new ArrayList<String>();
|
||||
for (Criterion each: criteria) {
|
||||
criteriaNames.add(each.getName());
|
||||
}
|
||||
return (criteriaNames.isEmpty()) ? _("[generic all workers]") : StringUtils.join(criteriaNames, ",");
|
||||
}
|
||||
|
||||
private String formatResources(List<Resource> resources) {
|
||||
List<String> resourcesNames = new ArrayList<String>();
|
||||
for (Resource each: resources) {
|
||||
|
|
@ -229,4 +226,8 @@ public class LimitingAllocationRow {
|
|||
&& resourceAllocation instanceof GenericResourceAllocation;
|
||||
}
|
||||
|
||||
public boolean hasDayAssignments() {
|
||||
return resourceAllocation.hasAssignments();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
|
|||
|
||||
private Tab tabLimitingResourceAllocation;
|
||||
|
||||
private Tab tabLimitingWorkerSearch;
|
||||
|
||||
private Grid gridLimitingOrderElementHours;
|
||||
|
||||
private Grid gridLimitingAllocations;
|
||||
|
|
@ -93,10 +95,12 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
|
|||
IMessagesForUser messagesForUser) {
|
||||
try {
|
||||
resourceAllocationModel.init(task);
|
||||
tabLimitingWorkerSearch.setDisabled(existsResourceAllocationWithDayAssignments());
|
||||
limitingNewAllocationSelector.setAllocationsAdder(resourceAllocationModel);
|
||||
gridLimitingOrderElementHours.setModel(new ListModelList(
|
||||
resourceAllocationModel.getHoursAggregatedByCriteria()));
|
||||
gridLimitingOrderElementHours.setRowRenderer(createOrderElementHoursRenderer());
|
||||
Util.reloadBindings(gridLimitingAllocations);
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getStackTrace());
|
||||
}
|
||||
|
|
@ -172,7 +176,9 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private Intbox intboxHours(final LimitingAllocationRow resourceAllocation) {
|
||||
return bindToHours(new Intbox(), resourceAllocation);
|
||||
Intbox result = bindToHours(new Intbox(), resourceAllocation);
|
||||
result.setDisabled(resourceAllocation.hasDayAssignments());
|
||||
return result;
|
||||
}
|
||||
|
||||
private Intbox bindToHours(Intbox intbox, final LimitingAllocationRow resourceAllocation) {
|
||||
|
|
@ -194,7 +200,9 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private Listbox listboxPriority(final LimitingAllocationRow resourceAllocation) {
|
||||
return bindToPriority(buildPriorityList(resourceAllocation.getPriority()), resourceAllocation);
|
||||
Listbox result = bindToPriority(buildPriorityList(resourceAllocation.getPriority()), resourceAllocation);
|
||||
result.setDisabled(resourceAllocation.hasDayAssignments());
|
||||
return result;
|
||||
}
|
||||
|
||||
private Listbox buildPriorityList(int selectedValue) {
|
||||
|
|
@ -237,4 +245,17 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
|
|||
|
||||
}
|
||||
|
||||
public boolean existsResourceAllocationWithDayAssignments() {
|
||||
final LimitingAllocationRow limitingAllocationRow = getLimitingAllocationRow();
|
||||
return (limitingAllocationRow != null) ? limitingAllocationRow
|
||||
.hasDayAssignments() : false;
|
||||
}
|
||||
|
||||
private LimitingAllocationRow getLimitingAllocationRow() {
|
||||
final List<LimitingAllocationRow> limitingAllocationRows = resourceAllocationModel
|
||||
.getResourceAllocationRows();
|
||||
return (limitingAllocationRows.size() > 0) ? limitingAllocationRows
|
||||
.get(0) : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,12 +265,12 @@ public class LimitingResourceAllocationModel implements ILimitingResourceAllocat
|
|||
ResourceAllocation<?> resourceAllocation = getAssociatedResourceAllocation();
|
||||
if (resourceAllocation != null && resourceAllocation.isNewObject()) {
|
||||
task.removeAllResourceAllocations();
|
||||
addResourceAllocation(task, resourceAllocation);
|
||||
addAssociatedLimitingResourceQueueElement(task, resourceAllocation);
|
||||
}
|
||||
taskDAO.save(task);
|
||||
}
|
||||
|
||||
private void addResourceAllocation(Task task, ResourceAllocation<?> resourceAllocation) {
|
||||
private void addAssociatedLimitingResourceQueueElement(Task task, ResourceAllocation<?> resourceAllocation) {
|
||||
LimitingResourceQueueElement element = LimitingResourceQueueElement.create();
|
||||
element.setEarlierStartDateBecauseOfGantt(task.getStartDate());
|
||||
resourceAllocation.setLimitingResourceQueueElement(element);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import org.zkoss.zul.Columns;
|
|||
import org.zkoss.zul.Datebox;
|
||||
import org.zkoss.zul.Decimalbox;
|
||||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Hbox;
|
||||
import org.zkoss.zul.Intbox;
|
||||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.ListModelList;
|
||||
|
|
@ -71,6 +72,7 @@ import org.zkoss.zul.Row;
|
|||
import org.zkoss.zul.RowRenderer;
|
||||
import org.zkoss.zul.SimpleListModel;
|
||||
import org.zkoss.zul.Tab;
|
||||
import org.zkoss.zul.Window;
|
||||
|
||||
/**
|
||||
* Controller for {@link ResourceAllocation} view.
|
||||
|
|
@ -100,18 +102,25 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
|
||||
private Intbox assignedHoursComponent;
|
||||
|
||||
private Datebox taskStartDateBox;
|
||||
|
||||
private Grid calculationTypesGrid;
|
||||
|
||||
private Radiogroup calculationTypeSelector;
|
||||
|
||||
private Checkbox recommendedAllocationCheckbox;
|
||||
|
||||
private Checkbox extendedViewCheckbox;
|
||||
|
||||
private Datebox taskEndDate;
|
||||
|
||||
private Decimalbox allResourcesPerDay;
|
||||
|
||||
private Label allOriginalHours;
|
||||
private Label allTotalHours;
|
||||
private Label allConsolidatedHours;
|
||||
|
||||
private Label allTotalResourcesPerDay;
|
||||
private Label allConsolidatedResourcesPerDay;
|
||||
|
||||
private Button applyButton;
|
||||
|
||||
private NewAllocationSelector newAllocationSelector;
|
||||
|
|
@ -120,6 +129,8 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
|
||||
private Tab workerSearchTab;
|
||||
|
||||
private Window editTaskWindow;
|
||||
|
||||
public static void registerNeededScripts() {
|
||||
getScriptsRegister()
|
||||
.register(ScriptsRequiredByAdvancedAllocation.class);
|
||||
|
|
@ -133,16 +144,29 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
@Override
|
||||
public void doAfterCompose(Component comp) throws Exception {
|
||||
super.doAfterCompose(comp);
|
||||
taskEndDate = new Datebox();
|
||||
allResourcesPerDay = new Decimalbox();
|
||||
allResourcesPerDay.setWidth("80px");
|
||||
newAllocationSelector.setLimitingResourceFilter(false);
|
||||
initAllocationLabels();
|
||||
makeReadyInputsForCalculationTypes();
|
||||
prepareCalculationTypesGrid();
|
||||
}
|
||||
|
||||
private void initAllocationLabels() {
|
||||
allOriginalHours = new Label();
|
||||
allTotalHours = new Label();
|
||||
allConsolidatedHours = new Label();
|
||||
|
||||
allTotalResourcesPerDay = new Label();
|
||||
allConsolidatedResourcesPerDay = new Label();
|
||||
}
|
||||
|
||||
private void makeReadyInputsForCalculationTypes() {
|
||||
final String width = "300px";
|
||||
final String width = "90px";
|
||||
taskEndDate.setWidth(width);
|
||||
assignedHoursComponent = new Intbox();
|
||||
assignedHoursComponent.setWidth("80px");
|
||||
}
|
||||
|
||||
private void prepareCalculationTypesGrid() {
|
||||
|
|
@ -157,11 +181,27 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
|
||||
@Override
|
||||
public Component cellFor(Integer column, CalculationTypeRadio data) {
|
||||
return data.createRadio();
|
||||
return data.createComponent(getController(),
|
||||
getCalculationTypeRadio());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Datebox getTaskEndDate() {
|
||||
return taskEndDate;
|
||||
}
|
||||
|
||||
private CalculationTypeRadio getCalculationTypeRadio() {
|
||||
if (formBinder != null) {
|
||||
return CalculationTypeRadio.from(formBinder.getCalculatedValue());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ResourceAllocationController getController() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows Resource Allocation window
|
||||
* @param task
|
||||
|
|
@ -179,18 +219,27 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
context, planningState);
|
||||
formBinder = allocationRows.createFormBinder(planningState
|
||||
.getCurrentScenario(), resourceAllocationModel);
|
||||
formBinder.setAllOriginalHours(allOriginalHours);
|
||||
formBinder.setAllTotalHours(allTotalHours);
|
||||
formBinder.setAllConsolidatedHours(allConsolidatedHours);
|
||||
formBinder.setAssignedHoursComponent(assignedHoursComponent);
|
||||
formBinder.setTaskStartDateBox(taskStartDateBox);
|
||||
formBinder.setEndDate(taskEndDate);
|
||||
|
||||
formBinder.setAllTotalResourcesPerDay(allTotalResourcesPerDay);
|
||||
formBinder
|
||||
.setAllConsolidatedResourcesPerDay(allConsolidatedResourcesPerDay);
|
||||
formBinder.setAllResourcesPerDay(allResourcesPerDay);
|
||||
|
||||
formBinder.setEndDate(taskEndDate);
|
||||
formBinder.setApplyButton(applyButton);
|
||||
formBinder.setAllocationsGrid(allocationsGrid);
|
||||
formBinder.setMessagesForUser(messagesForUser);
|
||||
formBinder.setWorkerSearchTab(workerSearchTab);
|
||||
formBinder.setCheckbox(recommendedAllocationCheckbox);
|
||||
|
||||
CalculationTypeRadio calculationTypeRadio = CalculationTypeRadio
|
||||
.from(formBinder.getCalculatedValue());
|
||||
calculationTypeRadio.doTheSelectionOn(calculationTypeSelector);
|
||||
|
||||
tbResourceAllocation.setSelected(true);
|
||||
orderElementHoursGrid.setModel(new ListModelList(
|
||||
resourceAllocationModel.getHoursAggregatedByCriterions()));
|
||||
|
|
@ -202,6 +251,10 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
}
|
||||
}
|
||||
|
||||
public Date getTaskStart() {
|
||||
return resourceAllocationModel.getTaskStart();
|
||||
}
|
||||
|
||||
public enum HoursRendererColumn {
|
||||
|
||||
|
||||
|
|
@ -224,8 +277,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
@Override
|
||||
public Component cell(HoursRendererColumn column,
|
||||
AggregatedHoursGroup data) {
|
||||
Intbox result = new Intbox(data.getHours());
|
||||
result.setDisabled(true);
|
||||
Label result = new Label(Integer.toString(data.getHours()));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
|
@ -280,9 +332,38 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the extended view of the resources allocations
|
||||
*/
|
||||
public void onCheckExtendedView() {
|
||||
if (isExtendedView()) {
|
||||
editTaskWindow.setWidth("970px");
|
||||
} else {
|
||||
editTaskWindow.setWidth("870px");
|
||||
}
|
||||
editTaskWindow.invalidate();
|
||||
Util.reloadBindings(allocationsGrid);
|
||||
}
|
||||
|
||||
public boolean isExtendedView() {
|
||||
return extendedViewCheckbox.isChecked();
|
||||
}
|
||||
|
||||
public int getColspanHours() {
|
||||
if (isExtendedView()) {
|
||||
return 4;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int getColspanResources() {
|
||||
if (isExtendedView()) {
|
||||
return 3;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* Close search worker in worker search tab
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
public void onCloseSelectWorkers() {
|
||||
|
|
@ -346,21 +427,53 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
public abstract Component input(
|
||||
ResourceAllocationController resourceAllocationController);
|
||||
|
||||
public Radio createRadio() {
|
||||
public Component createComponent(
|
||||
ResourceAllocationController resourceAllocationController,
|
||||
CalculationTypeRadio calculationTypeRadio) {
|
||||
if (this.equals(END_DATE)) {
|
||||
return createHbox(resourceAllocationController.taskEndDate,
|
||||
calculationTypeRadio);
|
||||
} else {
|
||||
return createRadio(calculationTypeRadio);
|
||||
}
|
||||
}
|
||||
|
||||
public Radio createRadio(CalculationTypeRadio calculationTypeRadio) {
|
||||
Radio result = new Radio();
|
||||
result.setLabel(getName());
|
||||
result.setValue(toString());
|
||||
result.setChecked(isSameCalculationTypeRadio(result,
|
||||
calculationTypeRadio));
|
||||
return result;
|
||||
}
|
||||
|
||||
public void doTheSelectionOn(Radiogroup radiogroup) {
|
||||
for (int i = 0; i < radiogroup.getItemCount(); i++) {
|
||||
Radio radio = radiogroup.getItemAtIndex(i);
|
||||
if (name().equals(radio.getValue())) {
|
||||
radiogroup.setSelectedIndex(i);
|
||||
break;
|
||||
}
|
||||
public Hbox createHbox(Datebox datebox,
|
||||
CalculationTypeRadio calculationTypeRadio) {
|
||||
Hbox hbox = new Hbox();
|
||||
hbox.setSpacing("65px");
|
||||
Radio radio = createRadio(calculationTypeRadio);
|
||||
|
||||
hbox.appendChild(radio);
|
||||
hbox.appendChild(datebox);
|
||||
return hbox;
|
||||
}
|
||||
|
||||
public boolean isSameCalculationTypeRadio(Radio radio,
|
||||
CalculationTypeRadio calculationTypeRadio) {
|
||||
if (calculationTypeRadio != null) {
|
||||
return name().equals(calculationTypeRadio.name());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void doTheSelectionOn(final Radiogroup radiogroup) {
|
||||
for (int i = 0; i < radiogroup.getItemCount(); i++) {
|
||||
Radio radio = radiogroup.getItemAtIndex(i);
|
||||
if (name().equals(radio.getValue())) {
|
||||
radiogroup.setSelectedIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final CalculatedValue calculatedValue;
|
||||
|
|
@ -502,9 +615,16 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
throws Exception {
|
||||
row.setValue(data);
|
||||
append(row, data.createDetail());
|
||||
append(row, data.getSatisfiedCheckbox());
|
||||
append(row, new Label(data.getName()));
|
||||
append(row, new Label(Integer.toString(data.getOriginalHours())));
|
||||
append(row, new Label(Integer.toString(data.getTotalHours())));
|
||||
append(row,
|
||||
new Label(Integer.toString(data.getConsolidatedHours())));
|
||||
append(row, data.getHoursInput());
|
||||
append(row, new Label(data.getTotalResourcesPerDay().getAmount()
|
||||
.toString()));
|
||||
append(row, new Label(data.getConsolidatedResourcesPerDay()
|
||||
.getAmount().toString()));
|
||||
append(row, data.getResourcesPerDayInput());
|
||||
// On click delete button
|
||||
Button deleteButton = appendDeleteButton(row);
|
||||
|
|
@ -516,16 +636,27 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
removeAllocation(data);
|
||||
}
|
||||
});
|
||||
|
||||
if (!data.isSatisfied()) {
|
||||
row.setSclass("allocation-not-satisfied");
|
||||
} else {
|
||||
row.setSclass("allocation-satisfied");
|
||||
}
|
||||
}
|
||||
|
||||
private void renderAggregatingRow(Row row) {
|
||||
ResourceAllocationController controller = ResourceAllocationController.this;
|
||||
append(row, new Label());
|
||||
append(row, new Label());
|
||||
append(row, new Label(_("Sum of all rows")));
|
||||
append(row, CalculationTypeRadio.NUMBER_OF_HOURS.input(controller));
|
||||
append(row, allOriginalHours);
|
||||
append(row, allTotalHours);
|
||||
append(row, allConsolidatedHours);
|
||||
append(row, CalculationTypeRadio.NUMBER_OF_HOURS
|
||||
.input(controller));
|
||||
append(row, allTotalResourcesPerDay);
|
||||
append(row, allConsolidatedResourcesPerDay);
|
||||
append(row, CalculationTypeRadio.RESOURCES_PER_DAY
|
||||
.input(controller));
|
||||
.input(controller));
|
||||
append(row, new Label());
|
||||
}
|
||||
|
||||
|
|
@ -567,7 +698,6 @@ public class ResourceAllocationController extends GenericForwardComposer {
|
|||
|
||||
public void setStartDate(Date date) {
|
||||
resourceAllocationModel.setStartDate(date);
|
||||
formBinder.setStartDate(date);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.navalplanner.business.calendars.daos.IBaseCalendarDAO;
|
||||
import org.navalplanner.business.common.IAdHocTransactionService;
|
||||
import org.navalplanner.business.common.IOnTransaction;
|
||||
import org.navalplanner.business.common.ProportionalDistributor;
|
||||
|
|
@ -84,9 +83,6 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
|
|||
|
||||
private Task task;
|
||||
|
||||
@Autowired
|
||||
private IBaseCalendarDAO calendarDAO;
|
||||
|
||||
@Autowired
|
||||
private ICriterionDAO criterionDAO;
|
||||
|
||||
|
|
@ -385,6 +381,14 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
|
|||
return AggregatedHoursGroup.sum(task.getAggregatedByCriterions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getTaskStart() {
|
||||
if (task == null) {
|
||||
return null;
|
||||
}
|
||||
return task.getStartDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStartDate(Date date) {
|
||||
if (task != null) {
|
||||
|
|
|
|||
|
|
@ -85,8 +85,19 @@ public class SpecificAllocationRow extends AllocationRow {
|
|||
|
||||
public static SpecificAllocationRow from(SpecificResourceAllocation specific) {
|
||||
SpecificAllocationRow result = forResource(specific.getResource());
|
||||
result.setResourcesPerDay(specific.getResourcesPerDay());
|
||||
result.setOrigin(specific);
|
||||
|
||||
result.setOriginalHours(specific.getOriginalTotalAssigment());
|
||||
result.setTotalHours(specific.getAssignedHours());
|
||||
result.setConsolidatedHours(specific.getConsolidatedHours());
|
||||
result.setNonConsolidatedHours(specific.getNonConsolidatedHours());
|
||||
|
||||
result.setNonConsolidatedResourcesPerDay(specific
|
||||
.getNonConsolidatedResourcePerDay());
|
||||
result.setConsolidatedResourcesPerDay(specific
|
||||
.getConsolidatedResourcePerDay());
|
||||
result.setTotalResourcesPerDay(specific.getResourcesPerDay());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -94,7 +105,7 @@ public class SpecificAllocationRow extends AllocationRow {
|
|||
SpecificAllocationRow result = new SpecificAllocationRow();
|
||||
result.setName(resource.getShortDescription());
|
||||
result.setResource(resource);
|
||||
result.setResourcesPerDay(ResourcesPerDay.amount(1));
|
||||
result.setNonConsolidatedResourcesPerDay(ResourcesPerDay.amount(1));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +114,7 @@ public class SpecificAllocationRow extends AllocationRow {
|
|||
@Override
|
||||
public ResourcesPerDayModification toResourcesPerDayModification(Task task) {
|
||||
return ResourcesPerDayModification.create(createSpecific(task),
|
||||
getResourcesPerDay());
|
||||
getNonConsolidatedResourcesPerDay());
|
||||
}
|
||||
|
||||
private SpecificResourceAllocation createSpecific(Task task) {
|
||||
|
|
|
|||
|
|
@ -204,13 +204,19 @@ public abstract class ChartFiller implements IChartFiller {
|
|||
}
|
||||
|
||||
private void fillZeroValueFromStart(PrintWriter writer) {
|
||||
printLine(writer, start, BigDecimal.ZERO);
|
||||
if (startIsPreviousToPreviousDayToFirstAssignment()) {
|
||||
printLine(writer, previousDayToFirstAssignment(),
|
||||
BigDecimal.ZERO);
|
||||
if (!startIsDayOfFirstAssignment()) {
|
||||
printLine(writer, start, BigDecimal.ZERO);
|
||||
if (startIsPreviousToPreviousDayToFirstAssignment()) {
|
||||
printLine(writer, previousDayToFirstAssignment(),
|
||||
BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean startIsDayOfFirstAssignment() {
|
||||
return !map.isEmpty() && start.compareTo(map.firstKey()) == 0;
|
||||
}
|
||||
|
||||
private boolean startIsPreviousToPreviousDayToFirstAssignment() {
|
||||
return !map.isEmpty()
|
||||
&& start.compareTo(previousDayToFirstAssignment()) < 0;
|
||||
|
|
@ -221,10 +227,17 @@ public abstract class ChartFiller implements IChartFiller {
|
|||
}
|
||||
|
||||
private void fillZeroValueToFinish(PrintWriter writer) {
|
||||
if (finishIsPosteriorToNextDayToLastAssignment()) {
|
||||
printLine(writer, nextDayToLastAssignment(), BigDecimal.ZERO);
|
||||
if (!finishIsDayOfLastAssignment()) {
|
||||
if (finishIsPosteriorToNextDayToLastAssignment()) {
|
||||
printLine(writer, nextDayToLastAssignment(),
|
||||
BigDecimal.ZERO);
|
||||
}
|
||||
printLine(writer, finish, BigDecimal.ZERO);
|
||||
}
|
||||
printLine(writer, finish, BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
private boolean finishIsDayOfLastAssignment() {
|
||||
return !map.isEmpty() && start.compareTo(map.lastKey()) == 0;
|
||||
}
|
||||
|
||||
private boolean finishIsPosteriorToNextDayToLastAssignment() {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue