menuBuilder = MenuBuilder.on(divElement.getPage(),
+ queueElementDivs);
+ menuBuilder.item(_("Unassign"), "/common/img/ico_borrar.png",
+ new ItemAction
() {
+ @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();
+ result.setClass("queue-element");
+
+ result.setTooltiptext(queueElement.getLimitingResourceQueue()
+ .getResource().getName());
+
+ result.setLeft(forCSS(getStartPixels(datesMapper, queueElement)));
+ result.setWidth(forCSS(getWidthPixels(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 long toMilliseconds(LocalDate localDate) {
+ return localDate.toDateMidnight().getMillis();
+ }
+
+ private static String forCSS(int pixels) {
+ return String.format("%dpx", pixels);
+ }
+
+ private static int getStartPixels(IDatesMapper datesMapper,
+ LimitingResourceQueueElement queueElement) {
+ return datesMapper.toPixels(queueElement.getStartDate().toDateMidnight()
+ .toDate());
+ }
+
+ private void appendContextMenus() {
+ for (Div each : queueElementDivs) {
+ appendMenu(each);
+ }
+ }
+
+ @Override
+ public void afterCompose() {
+ appendContextMenus();
+ }
+
+}
\ No newline at end of file
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java
new file mode 100644
index 000000000..806a6e5d2
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java
@@ -0,0 +1,227 @@
+/*
+ * 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
.
+ */
+
+package org.navalplanner.web.limitingresources;
+
+import static org.navalplanner.web.I18nHelper._;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.lang.Validate;
+import org.navalplanner.business.orders.entities.Order;
+import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
+import org.navalplanner.business.planner.entities.TaskElement;
+import org.navalplanner.web.limitingresources.LimitingResourcesPanel.IToolbarCommand;
+import org.navalplanner.web.planner.order.BankHolidaysMarker;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.zkoss.ganttz.resourceload.IFilterChangedListener;
+import org.zkoss.ganttz.timetracker.TimeTracker;
+import org.zkoss.ganttz.timetracker.zoom.SeveralModificators;
+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.Composer;
+import org.zkoss.zul.Button;
+import org.zkoss.zul.Checkbox;
+import org.zkoss.zul.Label;
+import org.zkoss.zul.Messagebox;
+import org.zkoss.zul.Row;
+import org.zkoss.zul.RowRenderer;
+
+/**
+ * Controller for limiting resources view
+ * @author Lorenzo Tilve Álvaro
+ */
+@Component
+@Scope(BeanDefinition.SCOPE_PROTOTYPE)
+public class LimitingResourcesController implements Composer {
+
+ @Autowired
+ private ILimitingResourceQueueModel limitingResourceQueueModel;
+
+ private List commands = new ArrayList();
+
+ private Order filterBy;
+
+ private org.zkoss.zk.ui.Component parent;
+
+ private LimitingResourcesPanel limitingResourcesPanel;
+
+ private TimeTracker timeTracker;
+
+ private final LimitingResourceQueueElementsRenderer limitingResourceQueueElementsRenderer =
+ new LimitingResourceQueueElementsRenderer();
+
+ private transient IFilterChangedListener filterChangedListener;
+
+ public LimitingResourcesController() {
+ }
+
+ public void add(IToolbarCommand... commands) {
+ Validate.noNullElements(commands);
+ this.commands.addAll(Arrays.asList(commands));
+ }
+
+ @Override
+ public void doAfterCompose(org.zkoss.zk.ui.Component comp) throws Exception {
+ this.parent = comp;
+ reload();
+ }
+
+ public void reload() {
+ // by default show the task by resources
+ boolean filterByResources = true;
+ reload(filterByResources);
+ }
+
+ private void reload(boolean filterByResources) {
+ try {
+ if (filterBy == null) {
+ limitingResourceQueueModel.initGlobalView(filterByResources);
+ } else {
+ limitingResourceQueueModel.initGlobalView(filterBy,
+ filterByResources);
+ }
+ timeTracker = buildTimeTracker();
+ limitingResourcesPanel = buildLimitingResourcesPanel();
+ addListeners();
+
+ this.parent.getChildren().clear();
+ this.parent.appendChild(limitingResourcesPanel);
+ limitingResourcesPanel.afterCompose();
+ addCommands(limitingResourcesPanel);
+ } catch (IllegalArgumentException e) {
+ try {
+ e.printStackTrace();
+ Messagebox.show(_("Limiting resources error") + e, _("Error"),
+ Messagebox.OK, Messagebox.ERROR);
+ } catch (InterruptedException o) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private void addListeners() {
+ filterChangedListener = new IFilterChangedListener() {
+
+ @Override
+ public void filterChanged(boolean filter) {
+ onApplyFilter(filter);
+ }
+ };
+ // this.limitingResourcesPanel.addFilterListener(filterChangedListener);
+ }
+
+ public void onApplyFilter(boolean filterByResources) {
+ limitingResourcesPanel.clearComponents();
+ reload(filterByResources);
+ }
+
+ private void addCommands(LimitingResourcesPanel limitingResourcesPanel) {
+ limitingResourcesPanel.add(commands.toArray(new IToolbarCommand[0]));
+ }
+
+ private TimeTracker buildTimeTracker() {
+ return timeTracker = new TimeTracker(limitingResourceQueueModel
+ .getViewInterval(), limitingResourceQueueModel
+ .calculateInitialZoomLevel(), SeveralModificators.create(),
+ SeveralModificators.create(new BankHolidaysMarker()), parent);
+ }
+
+ private LimitingResourcesPanel buildLimitingResourcesPanel() {
+ LimitingResourcesPanel result = new LimitingResourcesPanel(
+ limitingResourceQueueModel.getLimitingResourceQueues(),
+ timeTracker);
+ result.setVariable("limitingResourcesController", this, true);
+ return result;
+ }
+
+ public List getUnassignedLimitingResourceQueueElements() {
+ return limitingResourceQueueModel.getUnassignedLimitingResourceQueueElements();
+ }
+
+ public void filterBy(Order order) {
+ this.filterBy = order;
+ }
+
+ public LimitingResourceQueueElementsRenderer getLimitingResourceQueueElementsRenderer() {
+ return limitingResourceQueueElementsRenderer;
+ }
+
+ private class LimitingResourceQueueElementsRenderer implements RowRenderer {
+
+ @Override
+ public void render(Row row, Object data) throws Exception {
+ LimitingResourceQueueElement element = (LimitingResourceQueueElement) data;
+
+ row.appendChild(label(getTaskName(element)));
+ row.appendChild(label(getOrderName(element)));
+ row.appendChild(assignButton(element));
+ row.appendChild(automaticQueueing(element));
+ }
+
+ private Button assignButton(final LimitingResourceQueueElement 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 {
+ // FIXME: assign element to queue
+ }
+ });
+ return result;
+ }
+
+ private Checkbox automaticQueueing(final LimitingResourceQueueElement element) {
+ Checkbox result = new Checkbox();
+ result.setTooltiptext(_("Select for automatic queuing"));
+ return result;
+ }
+
+ private Label label(String value) {
+ 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();
+ }
+
+ }
+
+}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesLeftPane.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesLeftPane.java
new file mode 100644
index 000000000..ebbe37c99
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesLeftPane.java
@@ -0,0 +1,168 @@
+/*
+ * 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 .
+ */
+
+package org.navalplanner.web.limitingresources;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.navalplanner.business.resources.entities.LimitingResourceQueue;
+import org.zkoss.ganttz.util.MutableTreeModel;
+import org.zkoss.zk.ui.Component;
+import org.zkoss.zk.ui.HtmlMacroComponent;
+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;
+import org.zkoss.zul.api.Tree;
+
+public class LimitingResourcesLeftPane extends HtmlMacroComponent {
+
+ private MutableTreeModel modelForTree;
+ private final LimitingResourcesList limitingResourcesList;
+
+ public LimitingResourcesLeftPane(
+ MutableTreeModel treeModel,
+ LimitingResourcesList resourceLoadList) {
+ this.limitingResourcesList = resourceLoadList;
+ this.modelForTree = treeModel;
+ }
+
+
+ @Override
+ public void afterCompose() {
+ super.afterCompose();
+ getContainerTree().setModel(modelForTree);
+ getContainerTree().setTreeitemRenderer(getRendererForTree());
+ }
+
+ private TreeitemRenderer getRendererForTree() {
+ return new TreeitemRenderer() {
+ @Override
+ public void render(Treeitem item, Object data)
+ throws Exception {
+ LimitingResourceQueue line = (LimitingResourceQueue) data;
+ item.setOpen(false);
+ item.setValue(line);
+
+ Treerow row = new Treerow();
+ Treecell cell = new Treecell();
+ Component component = createComponent(line);
+ item.appendChild(row);
+ row.appendChild(cell);
+ cell.appendChild(component);
+ }
+
+ private Component createComponent(LimitingResourceQueue line) {
+ return isTopLevel(line) ? createFirstLevel(line)
+ : createSecondLevel(line);
+ }
+
+ private boolean isTopLevel(LimitingResourceQueue line) {
+ int[] path = modelForTree.getPath(modelForTree.getRoot(), line);
+ return path.length == 0;
+ }
+ };
+ }
+
+ private void collapse(LimitingResourceQueue line) {
+ // unnecesary
+ limitingResourcesList.collapse(line);
+ }
+
+ private void expand(LimitingResourceQueue line,
+ List closed) {
+ // unnecesary
+ // limitingResourcesList.expand(line, closed);
+ }
+
+ private List calculatedClosedItems(Treeitem item) {
+ List result = new ArrayList();
+ Treechildren treeChildren = item.getTreechildren();
+ if (treeChildren != null) {
+ List myTreeItems = (List) treeChildren
+ .getChildren();
+ Iterator 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 getLineChildrenBy(Treeitem item) {
+ List result = new ArrayList();
+ LimitingResourceQueue line = getLineByTreeitem(item);
+ return result;
+ }
+
+ private LimitingResourceQueue getLineByTreeitem(Treeitem child) {
+ LimitingResourceQueue line = null;
+ try {
+ line = (LimitingResourceQueue) child.getValue();
+ } catch (Exception e) {
+ return null;
+ }
+ return line;
+ }
+
+ private Tree getContainerTree() {
+ return (Tree) getFellow("loadsTree");
+ }
+
+ private Component createFirstLevel(LimitingResourceQueue principal) {
+ Div result = createLabelWithName(principal);
+ result.setSclass("firstlevel");
+ return result;
+ }
+
+ private Component createSecondLevel(LimitingResourceQueue loadTimeLine) {
+ Div result = createLabelWithName(loadTimeLine);
+ result.setSclass("secondlevel");
+ return result;
+ }
+
+ private Div createLabelWithName(LimitingResourceQueue principal) {
+ Div result = new Div();
+ Label label = new Label();
+ final String conceptName = principal.getResource().getName();
+ label.setValue(conceptName);
+ result.appendChild(label);
+ return result;
+ }
+
+
+ private static Popup createPopup(Div parent, String originalValue) {
+ Popup result = new Popup();
+ result.appendChild(new Label(originalValue));
+ parent.appendChild(result);
+ return result;
+ }
+}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesList.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesList.java
new file mode 100644
index 000000000..80d34ac0c
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesList.java
@@ -0,0 +1,117 @@
+/*
+ * 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 .
+ */
+
+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
+ */
+public class LimitingResourcesList extends HtmlMacroComponent implements
+ AfterCompose {
+
+ private final IZoomLevelChangedListener zoomListener;
+
+ private Map fromTimeLineToComponent = new HashMap();
+
+ private final MutableTreeModel timelinesTree;
+
+ private List limitingResourcesComponents = new ArrayList();
+
+ public LimitingResourcesList(TimeTracker timeTracker,
+ MutableTreeModel timelinesTree) {
+ this.timelinesTree = timelinesTree;
+ zoomListener = adjustTimeTrackerSizeListener();
+ timeTracker.addZoomListener(zoomListener);
+ LimitingResourceQueue current = timelinesTree.getRoot();
+ List toInsert = new ArrayList();
+ fill(timelinesTree, current, toInsert);
+ insertAsComponents(timeTracker, toInsert);
+ }
+
+ private void fill(MutableTreeModel timelinesTree,
+ LimitingResourceQueue current, List 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 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 closed) {
+ }
+
+ @Override
+ public void afterCompose() {
+ super.afterCompose();
+ for (LimitingResourcesComponent each : limitingResourcesComponents) {
+ each.afterCompose();
+ }
+ }
+}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesPanel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesPanel.java
new file mode 100644
index 000000000..4fc6e9a5b
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesPanel.java
@@ -0,0 +1,262 @@
+/*
+ * 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 .
+ */
+
+package org.navalplanner.web.limitingresources;
+
+import static org.zkoss.ganttz.i18n.I18nHelper._;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.navalplanner.business.resources.daos.IResourceDAO;
+import org.navalplanner.business.resources.entities.LimitingResourceQueue;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.zkoss.ganttz.timetracker.TimeTracker;
+import org.zkoss.ganttz.timetracker.TimeTrackerComponent;
+import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
+import org.zkoss.ganttz.util.ComponentsFinder;
+import org.zkoss.ganttz.util.MutableTreeModel;
+import org.zkoss.ganttz.util.OnZKDesktopRegistry;
+import org.zkoss.ganttz.util.script.IScriptsRegister;
+import org.zkoss.zk.au.out.AuInvoke;
+import org.zkoss.zk.ui.Component;
+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.zul.Button;
+import org.zkoss.zul.Div;
+import org.zkoss.zul.ListModel;
+import org.zkoss.zul.Listbox;
+import org.zkoss.zul.Separator;
+import org.zkoss.zul.SimpleListModel;
+
+public class LimitingResourcesPanel extends HtmlMacroComponent {
+
+ public interface IToolbarCommand {
+ public void doAction();
+
+ public String getLabel();
+
+ public String getImage();
+ }
+
+ private TimeTrackerComponent timeTrackerComponent;
+
+ private LimitingResourcesLeftPane leftPane;
+
+ private LimitingResourcesList limitingResourcesList;
+
+ private List limitingResourceQueues = new ArrayList();
+
+ private MutableTreeModel treeModel;
+
+ private TimeTracker timeTracker;
+
+ // private LimitingDependencyList dependencyList;
+
+ // private WeakReferencedListeners zoomListeners =
+ // WeakReferencedListeners.create();
+
+ private Listbox listZoomLevels;
+
+ @Autowired
+ IResourceDAO resourcesDAO;
+
+ private static final String filterResources = _("Filter by resources");
+ private static final String filterCriterions = _("Filter by criterions");
+ private boolean filterbyResources = true;
+
+ public LimitingResourcesPanel(List groups,
+ TimeTracker timeTracker) {
+ init(groups, timeTracker);
+
+ }
+
+ public void init(List groups, TimeTracker timeTracker) {
+ this.limitingResourceQueues = groups;
+ this.timeTracker = timeTracker;
+ treeModel = createModelForTree();
+ timeTrackerComponent = timeTrackerForResourcesLoadPanel(timeTracker);
+ limitingResourcesList = new LimitingResourcesList(timeTracker,
+ treeModel);
+ leftPane = new LimitingResourcesLeftPane(treeModel,
+ limitingResourcesList);
+ registerNeededScripts();
+ }
+
+ public ListModel getFilters() {
+ String[] filters = new String[] { filterResources, filterCriterions };
+ return new SimpleListModel(filters);
+ }
+
+ public void setFilter(String filterby) {
+ if (filterby.equals(filterResources)) {
+ this.filterbyResources = true;
+ } else {
+ this.filterbyResources = false;
+ }
+ }
+
+ public boolean getFilter() {
+ return filterbyResources;
+ }
+
+ public ListModel getZoomLevels() {
+ return new SimpleListModel(ZoomLevel.values());
+ }
+
+ public void setZoomLevel(final ZoomLevel zoomLevel) {
+ timeTracker.setZoomLevel(zoomLevel);
+ }
+
+ public void zoomIncrease() {
+ timeTracker.zoomIncrease();
+ }
+
+ public void zoomDecrease() {
+ timeTracker.zoomDecrease();
+ }
+
+ public void add(final IToolbarCommand... commands) {
+ Component toolbar = getToolbar();
+ Separator separator = getSeparator();
+ for (IToolbarCommand c : commands) {
+ toolbar.insertBefore(asButton(c), separator);
+ }
+ }
+
+ private Button asButton(final IToolbarCommand c) {
+ Button result = new Button();
+ result.addEventListener(Events.ON_CLICK, new EventListener() {
+ @Override
+ public void onEvent(Event event) throws Exception {
+ c.doAction();
+ }
+ });
+ if (!StringUtils.isEmpty(c.getImage())) {
+ result.setImage(c.getImage());
+ result.setTooltiptext(c.getLabel());
+ } else {
+ result.setLabel(c.getLabel());
+ }
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Separator getSeparator() {
+ List children = getToolbar().getChildren();
+ Separator separator = ComponentsFinder.findComponentsOfType(
+ Separator.class, children).get(0);
+ return separator;
+ }
+
+ private Component getToolbar() {
+ Component toolbar = getFellow("toolbar");
+ return toolbar;
+ }
+
+ private void registerNeededScripts() {
+ // getScriptsRegister().register(ScriptsRequiredByResourceLoadPanel.class);
+ }
+
+ private IScriptsRegister getScriptsRegister() {
+ return OnZKDesktopRegistry.getLocatorFor(IScriptsRegister.class)
+ .retrieve();
+ }
+
+ private MutableTreeModel createModelForTree() {
+ MutableTreeModel 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,
+ "adjustScrollHorizontalPosition", pixelsDisplacement
+ + ""));
+ }
+ };
+ }
+
+ @Override
+ public void afterCompose() {
+
+ super.afterCompose();
+
+ // Insert resourcesList left pane component
+ getFellow("insertionPointLeftPanel").appendChild(leftPane);
+ leftPane.afterCompose();
+
+ // Insert timetracker watermarks and limitingResourcesQueues
+ getFellow("insertionPointRightPanel").appendChild(timeTrackerComponent);
+ getFellow("insertionPointRightPanel")
+ .appendChild(limitingResourcesList);
+ limitingResourcesList.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();
+
+ // Insert timetracker headers
+ TimeTrackerComponent timeTrackerHeader = createTimeTrackerHeader();
+ getFellow("insertionPointTimetracker").appendChild(timeTrackerHeader);
+
+ timeTrackerHeader.afterCompose();
+ timeTrackerComponent.afterCompose();
+ listZoomLevels = (Listbox) getFellow("listZoomLevels");
+ listZoomLevels.setSelectedIndex(timeTracker.getDetailLevel().ordinal());
+ }
+
+ public void clearComponents() {
+ getFellow("insertionPointLeftPanel").getChildren().clear();
+ getFellow("insertionPointRightPanel").getChildren().clear();
+ getFellow("insertionPointTimetracker").getChildren().clear();
+ }
+
+ private TimeTrackerComponent createTimeTrackerHeader() {
+ return new TimeTrackerComponent(
+ timeTracker) {
+
+ @Override
+ protected void scrollHorizontalPercentage(int pixelsDisplacement) {
+ }
+ };
+ }
+
+}
\ No newline at end of file
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueueTaskGenerator.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueueTaskGenerator.java
new file mode 100644
index 000000000..7247617c1
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/QueueTaskGenerator.java
@@ -0,0 +1,365 @@
+/*
+ * 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 .
+ */
+
+package org.navalplanner.web.limitingresources;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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;
+import org.navalplanner.business.resources.daos.IResourceDAO;
+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);
+}
+
+
+abstract class QueueTaskGenerator {
+
+ private static final Log LOG = LogFactory.getLog(QueueTaskGenerator.class);
+
+ public static QueueTaskGeneratorFactory onResource(Resource resource) {
+ return new OnResourceFactory(resource);
+ }
+
+ public static QueueTaskGeneratorFactory onResourceSatisfying(
+ Resource resource, Collection criterions) {
+ return new OnResourceFactory(resource, criterions);
+ }
+
+ private static class OnResourceFactory implements
+ QueueTaskGeneratorFactory {
+
+ private final Resource resource;
+
+ private final ICriterion criterion;
+
+ public OnResourceFactory(Resource resource) {
+ this(resource, Collections. emptyList());
+ }
+
+ public OnResourceFactory(Resource resource,
+ Collection criterionsToSatisfy) {
+ Validate.notNull(resource);
+ this.resource = resource;
+ this.criterion = CriterionCompounder.buildAnd(criterionsToSatisfy)
+ .getResult();
+ }
+
+ @Override
+ public QueueTaskGenerator create(ResourceAllocation> allocation) {
+ return new QueueTaskGeneratorOnResource(resource, allocation,
+ criterion);
+ }
+
+ }
+
+ public static QueueTaskGeneratorFactory onCriterion(
+ final Criterion criterion, final IResourceDAO resourcesDAO) {
+ return new QueueTaskGeneratorFactory() {
+
+ @Override
+ public QueueTaskGenerator create(ResourceAllocation> allocation) {
+ return new QueueTaskGeneratorOnCriterion(criterion,
+ allocation, findResources(criterion, resourcesDAO));
+ }
+
+ private List findResources(final Criterion criterion,
+ final IResourceDAO resourcesDAO) {
+ return resourcesDAO
+ .findSatisfyingCriterionsAtSomePoint(Collections
+ .singletonList(criterion));
+ }
+ };
+ }
+
+ protected final LocalDate start;
+ protected final LocalDate end;
+
+ private List> allocationsOnInterval = new ArrayList>();
+
+ protected QueueTaskGenerator(LocalDate start,
+ LocalDate end, List> allocationsOnInterval) {
+ Validate.notNull(start);
+ Validate.notNull(end);
+ Validate.notNull(allocationsOnInterval);
+ this.start = start;
+ this.end = end;
+ this.allocationsOnInterval = ResourceAllocation
+ .getSatisfied(allocationsOnInterval);
+ }
+
+ public List join(QueueTaskGenerator next) {
+ if (!overlaps(next)) {
+ return stripEmpty(this, next);
+ }
+ if (isIncluded(next)) {
+ return stripEmpty(this.until(next.start), intersect(next), this
+ .from(next.end));
+ }
+ assert overlaps(next) && !isIncluded(next);
+ return stripEmpty(this.until(next.start), intersect(next), next
+ .from(end));
+ }
+
+ protected List> getAllocationsOnInterval() {
+ return allocationsOnInterval;
+ }
+
+ private List stripEmpty(
+ QueueTaskGenerator... generators) {
+ List result = new ArrayList();
+ for (QueueTaskGenerator loadPeriodGenerator : generators) {
+ if (!loadPeriodGenerator.isEmpty()) {
+ result.add(loadPeriodGenerator);
+ }
+ }
+ return result;
+ }
+
+ private boolean isEmpty() {
+ return start.equals(end);
+ }
+
+ protected abstract QueueTaskGenerator create(LocalDate start,
+ LocalDate end, List> allocationsOnInterval);
+
+ private QueueTaskGenerator intersect(QueueTaskGenerator other) {
+ return create(max(this.start, other.start),
+ min(this.end, other.end), plusAllocations(other));
+ }
+
+ private static LocalDate max(LocalDate l1, LocalDate l2) {
+ return l1.compareTo(l2) < 0 ? l2 : l1;
+ }
+
+ private static LocalDate min(LocalDate l1, LocalDate l2) {
+ return l1.compareTo(l2) < 0 ? l1 : l2;
+ }
+
+ private List> plusAllocations(
+ QueueTaskGenerator other) {
+ List> result = new ArrayList>();
+ result.addAll(allocationsOnInterval);
+ result.addAll(other.allocationsOnInterval);
+ return result;
+ }
+
+ private QueueTaskGenerator from(LocalDate newStart) {
+ return create(newStart, end,
+ allocationsOnInterval);
+ }
+
+ private QueueTaskGenerator until(LocalDate newEnd) {
+ return create(start, newEnd,
+ allocationsOnInterval);
+ }
+
+ boolean overlaps(QueueTaskGenerator other) {
+ return (start.compareTo(other.end) < 0 && other.start
+ .compareTo(this.end) < 0);
+ }
+
+ private boolean isIncluded(QueueTaskGenerator other) {
+ return other.start.compareTo(start) >= 0
+ && 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() {
+ int sum = 0;
+ for (ResourceAllocation> resourceAllocation : allocationsOnInterval) {
+ sum += getAssignedHoursFor(resourceAllocation);
+ }
+ return sum;
+ }
+
+ protected abstract int getAssignedHoursFor(
+ ResourceAllocation> resourceAllocation);
+
+ public LocalDate getStart() {
+ return start;
+ }
+
+ public LocalDate getEnd() {
+ return end;
+ }
+}
+
+class QueueTaskGeneratorOnResource extends QueueTaskGenerator {
+
+ private Resource resource;
+
+ private final ICriterion criterion;
+
+ QueueTaskGeneratorOnResource(Resource resource, LocalDate start,
+ LocalDate end, List> allocationsOnInterval,
+ ICriterion criterion) {
+ super(start, end, allocationsOnInterval);
+ this.resource = resource;
+ this.criterion = criterion;
+ }
+
+ QueueTaskGeneratorOnResource(Resource resource,
+ ResourceAllocation> initial, ICriterion criterion) {
+ super(initial.getStartDate(), initial.getEndDate(), Arrays.> asList(initial));
+ this.resource = resource;
+ this.criterion = criterion;
+ }
+
+ @Override
+ protected QueueTaskGenerator create(LocalDate start, LocalDate end,
+ List> allocationsOnInterval) {
+ return new QueueTaskGeneratorOnResource(resource, start, end,
+ allocationsOnInterval, criterion);
+ }
+
+ @Override
+ protected int getTotalWorkHours() {
+ return resource.getTotalWorkHours(start, end, criterion);
+ }
+
+ @Override
+ protected int getAssignedHoursFor(ResourceAllocation> resourceAllocation) {
+ return resourceAllocation.getAssignedHours(resource, start, end);
+ }
+
+ @Override
+ protected int getHoursAssigned() {
+ return sumAllocations();
+ }
+
+}
+
+class QueueTaskGeneratorOnCriterion extends QueueTaskGenerator {
+
+ private final Criterion criterion;
+ private final List resourcesSatisfyingCriterionAtSomePoint;
+
+ public QueueTaskGeneratorOnCriterion(Criterion criterion,
+ ResourceAllocation> allocation,
+ List resourcesSatisfyingCriterionAtSomePoint) {
+ this(criterion, allocation.getStartDate(), allocation.getEndDate(),
+ Arrays.> asList(allocation),
+ resourcesSatisfyingCriterionAtSomePoint);
+ }
+
+ public QueueTaskGeneratorOnCriterion(Criterion criterion,
+ LocalDate startDate, LocalDate endDate,
+ List> allocations,
+ List resourcesSatisfyingCriterionAtSomePoint) {
+ super(startDate, endDate, allocations);
+ this.criterion = criterion;
+ this.resourcesSatisfyingCriterionAtSomePoint = resourcesSatisfyingCriterionAtSomePoint;
+ }
+
+ @Override
+ protected QueueTaskGenerator create(LocalDate start, LocalDate end,
+ List> allocationsOnInterval) {
+ QueueTaskGeneratorOnCriterion result = new QueueTaskGeneratorOnCriterion(
+ criterion, start, end, allocationsOnInterval,
+ resourcesSatisfyingCriterionAtSomePoint);
+ result.specificByResourceCached = specificByResourceCached;
+ return result;
+ }
+
+ private List genericAllocationsOnInterval() {
+ return ResourceAllocation.getOfType(GenericResourceAllocation.class,
+ getAllocationsOnInterval());
+ }
+
+ @Override
+ protected int getAssignedHoursFor(ResourceAllocation> resourceAllocation) {
+ return resourceAllocation.getAssignedHours(start, end);
+ }
+
+ @Override
+ protected int getTotalWorkHours() {
+ int sum = 0;
+ for (Resource resource : resourcesSatisfyingCriterionAtSomePoint) {
+ sum += resource.getTotalWorkHours(start, end, criterion);
+ }
+ return sum;
+ }
+
+ @Override
+ protected int getHoursAssigned() {
+ return sumAllocations();
+ }
+
+ private Map> specificByResourceCached = new HashMap>();
+
+ private List getSpecificOrderedAssignmentsFor(
+ Resource resource) {
+ if (!specificByResourceCached.containsKey(resource)) {
+ specificByResourceCached.put(resource, DayAssignment
+ .specific(DayAssignment.orderedByDay(resource
+ .getAssignments())));
+ }
+ return specificByResourceCached.get(resource);
+ }
+
+ private int sum(List specific) {
+ int result = 0;
+ for (SpecificDayAssignment s : specific) {
+ result += s.getHours();
+ }
+ return result;
+ }
+
+}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/IManageOrderElementAdvancesModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/IManageOrderElementAdvancesModel.java
index a92208fe5..7acbbbe40 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/IManageOrderElementAdvancesModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/IManageOrderElementAdvancesModel.java
@@ -62,7 +62,7 @@ public interface IManageOrderElementAdvancesModel {
public boolean isReadOnlyAdvanceMeasurements();
- public void cleanAdvance();
+ public void cleanAdvance(DirectAdvanceAssignment advance);
public boolean isPrecisionValid(AdvanceMeasurement advanceMeasurement);
@@ -99,4 +99,13 @@ public interface IManageOrderElementAdvancesModel {
public boolean isQualityForm(AdvanceAssignment advance);
public boolean lessThanPreviousMeasurements();
+
+ public boolean hasConsolidatedAdvances(AdvanceAssignment advance);
+
+ public boolean hasConsolidatedAdvances(AdvanceMeasurement advanceMeasurement);
+
+ public boolean findIndirectConsolidation(
+ AdvanceMeasurement advanceMeasurement);
+
+ public void resetAdvanceAssignment();
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/ManageOrderElementAdvancesController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/ManageOrderElementAdvancesController.java
index d509dd2fb..1bacef8a5 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/ManageOrderElementAdvancesController.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/ManageOrderElementAdvancesController.java
@@ -29,6 +29,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.LocalDate;
@@ -164,17 +165,33 @@ public class ManageOrderElementAdvancesController extends
return orderElementModel.getOrderElement();
}
+ private void resetAdvancesGrid() {
+ manageOrderElementAdvancesModel.resetAdvanceAssignment();
+ this.indexSelectedItem = -1;
+ reloadAdvances();
+ }
+
+ private void reloadAdvances() {
+ Util.reloadBindings(self);
+ if (indexSelectedItem > -1) {
+ editAdvances.setSelectedItem(editAdvances
+ .getItemAtIndex(indexSelectedItem));
+ editAdvances.invalidate();
+ }
+ }
+
private Listbox editAdvances;
public void prepareEditAdvanceMeasurements(Listitem selectedItem) {
AdvanceAssignment advanceAssignment = (AdvanceAssignment) selectedItem
.getValue();
if (advanceAssignment.getAdvanceType() != null) {
- validateListAdvanceMeasurement();
- manageOrderElementAdvancesModel
+ validateListAdvanceMeasurement();
+ manageOrderElementAdvancesModel
.prepareEditAdvanceMeasurements(advanceAssignment);
- this.indexSelectedItem = editAdvances.getIndexOfItem(editAdvances.getSelectedItem());
- Util.reloadBindings(self);
+ this.indexSelectedItem = editAdvances.getIndexOfItem(editAdvances
+ .getSelectedItem());
+ reloadAdvances();
} else {
Component comboAdvanceType = selectedItem.getFirstChild()
.getFirstChild();
@@ -187,14 +204,12 @@ public class ManageOrderElementAdvancesController extends
public void goToCreateLineAdvanceAssignment() {
manageOrderElementAdvancesModel.addNewLineAdvaceAssignment();
- manageOrderElementAdvancesModel.prepareEditAdvanceMeasurements(null);
- this.indexSelectedItem = -1;
- Util.reloadBindings(self);
+ resetAdvancesGrid();
}
public void goToCreateLineAdvanceMeasurement() {
manageOrderElementAdvancesModel.addNewLineAdvaceMeasurement();
- Util.reloadBindings(self);
+ reloadAdvances();
}
public void goToRemoveLineAdvanceAssignment(){
@@ -204,7 +219,7 @@ public class ManageOrderElementAdvancesController extends
.getValue();
manageOrderElementAdvancesModel
.removeLineAdvanceAssignment(advanceAssignment);
- Util.reloadBindings(self);
+ reloadAdvances();
}
}
@@ -218,7 +233,7 @@ public class ManageOrderElementAdvancesController extends
if (advanceMeasurement != null) {
manageOrderElementAdvancesModel
.removeLineAdvanceMeasurement(advanceMeasurement);
- Util.reloadBindings(self);
+ reloadAdvances();
}
}
}
@@ -306,8 +321,9 @@ public class ManageOrderElementAdvancesController extends
@Override
public void onEvent(Event event) throws Exception {
setMaxValue(listItem,comboAdvanceTypes);
- cleanFields();
+ cleanFields(advance);
setPercentage();
+ resetAdvancesGrid();
}
});
@@ -351,7 +367,7 @@ public class ManageOrderElementAdvancesController extends
private void appendDecimalBoxMaxValue(final Listitem listItem,
boolean isQualityForm) {
- AdvanceAssignment advanceAssignment = (AdvanceAssignment) listItem
+ final AdvanceAssignment advanceAssignment = (AdvanceAssignment) listItem
.getValue();
Decimalbox maxValue = new Decimalbox();
maxValue.setScale(2);
@@ -379,15 +395,23 @@ public class ManageOrderElementAdvancesController extends
@Override
public void set(BigDecimal value) {
- directAdvanceAssignment.setMaxValue(value);
+ if (!manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advanceAssignment)) {
+ directAdvanceAssignment.setMaxValue(value);
+ }
}
});
maxValue.addEventListener(Events.ON_CHANGE,
new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
- setPercentage();
- Util.reloadBindings(self);
+ if (manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advanceAssignment)) {
+ showMessagesConsolidation(1);
+ } else {
+ setPercentage();
+ reloadAdvances();
+ }
}
});
@@ -531,7 +555,7 @@ public class ManageOrderElementAdvancesController extends
} else {
selectedAdvances.remove(advance);
}
- Util.reloadBindings(self);
+ reloadAdvances();
}
});
@@ -548,9 +572,18 @@ public class ManageOrderElementAdvancesController extends
removeButton.addEventListener(Events.ON_CLICK, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
- manageOrderElementAdvancesModel
+ if (manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advance)) {
+ showMessagesConsolidation(1);
+ } else {
+ manageOrderElementAdvancesModel
.removeLineAdvanceAssignment(advance);
- Util.reloadBindings(self);
+ if (indexSelectedItem == editAdvances
+ .getIndexOfItem(listItem)) {
+ indexSelectedItem = -1;
+ }
+ reloadAdvances();
+ }
}
});
@@ -589,12 +622,14 @@ public class ManageOrderElementAdvancesController extends
Listitem item = (Listitem) comp.getParent().getParent();
DirectAdvanceAssignment advance = (DirectAdvanceAssignment) item
.getValue();
- if (value == null) {
- ((Decimalbox) comp).setValue(advance.getMaxValue());
- ((Decimalbox) comp).invalidate();
- throw new WrongValueException(
- comp,
- _("The max value must be not empty"));
+ if (!manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advance)) {
+ if (value == null) {
+ ((Decimalbox) comp).setValue(advance.getMaxValue());
+ ((Decimalbox) comp).invalidate();
+ throw new WrongValueException(comp,
+ _("The max value must be not empty"));
+ }
}
}
};
@@ -651,7 +686,6 @@ public class ManageOrderElementAdvancesController extends
((Decimalbox) value.getFirstChild()).invalidate();
}
}
-
}
private Chart chart;
@@ -695,29 +729,47 @@ public class ManageOrderElementAdvancesController extends
}
}
- private void cleanFields(){
- this.manageOrderElementAdvancesModel.cleanAdvance();
- Util.reloadBindings(self);
+ private void cleanFields(DirectAdvanceAssignment advance) {
+ this.manageOrderElementAdvancesModel
+ .cleanAdvance((DirectAdvanceAssignment) advance);
}
private void setReportGlobalAdvance(final Listitem item){
- for(int i=0; i< editAdvances.getChildren().size(); i++){
- if(editAdvances.getChildren().get(i) instanceof Listitem){
- Listitem listItem = (Listitem) editAdvances.getChildren().get(i);
- Listcell celdaSpread = (Listcell) listItem.getChildren().get(5);
- Radio radioSpread = ((Radio)celdaSpread.getFirstChild());
- if(!radioSpread.isDisabled()){
- radioSpread.setChecked(false);
- ((AdvanceAssignment) listItem.getValue())
- .setReportGlobalAdvance(false);
+ boolean spread = true;
+ if (!radioSpreadIsConsolidated()) {
+ for (int i = 0; i < editAdvances.getChildren().size(); i++) {
+ if (editAdvances.getChildren().get(i) instanceof Listitem) {
+ Listitem listItem = (Listitem) editAdvances.getChildren()
+ .get(i);
+ Listcell celdaSpread = (Listcell) listItem.getChildren()
+ .get(5);
+ Radio radioSpread = ((Radio) celdaSpread.getFirstChild());
+ if (!radioSpread.isDisabled()) {
+ radioSpread.setChecked(false);
+ ((AdvanceAssignment) listItem.getValue())
+ .setReportGlobalAdvance(false);
+ }
}
}
+ } else {
+ spread = false;
}
Listcell celdaSpread = (Listcell) item.getChildren().get(5);
- ((Radio)celdaSpread.getFirstChild()).setChecked(true);
- ((AdvanceAssignment) item.getValue()).setReportGlobalAdvance(true);
+ ((Radio) celdaSpread.getFirstChild()).setChecked(spread);
+ ((AdvanceAssignment) item.getValue()).setReportGlobalAdvance(spread);
}
+ private boolean radioSpreadIsConsolidated() {
+ for (AdvanceAssignment advance : getAdvanceAssignments()) {
+ if ((advance.getReportGlobalAdvance())
+ && (manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advance))) {
+ showMessagesConsolidation(1);
+ return true;
+ }
+ }
+ return false;
+ }
private boolean validateDataForm(){
return ((validateListAdvanceAssignment())
@@ -845,7 +897,12 @@ public class ManageOrderElementAdvancesController extends
@Override
public void onEvent(Event event) throws Exception {
- updatesValue(value);
+ if (manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advanceMeasurement)) {
+ showMessagesConsolidation(2);
+ } else {
+ updatesValue(value);
+ }
}
});
@@ -859,9 +916,11 @@ public class ManageOrderElementAdvancesController extends
@Override
public void set(BigDecimal value) {
- advanceMeasurement.setValue(value);
- Util.reloadBindings(chart);
- Util.reloadBindings(editAdvances);
+ if (!manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advanceMeasurement)) {
+ advanceMeasurement.setValue(value);
+ reloadAdvances();
+ }
}
});
value.setConstraint(checkValidValue());
@@ -883,7 +942,7 @@ public class ManageOrderElementAdvancesController extends
private void appendDateboxDate(final Listitem listitem) {
final AdvanceMeasurement advanceMeasurement = (AdvanceMeasurement) listitem
.getValue();
- Datebox date = new Datebox();
+ final Datebox date = new Datebox();
Listcell listcell = new Listcell();
listcell.appendChild(date);
@@ -894,7 +953,12 @@ public class ManageOrderElementAdvancesController extends
@Override
public void onEvent(Event event) throws Exception {
- setCurrentDate(listitem);
+ if (manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advanceMeasurement)) {
+ showMessagesConsolidation(2);
+ } else {
+ setCurrentDate(listitem);
+ }
}
});
@@ -912,10 +976,13 @@ public class ManageOrderElementAdvancesController extends
@Override
public void set(Date value) {
- advanceMeasurement.setDate(new LocalDate(value));
- manageOrderElementAdvancesModel
+ if (!manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advanceMeasurement)) {
+ advanceMeasurement.setDate(new LocalDate(value));
+ manageOrderElementAdvancesModel
.sortListAdvanceMeasurement();
- Util.reloadBindings(self);
+ reloadAdvances();
+ }
}
});
date.setConstraint(checkValidDate());
@@ -927,7 +994,9 @@ public class ManageOrderElementAdvancesController extends
public void validate(Component comp, Object value)
throws WrongValueException {
AdvanceMeasurement advanceMeasurement = getAdvanceMeasurementByComponent(comp);
- if (advanceMeasurement != null) {
+ if ((advanceMeasurement != null)
+ && (!manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advanceMeasurement))) {
advanceMeasurement.setValue((BigDecimal) value);
if (((BigDecimal) value) == null) {
throw new WrongValueException(
@@ -977,29 +1046,32 @@ public class ManageOrderElementAdvancesController extends
public void validate(Component comp, Object value)
throws WrongValueException {
AdvanceMeasurement advanceMeasurement = getAdvanceMeasurementByComponent(comp);
- if (((Date) value) == null) {
- advanceMeasurement.setDate(null);
- throw new WrongValueException(
- comp,
- _("The date is not valid, the date must be not empty"));
- } else {
- if (!manageOrderElementAdvancesModel
- .isDistinctValidDate((Date) value,
- advanceMeasurement)) {
+ if ((!manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advanceMeasurement))) {
+ if (((Date) value) == null) {
+ advanceMeasurement.setDate(null);
throw new WrongValueException(
comp,
- _("The date is not valid, the date must be unique for this advanced assignment"));
- }
- if (advanceMeasurement != null) {
- advanceMeasurement.setDate(new LocalDate(
- (Date) value));
- manageOrderElementAdvancesModel
- .sortListAdvanceMeasurement();
- if (manageOrderElementAdvancesModel
- .lessThanPreviousMeasurements()) {
+ _("The date is not valid, the date must be not empty"));
+ } else {
+ if (!manageOrderElementAdvancesModel
+ .isDistinctValidDate((Date) value,
+ advanceMeasurement)) {
throw new WrongValueException(
comp,
- _("Value is not valid, the value must be greater than the value of the previous advances."));
+ _("The date is not valid, the date must be unique for this advanced assignment"));
+ }
+ if (advanceMeasurement != null) {
+ advanceMeasurement.setDate(new LocalDate(
+ (Date) value));
+ manageOrderElementAdvancesModel
+ .sortListAdvanceMeasurement();
+ if (manageOrderElementAdvancesModel
+ .lessThanPreviousMeasurements()) {
+ throw new WrongValueException(
+ comp,
+ _("Value is not valid, the value must be greater than the value of the previous advances."));
+ }
}
}
}
@@ -1016,9 +1088,14 @@ public class ManageOrderElementAdvancesController extends
removeButton.addEventListener(Events.ON_CLICK, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
- manageOrderElementAdvancesModel
+ if (manageOrderElementAdvancesModel
+ .hasConsolidatedAdvances(advance)) {
+ showMessagesConsolidation(2);
+ } else {
+ manageOrderElementAdvancesModel
.removeLineAdvanceMeasurement(advance);
- Util.reloadBindings(self);
+ reloadAdvances();
+ }
}
});
@@ -1047,4 +1124,19 @@ public class ManageOrderElementAdvancesController extends
manageOrderElementAdvancesModel.refreshChangesFromOrderElement();
}
+ private void showMessagesConsolidation(int opcion) {
+ String message = "";
+ switch (opcion) {
+ case 1:
+ message = _("This advance can not be changed or removed, because it has got consolidated advances. It is needed removing the consolidation on all its advances.");
+ break;
+ case 2:
+ message = _("This advance measurement can not be changed or removed, because it is consolidated. It is needed removing its consolidation.");
+ break;
+ }
+ if (!StringUtils.isBlank(message)) {
+ messagesForUser.showMessage(Level.ERROR, message);
+ }
+ }
+
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/ManageOrderElementAdvancesModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/ManageOrderElementAdvancesModel.java
index d8ac6707a..2552c3a2e 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/ManageOrderElementAdvancesModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/ManageOrderElementAdvancesModel.java
@@ -28,6 +28,8 @@ import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
@@ -51,6 +53,8 @@ import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.orders.daos.IOrderElementDAO;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.OrderLineGroup;
+import org.navalplanner.business.planner.entities.consolidations.CalculatedConsolidatedValue;
+import org.navalplanner.business.planner.entities.consolidations.CalculatedConsolidation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
@@ -176,10 +180,22 @@ public class ManageOrderElementAdvancesModel implements
private void forceLoadAdvanceAssignmentsAndMeasurements() {
for (DirectAdvanceAssignment each : orderElement
.getDirectAdvanceAssignments()) {
- each.getAdvanceMeasurements().size();
+ forceLoadAdvanceConsolidatedValues(each);
+ each.getNonCalculatedConsolidation().size();
}
if (orderElement instanceof OrderLineGroup) {
((OrderLineGroup) orderElement).getIndirectAdvanceAssignments().size();
+ for (IndirectAdvanceAssignment each : ((OrderLineGroup) orderElement)
+ .getIndirectAdvanceAssignments()) {
+ each.getCalculatedConsolidation().size();
+ }
+ }
+ }
+
+ private void forceLoadAdvanceConsolidatedValues(
+ DirectAdvanceAssignment advance) {
+ for (AdvanceMeasurement measurement : advance.getAdvanceMeasurements()) {
+ measurement.getNonCalculatedConsolidatedValues().size();
}
}
@@ -302,18 +318,18 @@ public class ManageOrderElementAdvancesModel implements
}
@Override
- public void cleanAdvance(){
- if (this.advanceAssignment != null) {
- this.advanceAssignment.setReportGlobalAdvance(false);
- List listAdvanceMeasurements = new ArrayList(
- this.advanceAssignment.getAdvanceMeasurements());
- for (AdvanceMeasurement advanceMeasurement : listAdvanceMeasurements) {
- advanceMeasurement.setValue(BigDecimal.ZERO);
- advanceMeasurement.setDate(null);
- }
+ public void cleanAdvance(DirectAdvanceAssignment advanceAssignment) {
+ if (advanceAssignment != null) {
+ advanceAssignment.setReportGlobalAdvance(false);
+ advanceAssignment.getAdvanceMeasurements().clear();
}
}
+ @Override
+ public void resetAdvanceAssignment() {
+ this.advanceAssignment = null;
+ }
+
@Override
@Transactional(readOnly = true)
public void confirmSave() throws InstanceNotFoundException,
@@ -561,6 +577,50 @@ public class ManageOrderElementAdvancesModel implements
return xymodel;
}
+ @Override
+ @Transactional(readOnly = true)
+ public boolean hasConsolidatedAdvances(AdvanceAssignment advance) {
+ if (advance instanceof DirectAdvanceAssignment) {
+ if ((advance.getReportGlobalAdvance())
+ && (!((DirectAdvanceAssignment) advance)
+ .getNonCalculatedConsolidation().isEmpty())) {
+ return true;
+ }
+ return (!((DirectAdvanceAssignment) advance).isFake())
+ && (containsAnyConsolidatedAdvanceMeasurement((DirectAdvanceAssignment) advance));
+
+ } else {
+ return ((advance.getReportGlobalAdvance()) && (!((IndirectAdvanceAssignment) advance)
+ .getCalculatedConsolidation().isEmpty()));
+ }
+ }
+
+ private boolean containsAnyConsolidatedAdvanceMeasurement(
+ DirectAdvanceAssignment advance) {
+ Iterator iterator = advance
+ .getAdvanceMeasurements().iterator();
+ while (iterator.hasNext()) {
+ if (hasConsolidatedAdvances(iterator.next())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Transactional(readOnly = true)
+ public boolean hasConsolidatedAdvances(
+ AdvanceMeasurement advanceMeasurement) {
+
+ if (advanceMeasurement.isNewObject() || isIndirectAdvanceAssignment) {
+ return false;
+ }
+
+ if (!advanceMeasurement.getNonCalculatedConsolidatedValues().isEmpty()) {
+ return true;
+ }
+ return findIndirectConsolidation(advanceMeasurement);
+ }
+
@Override
@Transactional(readOnly = true)
public boolean isQualityForm(AdvanceAssignment advance) {
@@ -569,4 +629,69 @@ public class ManageOrderElementAdvancesModel implements
return advanceType.isQualityForm();
}
+ @Override
+ @Transactional(readOnly = true)
+ public boolean findIndirectConsolidation(
+ AdvanceMeasurement advanceMeasurement) {
+
+ AdvanceAssignment advance = advanceMeasurement.getAdvanceAssignment();
+ if ((orderElement != null) && (orderElement.getParent() != null) && (advance instanceof DirectAdvanceAssignment)) {
+
+ List types = new ArrayList();
+
+ types.add(advance.getAdvanceType().getUnitName());
+ if (advance.getReportGlobalAdvance()) {
+ types.add(PredefinedAdvancedTypes.CHILDREN.getTypeName());
+ }
+
+ Set indirects = getSpreadIndirectAdvanceAssignmentWithSameType(
+ orderElement, types);
+
+ for (IndirectAdvanceAssignment indirect : indirects) {
+ if (findConsolidatedAdvance(indirect
+ .getCalculatedConsolidation(), advanceMeasurement)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private Set getSpreadIndirectAdvanceAssignmentWithSameType(
+ OrderElement orderElement, List types) {
+
+ orderElementDAO.reattach(orderElement);
+ Set result = new HashSet();
+
+ for (IndirectAdvanceAssignment indirect : orderElement
+ .getIndirectAdvanceAssignments()) {
+ if ((indirect.getReportGlobalAdvance())
+ && (types.contains(indirect.getAdvanceType().getUnitName()))) {
+ result.add(indirect);
+ }
+ }
+
+ OrderElement parent = orderElement.getParent();
+ if (parent != null) {
+ result.addAll(getSpreadIndirectAdvanceAssignmentWithSameType(
+ parent, types));
+ }
+
+ return result;
+ }
+
+ private boolean findConsolidatedAdvance(
+ Set consolidations,
+ AdvanceMeasurement advance) {
+ for (CalculatedConsolidation consolidation : consolidations) {
+ for (CalculatedConsolidatedValue value : consolidation
+ .getCalculatedConsolidatedValues()) {
+ if (value.getDate().compareTo(advance.getDate()) == 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeController.java
index 0b4dc801f..41d94c102 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeController.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderElementTreeController.java
@@ -410,7 +410,7 @@ public class OrderElementTreeController extends TreeController {
InputElement codeBox = (InputElement)
((Treecell)row.getChildren().get(1)).getChildren().get(0);
InputElement nameBox = (InputElement)
- ((Treecell)row.getChildren().get(2)).getChildren().get(1);
+ ((Treecell)row.getChildren().get(2)).getChildren().get(0);
InputElement hoursBox = (InputElement)
((Treecell)row.getChildren().get(3)).getChildren().get(0);
InputElement initDateBox = (InputElement)
@@ -423,30 +423,13 @@ public class OrderElementTreeController extends TreeController {
@Override
protected void addDescriptionCell(OrderElement element) {
- addTaskNumberCell(element);
+ addTaskNameCell(element);
}
- private void addTaskNumberCell(final OrderElement orderElementForThisRow) {
+ private void addTaskNameCell(final OrderElement orderElementForThisRow) {
int[] path = getModel().getPath(orderElementForThisRow);
String cssClass = "depth_" + path.length;
- Label taskNumber = new Label(pathAsString(path));
- taskNumber.setSclass("tasknumber");
- taskNumber.addEventListener(Events.ON_DOUBLE_CLICK,
- new EventListener() {
-
- @Override
- public void onEvent(Event event) throws Exception {
- IOrderElementModel model = orderModel
- .getOrderElementModel(orderElementForThisRow);
- orderElementController.openWindow(model);
- // Util.reloadBindings(tree);
- }
-
- });
-
- // TODO It would be needed to expand the width for the numbers
- // to make it ready for 2 and 3 digit numbers
Textbox textBox = Util.bind(new Textbox(),
new Util.Getter() {
@@ -464,7 +447,7 @@ public class OrderElementTreeController extends TreeController {
if (readOnly) {
textBox.setDisabled(true);
}
- addCell(cssClass, taskNumber, textBox);
+ addCell(cssClass, textBox);
registerKeyboardListener(textBox);
}
@@ -584,6 +567,7 @@ public class OrderElementTreeController extends TreeController {
notifyDateboxCantBeCreated(dateboxName, currentOrderElement
.getCode());
}
+ registerFocusEvent(dinamicDatebox.getDateTextBox());
addCell(cell);
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRow.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRow.java
index efa5aff8d..88cff794e 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRow.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/AllocationRow.java
@@ -266,7 +266,12 @@ public abstract class AllocationRow {
public void setResourcesPerDay(ResourcesPerDay resourcesPerDay) {
this.resourcesPerDay = resourcesPerDay;
- resourcesPerDayInput.setValue(this.resourcesPerDay.getAmount());
+ resourcesPerDayInput.setValue(getAmount(resourcesPerDay));
+ }
+
+ private BigDecimal getAmount(ResourcesPerDay resourcesPerDay) {
+ return (resourcesPerDay != null) ? resourcesPerDay.getAmount()
+ : new BigDecimal(0);
}
public void setTemporal(ResourceAllocation> last) {
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ILimitingResourceAllocationModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ILimitingResourceAllocationModel.java
index 852cd5876..336c51db4 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ILimitingResourceAllocationModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ILimitingResourceAllocationModel.java
@@ -24,7 +24,6 @@ import java.util.List;
import org.navalplanner.business.orders.entities.AggregatedHoursGroup;
import org.navalplanner.business.planner.entities.Task;
-import org.navalplanner.web.planner.allocation.LimitingResourceAllocationModel.LimitingResourceAllocationRow;
/**
* Contract for {@link Task}.
@@ -33,14 +32,14 @@ import org.navalplanner.web.planner.allocation.LimitingResourceAllocationModel.L
*/
public interface ILimitingResourceAllocationModel extends INewAllocationsAdder {
+ void confirmSave();
+
List getHoursAggregatedByCriteria();
Integer getOrderHours();
- List getResourceAllocations();
+ List getResourceAllocationRows();
void init(Task task);
- void removeAllResourceAllocations();
-
-}
+}
\ No newline at end of file
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingAllocationRow.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingAllocationRow.java
new file mode 100644
index 000000000..61b90fe88
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingAllocationRow.java
@@ -0,0 +1,232 @@
+/*
+ * 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 .
+ */
+package org.navalplanner.web.planner.allocation;
+
+import static org.navalplanner.business.i18n.I18nHelper._;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.math.NumberUtils;
+import org.navalplanner.business.planner.entities.GenericResourceAllocation;
+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.Resource;
+import org.navalplanner.web.common.components.NewAllocationSelector.AllocationType;
+
+/**
+ *
+ * @author Diego Pino Garcia
+ *
+ */
+public class LimitingAllocationRow {
+
+ public static final int DEFAULT_PRIORITY = 5;
+
+ private ResourceAllocation> resourceAllocation;
+
+ private int hours = 0;
+
+ private int priority = DEFAULT_PRIORITY;
+
+ private Task task;
+
+ private Collection extends Resource> resources;
+
+ public LimitingAllocationRow() {
+
+ }
+
+ public static List toRows(Task task) {
+ List result = new ArrayList();
+ for (ResourceAllocation> each : task.getLimitingResourceAllocations()) {
+ result.add(new LimitingAllocationRow(each, task));
+ }
+ return result;
+ }
+
+ public static LimitingAllocationRow create(Resource resource, Task task) {
+ return new LimitingAllocationRow(SpecificResourceAllocation.create(resource, task), task);
+ }
+
+ private LimitingAllocationRow(ResourceAllocation> resourceAllocation,
+ Task task) {
+ this.resourceAllocation = resourceAllocation;
+ this.task = task;
+ this.hours = calculateTotalHours();
+ this.priority = task.getPriority();
+ }
+
+ /**
+ * Returns initial total hours
+ *
+ * @return
+ */
+ private Integer calculateTotalHours() {
+ return (resourceAllocation != null && resourceAllocation.getIntendedTotalHours() != null) ?
+ resourceAllocation.getIntendedTotalHours() : task.getTotalHours();
+ }
+
+ public static LimitingAllocationRow create(Set criteria,
+ Collection extends Resource> resources, Task task, int priority) {
+ LimitingAllocationRow result = new LimitingAllocationRow(
+ GenericResourceAllocation.create(task, criteria), task,
+ priority);
+ result.setResources(resources);
+ return result;
+ }
+
+ private void setResources(Collection extends Resource> resources) {
+ this.resources = resources;
+ }
+
+ public static LimitingAllocationRow create(Resource resource, Task task,
+ int priority) {
+ return new LimitingAllocationRow(SpecificResourceAllocation.create(
+ resource, task), task, priority);
+ }
+
+ private LimitingAllocationRow(ResourceAllocation> resourceAllocation,
+ Task task, int priority) {
+
+ this.resourceAllocation = resourceAllocation;
+ this.task = task;
+ this.hours = calculateTotalHours();
+
+ task.setPriority(priority);
+ this.priority = task.getPriority();
+ }
+
+ public AllocationType getAllocationType() {
+ return (resourceAllocation instanceof SpecificResourceAllocation) ? AllocationType.SPECIFIC
+ : AllocationType.GENERIC;
+ }
+
+ public String getAllocationTypeStr() {
+ return getAllocationType().toString();
+ }
+
+ public String getAllocation() {
+ final AllocationType type = getAllocationType();
+ if (AllocationType.GENERIC.equals(type)) {
+ final GenericResourceAllocation generic = (GenericResourceAllocation) resourceAllocation;
+ return formatCriteria(generic.getCriterions());
+ }
+ if (AllocationType.SPECIFIC.equals(type)) {
+ return formatResources(resourceAllocation.getAssociatedResources());
+ }
+ return "";
+ }
+
+ private String formatCriteria(Set criteria) {
+ List criteriaNames = new ArrayList();
+ for (Criterion each: criteria) {
+ criteriaNames.add(each.getName());
+ }
+ return (criteriaNames.isEmpty()) ? _("[generic all workers]") : StringUtils.join(criteriaNames, ",");
+ }
+
+ private String formatResources(List resources) {
+ List resourcesNames = new ArrayList();
+ for (Resource each: resources) {
+ resourcesNames.add(each.getName());
+ }
+ return StringUtils.join(resourcesNames, ",");
+ }
+
+ public int getHours() {
+ return hours;
+ }
+
+ public void setHours(int hours) {
+ this.hours = hours;
+ updateHours(resourceAllocation, hours);
+ }
+
+ private void updateHours(ResourceAllocation> resourceAllocation, final int hours) {
+ if (resourceAllocation != null) {
+ resourceAllocation.setIntendedTotalHours(hours);
+ }
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public String getPriorityStr() {
+ return (new Integer(getPriority()).toString());
+ }
+
+ public void setPriorityStr(String priority) {
+ this.priority = toNumber(priority);
+ task.setPriority(this.priority);
+ }
+
+ private int toNumber(String str) {
+ if (NumberUtils.isNumber(str)) {
+ int result = NumberUtils.toInt(str);
+ return (result >= 1 && result <= 10) ? result : 1;
+ }
+ return 1;
+ }
+
+ public ResourceAllocation> getResourceAllocation() {
+ return resourceAllocation;
+ }
+
+ public Set getResourcesIds() {
+ Set result = new HashSet();
+ if (resources != null) {
+ for (Resource each: resources) {
+ result.add(each.getId());
+ }
+ }
+ return result;
+ }
+
+ public Set getCriteriaIds() {
+ Set result = new HashSet();
+
+ if (resourceAllocation instanceof GenericResourceAllocation) {
+ GenericResourceAllocation generic = (GenericResourceAllocation) resourceAllocation;
+ for (Criterion each: generic.getCriterions()) {
+ result.add(each.getId());
+ }
+ }
+ return result;
+ }
+
+ public boolean isSpecific() {
+ return resourceAllocation != null
+ && resourceAllocation instanceof SpecificResourceAllocation;
+ }
+
+ public boolean isGeneric() {
+ return resourceAllocation != null
+ && resourceAllocation instanceof GenericResourceAllocation;
+ }
+
+}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingResourceAllocationController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingResourceAllocationController.java
index 825d8ef99..c2199086b 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingResourceAllocationController.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingResourceAllocationController.java
@@ -27,11 +27,9 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.navalplanner.business.orders.entities.AggregatedHoursGroup;
import org.navalplanner.business.planner.entities.ResourceAllocation;
-import org.navalplanner.web.common.ConstraintChecker;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.Util;
import org.navalplanner.web.common.components.NewAllocationSelector;
-import org.navalplanner.web.planner.allocation.LimitingResourceAllocationModel.LimitingResourceAllocationRow;
import org.navalplanner.web.planner.allocation.ResourceAllocationController.HoursRendererColumn;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -100,7 +98,7 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
resourceAllocationModel.getHoursAggregatedByCriteria()));
gridLimitingOrderElementHours.setRowRenderer(createOrderElementHoursRenderer());
} catch (Exception e) {
-
+ LOG.error(e.getStackTrace());
}
}
@@ -123,12 +121,8 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
return resourceAllocationModel.getOrderHours();
}
- public List getResourceAllocations() {
- return resourceAllocationModel.getResourceAllocations();
- }
-
- public void removeAllResourceAllocations() {
- resourceAllocationModel.removeAllResourceAllocations();
+ public List getResourceAllocationRows() {
+ return resourceAllocationModel.getResourceAllocationRows();
}
public void onSelectWorkers(Event event) {
@@ -142,7 +136,6 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
}
private void addSelectedResources() {
- resourceAllocationModel.removeAllResourceAllocations();
limitingNewAllocationSelector.addChoosen();
}
@@ -151,7 +144,6 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
}
public void clear() {
- resourceAllocationModel.removeAllResourceAllocations();
limitingNewAllocationSelector.clearAll();
}
@@ -159,13 +151,17 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
return gridLimitingAllocationRenderer;
}
+ public void accept() {
+ resourceAllocationModel.confirmSave();
+ }
+
public class GridLimitingAllocationRenderer implements RowRenderer {
@Override
public void render(Row row, Object data) throws Exception {
- LimitingResourceAllocationRow resourceAllocation = (LimitingResourceAllocationRow) data;
+ LimitingAllocationRow resourceAllocation = (LimitingAllocationRow) data;
- row.appendChild(label(resourceAllocation.getAllocationType()));
+ row.appendChild(label(resourceAllocation.getAllocationTypeStr()));
row.appendChild(label(resourceAllocation.getAllocation()));
row.appendChild(intboxHours(resourceAllocation));
row.appendChild(listboxPriority(resourceAllocation));
@@ -175,11 +171,11 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
return new Label(value);
}
- private Intbox intboxHours(final LimitingResourceAllocationRow resourceAllocation) {
+ private Intbox intboxHours(final LimitingAllocationRow resourceAllocation) {
return bindToHours(new Intbox(), resourceAllocation);
}
- private Intbox bindToHours(Intbox intbox, final LimitingResourceAllocationRow resourceAllocation) {
+ private Intbox bindToHours(Intbox intbox, final LimitingAllocationRow resourceAllocation) {
Util.bind(intbox, new Util.Getter() {
@Override
@@ -197,7 +193,7 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
return intbox;
}
- private Listbox listboxPriority(final LimitingResourceAllocationRow resourceAllocation) {
+ private Listbox listboxPriority(final LimitingAllocationRow resourceAllocation) {
return bindToPriority(buildPriorityList(resourceAllocation.getPriority()), resourceAllocation);
}
@@ -221,17 +217,24 @@ public class LimitingResourceAllocationController extends GenericForwardComposer
return result;
}
- private Listbox bindToPriority(Listbox listbox, final LimitingResourceAllocationRow resourceAllocation) {
+ private Listbox bindToPriority(Listbox listbox, final LimitingAllocationRow resourceAllocation) {
listbox.addEventListener("onSelect", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
- resourceAllocation.setPriorityStr((String) event.getData());
+ String priority = getSelectedValue((Listbox) event.getTarget());
+ resourceAllocation.setPriorityStr(priority);
}
});
return listbox;
}
+ private String getSelectedValue(Listbox listbox) {
+ final Listitem item = listbox.getSelectedItem();
+ final Listcell cell = (Listcell) item.getChildren().get(0);
+ return cell.getLabel();
+ }
+
}
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingResourceAllocationModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingResourceAllocationModel.java
index fefa3d88c..815ff1b77 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingResourceAllocationModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/LimitingResourceAllocationModel.java
@@ -20,26 +20,26 @@
package org.navalplanner.web.planner.allocation;
-import static org.navalplanner.business.i18n.I18nHelper._;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import org.apache.commons.lang.math.NumberUtils;
import org.navalplanner.business.orders.daos.IHoursGroupDAO;
import org.navalplanner.business.orders.entities.AggregatedHoursGroup;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.TaskSource;
+import org.navalplanner.business.planner.daos.ITaskElementDAO;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
+import org.navalplanner.business.planner.entities.LimitingResourceQueueElement;
+import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.resources.daos.ICriterionDAO;
+import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.business.resources.entities.Resource;
-import org.navalplanner.web.common.components.NewAllocationSelector.AllocationType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
@@ -64,120 +64,87 @@ public class LimitingResourceAllocationModel implements ILimitingResourceAllocat
@Autowired
private ICriterionDAO criterionDAO;
+ @Autowired
+ private ITaskElementDAO taskDAO;
+
+ @Autowired
+ private IResourceDAO resourceDAO;
+
private Task task;
- private List resourceAllocations = new ArrayList();
+ private List limitingAllocationRows = new ArrayList();
@Override
public void init(Task task) {
this.task = task;
- this.resourceAllocations = new ArrayList();
+ limitingAllocationRows = LimitingAllocationRow.toRows(task);
}
@Override
+ @Transactional(readOnly=true)
public Integer getOrderHours() {
if (task == null) {
return 0;
}
- return AggregatedHoursGroup.sum(task.getAggregatedByCriterions());
- }
-
- public class LimitingResourceAllocationRow {
-
- private static final int DEFAULT_PRIORITY = 5;
-
- private AllocationType type = AllocationType.GENERIC;
-
- private int hours = 0;
-
- private int priority = DEFAULT_PRIORITY;
-
- public LimitingResourceAllocationRow() {
-
- }
-
- public LimitingResourceAllocationRow(AllocationType type, int hours) {
- this(type, hours, DEFAULT_PRIORITY);
- }
-
- public LimitingResourceAllocationRow(AllocationType type, int hours, int priority) {
- this.type = type;
- this.hours = hours;
- this.priority = priority;
- }
-
- public String getAllocationType() {
- return type.toString();
- }
-
- public String getAllocation() {
- if (AllocationType.GENERIC.equals(type)) {
- return _("Criteria");
- }
- if (AllocationType.SPECIFIC.equals(type)) {
- return _("Resource");
- }
- return "";
- }
-
- public int getHours() {
- return hours;
- }
-
- public void setHours(int hours) {
- this.hours = hours;
- }
-
- public int getPriority() {
- return priority;
- }
-
- public String getPriorityStr() {
- return (new Integer(priority)).toString();
- }
-
- public void setPriorityStr(String priority) {
- this.priority = toNumber(priority);
- }
-
- private int toNumber(String str) {
- if (NumberUtils.isNumber(str)) {
- int result = NumberUtils.toInt(str);
- return (result >= 1 && result <= 10) ? result : 1;
- }
- return 1;
- }
-
- };
-
- private void addSpecificResourceAllocation(Resource resource) {
- LimitingResourceAllocationRow resourceAllocation = new LimitingResourceAllocationRow(
- AllocationType.SPECIFIC, getSumHoursGroups());
- resourceAllocations.add(resourceAllocation);
- }
-
- private int getSumHoursGroups() {
- return task.getTaskSource().getTotalHours();
- }
-
- private void addGenericResourceAllocation(Resource resource) {
- LimitingResourceAllocationRow resourceAllocation = new LimitingResourceAllocationRow(
- AllocationType.GENERIC, getSumHoursGroups());
- resourceAllocations.add(resourceAllocation);
+ return AggregatedHoursGroup.sum(getHoursAggregatedByCriteria());
}
@Override
- public void addGeneric(Set criterions,
+ @Transactional(readOnly = true)
+ public void addGeneric(Set criteria,
Collection extends Resource> resources) {
if (resources.size() >= 1) {
- addGenericResourceAllocation(getFirstChild(resources));
+ reattachResources(resources);
+ addGenericResourceAllocation(criteria, resources);
}
}
+ private void reattachResources(Collection extends Resource> resources) {
+ for (Resource each: resources) {
+ resourceDAO.reattach(each);
+ }
+ }
+
+ private void addGenericResourceAllocation(Set criteria,
+ Collection extends Resource> resources) {
+ if (isNew(criteria, resources)) {
+ limitingAllocationRows.clear();
+ LimitingAllocationRow allocationRow = LimitingAllocationRow.create(
+ criteria, resources, task, LimitingAllocationRow.DEFAULT_PRIORITY);
+ limitingAllocationRows.add(allocationRow);
+ }
+ }
+
+ private boolean isNew(Set criteria, Collection extends Resource> resources) {
+ LimitingAllocationRow allocationRow = getLimitingAllocationRow();
+
+ if (allocationRow == null || allocationRow.isSpecific()) {
+ return true;
+ }
+
+ Set allocatedResourcesIds = allocationRow.getResourcesIds();
+ for (Resource each: resources) {
+ if (!allocatedResourcesIds.contains(each.getId())) {
+ return true;
+ }
+ }
+
+ Set allocatedCriteriaIds = allocationRow.getCriteriaIds();
+ for (Criterion each: criteria) {
+ if (!allocatedCriteriaIds.contains(each.getId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
+ @Transactional(readOnly = true)
public void addSpecific(Collection extends Resource> resources) {
if (resources.size() >= 1) {
- addSpecificResourceAllocation(getFirstChild(resources));
+ Resource resource = getFirstChild(resources);
+ resourceDAO.reattach(resource);
+ addSpecificResourceAllocation(resource);
}
}
@@ -185,9 +152,58 @@ public class LimitingResourceAllocationModel implements ILimitingResourceAllocat
return collection.iterator().next();
}
+ private void addSpecificResourceAllocation(Resource resource) {
+ if (isNew(resource)) {
+ limitingAllocationRows.clear();
+ LimitingAllocationRow allocationRow = LimitingAllocationRow.create(
+ resource, task, LimitingAllocationRow.DEFAULT_PRIORITY);
+ limitingAllocationRows.add(allocationRow);
+ }
+ }
+
+ private boolean isNew(Resource resource) {
+ LimitingAllocationRow allocationRow = getLimitingAllocationRow();
+
+ if (allocationRow == null || allocationRow.isGeneric()) {
+ return true;
+ }
+
+ final Resource taskResource = getAssociatedResource();
+ if (taskResource != null) {
+ return (!resource.getId().equals(taskResource.getId()));
+ }
+ return true;
+ }
+
+ private Resource getAssociatedResource() {
+ ResourceAllocation> resourceAllocation = getAssociatedResourceAllocation();
+ if (resourceAllocation != null) {
+ List resources = resourceAllocation.getAssociatedResources();
+ if (resources != null && resources.size() >= 1) {
+ return (Resource) resources.iterator().next();
+ }
+ }
+ return null;
+ }
+
+ private ResourceAllocation> getAssociatedResourceAllocation() {
+ LimitingAllocationRow allocationRow = getLimitingAllocationRow();
+ if (allocationRow != null) {
+ return allocationRow.getResourceAllocation();
+ }
+ return null;
+ }
+
+ private LimitingAllocationRow getLimitingAllocationRow() {
+ if (limitingAllocationRows.size() >= 1) {
+ return limitingAllocationRows.get(0);
+ }
+ return null;
+ }
+
@Override
- public List getResourceAllocations() {
- return Collections.unmodifiableList(resourceAllocations);
+ public List getResourceAllocationRows() {
+ return Collections.unmodifiableList(limitingAllocationRows);
}
@Override
@@ -243,8 +259,22 @@ public class LimitingResourceAllocationModel implements ILimitingResourceAllocat
}
@Override
- public void removeAllResourceAllocations() {
- resourceAllocations.clear();
+ @Transactional(readOnly=true)
+ public void confirmSave() {
+ taskDAO.reattach(task);
+ ResourceAllocation> resourceAllocation = getAssociatedResourceAllocation();
+ if (resourceAllocation != null && resourceAllocation.isNewObject()) {
+ task.removeAllResourceAllocations();
+ addResourceAllocation(task, resourceAllocation);
+ }
+ taskDAO.save(task);
}
-}
+ private void addResourceAllocation(Task task, ResourceAllocation> resourceAllocation) {
+ LimitingResourceQueueElement element = LimitingResourceQueueElement.create();
+ element.setEarlierStartDateBecauseOfGantt(task.getStartDate());
+ resourceAllocation.setLimitingResourceQueueElement(element);
+ task.addResourceAllocation(resourceAllocation, false);
+ }
+
+}
\ No newline at end of file
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationCommand.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationCommand.java
index 7518c2bf4..4bb733f38 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationCommand.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationCommand.java
@@ -51,16 +51,22 @@ public class ResourceAllocationCommand implements IResourceAllocationCommand {
public ResourceAllocationCommand() {
}
- @Override
- public void doAction(IContextWithPlannerTask context,
- TaskElement task) {
- editTaskUtilities.reattach(task);
+ @Override
+ public void doAction(IContextWithPlannerTask context,
+ TaskElement taskElement) {
+ editTaskUtilities.reattach(taskElement);
- if (isApplicableTo(task)) {
- this.editTaskController.showEditFormResourceAllocation(context,
- (Task) task, planningState);
- }
- }
+ if (isApplicableTo(taskElement)) {
+ Task task = (Task) taskElement;
+ if (task.isSubcontracted()) {
+ editTaskController.showEditFormSubcontract(context, task,
+ planningState);
+ } else {
+ editTaskController.showEditFormResourceAllocation(context,
+ task, planningState);
+ }
+ }
+ }
@Override
public String getName() {
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java
index 668e48aa9..422814096 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationController.java
@@ -71,7 +71,6 @@ import org.zkoss.zul.Row;
import org.zkoss.zul.RowRenderer;
import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.Tab;
-import org.zkoss.zul.api.Tabpanel;
/**
* Controller for {@link ResourceAllocation} view.
@@ -121,8 +120,6 @@ public class ResourceAllocationController extends GenericForwardComposer {
private Tab workerSearchTab;
- private Tabpanel tabpanel;
-
public static void registerNeededScripts() {
getScriptsRegister()
.register(ScriptsRequiredByAdvancedAllocation.class);
@@ -136,7 +133,6 @@ public class ResourceAllocationController extends GenericForwardComposer {
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
- tabpanel = (Tabpanel) comp;
allResourcesPerDay = new Decimalbox();
newAllocationSelector.setLimitingResourceFilter(false);
makeReadyInputsForCalculationTypes();
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationModel.java
index 04504b4d9..987f6eadc 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/allocation/ResourceAllocationModel.java
@@ -246,8 +246,8 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
reattachCriterions(this.task.getHoursGroup().getValidCriterions());
loadResources(this.task.getSatisfiedResourceAllocations());
loadDerivedAllocations(this.task.getSatisfiedResourceAllocations());
- List initialRows = AllocationRow.toRows(this.task
- .getAllResourceAllocations(), resourceDAO);
+ List initialRows = AllocationRow.toRows(task
+ .getNonLimitingResourceAllocations(), resourceDAO);
allocationRowsHandler = AllocationRowsHandler.create(task, initialRows,
createWorkerFinder());
return allocationRowsHandler;
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java
index 1f043f56d..4a359be3b 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/company/CompanyPlanningModel.java
@@ -42,6 +42,7 @@ import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay;
import org.navalplanner.business.common.IAdHocTransactionService;
import org.navalplanner.business.common.IOnTransaction;
+import org.navalplanner.business.common.daos.IConfigurationDAO;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.orders.daos.IOrderDAO;
import org.navalplanner.business.orders.entities.Order;
@@ -82,6 +83,7 @@ import org.zkforge.timeplot.Plotinfo;
import org.zkforge.timeplot.Timeplot;
import org.zkforge.timeplot.geometry.TimeGeometry;
import org.zkforge.timeplot.geometry.ValueGeometry;
+import org.zkoss.ganttz.IChartVisibilityChangedListener;
import org.zkoss.ganttz.IPredicate;
import org.zkoss.ganttz.Planner;
import org.zkoss.ganttz.adapters.IStructureNavigator;
@@ -154,6 +156,11 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
private MultipleTabsPlannerController tabs;
+ private List keepAliveChartVisibilityListeners = new ArrayList();
+
+ @Autowired
+ private IConfigurationDAO configurationDAO;
+
@Autowired
private IScenarioManager scenarioManager;
@@ -205,6 +212,8 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
IPredicate predicate) {
PlannerConfiguration configuration = createConfiguration(predicate);
+ configuration.setExpandPlanningViewCharts(configurationDAO
+ .getConfiguration().isExpandCompanyPlanningViewCharts());
Tabbox chartComponent = new Tabbox();
chartComponent.setOrient("vertical");
@@ -247,22 +256,26 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
configuration.setSecondLevelModificators(new BankHolidaysMarker());
planner.setConfiguration(configuration);
- Timeplot chartLoadTimeplot = new Timeplot();
- Timeplot chartEarnedValueTimeplot = new Timeplot();
+ Timeplot chartLoadTimeplot = createEmptyTimeplot();
+ Timeplot chartEarnedValueTimeplot = createEmptyTimeplot();
CompanyEarnedValueChartFiller earnedValueChartFiller = new CompanyEarnedValueChartFiller();
earnedValueChartFiller.calculateValues(planner.getTimeTracker()
.getRealInterval());
appendTabpanels(chartComponent, chartLoadTimeplot,
chartEarnedValueTimeplot, earnedValueChartFiller);
- setupChart(chartLoadTimeplot, new CompanyLoadChartFiller(), planner
- .getTimeTracker(), planner.getZoomLevel());
+ setupChart(chartLoadTimeplot, new CompanyLoadChartFiller(), planner);
Chart earnedValueChart = setupChart(chartEarnedValueTimeplot,
- earnedValueChartFiller, planner.getTimeTracker(),
- planner.getZoomLevel());
+ earnedValueChartFiller, planner);
setEventListenerConfigurationCheckboxes(earnedValueChart);
}
+ private Timeplot createEmptyTimeplot() {
+ Timeplot timeplot = new Timeplot();
+ timeplot.appendChild(new Plotinfo());
+ return timeplot;
+ }
+
private void appendTabs(Tabbox chartComponent) {
Tabs chartTabs = new Tabs();
chartTabs.appendChild(new Tab(_("Load")));
@@ -486,6 +499,7 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
configuration.setCriticalPathEnabled(false);
configuration.setExpandAllEnabled(false);
configuration.setFlattenTreeEnabled(false);
+ configuration.setRenamingTasksEnabled(false);
}
private void addAdditionalCommands(
@@ -518,17 +532,43 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
}
private Chart setupChart(Timeplot chartComponent,
- IChartFiller loadChartFiller, TimeTracker timeTracker,
- ZoomLevel defaultZoomLevel) {
+ IChartFiller loadChartFiller, Planner planner) {
+ TimeTracker timeTracker = planner.getTimeTracker();
Chart loadChart = new Chart(chartComponent, loadChartFiller,
timeTracker);
- loadChart.setZoomLevel(defaultZoomLevel);
- loadChart.fillChart();
- timeTracker.addZoomListener(fillOnZoomChange(loadChart));
+ loadChart.setZoomLevel(planner.getZoomLevel());
+ if (planner.isVisibleChart()) {
+ loadChart.fillChart();
+ }
+ timeTracker.addZoomListener(fillOnZoomChange(planner, loadChart));
+ planner
+ .addChartVisibilityListener(fillOnChartVisibilityChange(loadChart));
return loadChart;
}
- private IZoomLevelChangedListener fillOnZoomChange(
+ private IChartVisibilityChangedListener fillOnChartVisibilityChange(
+ final Chart loadChart) {
+ IChartVisibilityChangedListener chartVisibilityChangedListener = new IChartVisibilityChangedListener() {
+
+ @Override
+ public void chartVisibilityChanged(final boolean visible) {
+ transactionService
+ .runOnReadOnlyTransaction(new IOnTransaction() {
+ @Override
+ public Void execute() {
+ if (visible) {
+ loadChart.fillChart();
+ }
+ return null;
+ }
+ });
+ }
+ };
+ keepAliveChartVisibilityListeners.add(chartVisibilityChangedListener);
+ return chartVisibilityChangedListener;
+ }
+
+ private IZoomLevelChangedListener fillOnZoomChange(final Planner planner,
final Chart loadChart) {
IZoomLevelChangedListener zoomListener = new IZoomLevelChangedListener() {
@@ -541,7 +581,9 @@ public abstract class CompanyPlanningModel implements ICompanyPlanningModel {
.runOnReadOnlyTransaction(new IOnTransaction() {
@Override
public Void execute() {
- loadChart.fillChart();
+ if (planner.isVisibleChart()) {
+ loadChart.fillChart();
+ }
return null;
}
});
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/consolidations/AdvanceConsolidationCommand.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/consolidations/AdvanceConsolidationCommand.java
new file mode 100644
index 000000000..095b7154f
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/consolidations/AdvanceConsolidationCommand.java
@@ -0,0 +1,87 @@
+/*
+ * 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 .
+ */
+
+package org.navalplanner.web.planner.consolidations;
+
+import static org.navalplanner.web.I18nHelper._;
+
+import org.navalplanner.business.planner.entities.Task;
+import org.navalplanner.business.planner.entities.TaskElement;
+import org.navalplanner.web.planner.order.IEditTaskUtilities;
+import org.navalplanner.web.planner.order.PlanningState;
+import org.navalplanner.web.planner.taskedition.EditTaskController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
+
+/**
+ * A command that opens a window to make the advances consolidations of a task.
+ * @author Susana Montes Pedreira
+ */
+@Component
+@Scope(BeanDefinition.SCOPE_PROTOTYPE)
+public class AdvanceConsolidationCommand implements
+ IAdvanceConsolidationCommand {
+
+ private EditTaskController editTaskController;
+ private PlanningState planningState;
+
+ @Autowired
+ private IEditTaskUtilities editTaskUtilities;
+
+ public AdvanceConsolidationCommand() {
+ }
+
+ @Override
+ public void doAction(IContextWithPlannerTask context,
+ TaskElement task) {
+ editTaskUtilities.reattach(task);
+
+ if (isApplicableTo(task)) {
+ this.editTaskController.showEditFormAdvanceConsolidation(context,
+ (Task) task, planningState);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return _("Advance consolidation");
+ }
+
+ @Override
+ public void initialize(EditTaskController editTaskController,
+ PlanningState planningState) {
+ this.editTaskController = editTaskController;
+ this.planningState = planningState;
+ }
+
+ @Override
+ public String getIcon() {
+ return "/common/img/ico_ok.png";
+ }
+
+ @Override
+ public boolean isApplicableTo(TaskElement task) {
+ return task instanceof Task;
+ }
+
+}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/consolidations/AdvanceConsolidationController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/consolidations/AdvanceConsolidationController.java
new file mode 100644
index 000000000..ef7fc798d
--- /dev/null
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/planner/consolidations/AdvanceConsolidationController.java
@@ -0,0 +1,118 @@
+/*
+ * 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 .
+ */
+
+package org.navalplanner.web.planner.consolidations;
+
+import static org.navalplanner.web.I18nHelper._;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.navalplanner.business.planner.entities.TaskElement;
+import org.navalplanner.web.common.IMessagesForUser;
+import org.navalplanner.web.common.Util;
+import org.navalplanner.web.planner.order.PlanningState;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
+import org.zkoss.zk.ui.Component;
+import org.zkoss.zk.ui.event.Event;
+import org.zkoss.zk.ui.util.GenericForwardComposer;
+import org.zkoss.zul.Grid;
+
+/**
+ * Controller for {@link Advance} consolidation view.
+ * @author Susana Montes Pedreira
+ */
+@org.springframework.stereotype.Component("advanceConsolidationController")
+@Scope(BeanDefinition.SCOPE_PROTOTYPE)
+public class AdvanceConsolidationController extends GenericForwardComposer {
+
+ private static final Log LOG = LogFactory
+ .getLog(AdvanceConsolidationController.class);
+
+ private IAdvanceConsolidationModel advanceConsolidationModel;
+
+ private Grid advancesGrid;
+
+ @Override
+ public void doAfterCompose(Component comp) throws Exception {
+ super.doAfterCompose(comp);
+ }
+
+ public void init(IContextWithPlannerTask context,
+ org.navalplanner.business.planner.entities.Task task,
+ PlanningState planningState, IMessagesForUser messagesForUser) {
+ advanceConsolidationModel.initAdvancesFor(task, context, planningState);
+ reloadAdvanceGrid();
+ }
+
+ // Triggered when closable button is clicked
+ public void onClose(Event event) {
+ cancel();
+ event.stopPropagation();
+ }
+
+ public void cancel() {
+ clear();
+ advanceConsolidationModel.cancel();
+ }
+
+ private void clear() {
+ }
+
+ public void accept() {
+ advanceConsolidationModel.accept();
+ clear();
+ }
+
+ public String getInfoAdvance() {
+ String infoAdvanceAssignment = advanceConsolidationModel
+ .getInfoAdvanceAssignment();
+ if (infoAdvanceAssignment.isEmpty()) {
+ return _("Advance measurements");
+ }
+
+ return _("Advance measurements: ") + infoAdvanceAssignment;
+ }
+
+ public List