/* * This file is part of LibrePlan * * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Desenvolvemento Tecnolóxico de Galicia * Copyright (C) 2010-2012 Igalia, S.L. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.libreplan.web.orders; import org.apache.commons.lang3.StringUtils; import org.joda.time.LocalDate; import org.libreplan.business.calendars.entities.BaseCalendar; import org.libreplan.business.common.Configuration; import org.libreplan.business.common.Registry; import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.externalcompanies.entities.DeadlineCommunication; import org.libreplan.business.externalcompanies.entities.DeliverDateComparator; import org.libreplan.business.externalcompanies.entities.EndDateCommunication; import org.libreplan.business.externalcompanies.entities.ExternalCompany; import org.libreplan.business.orders.daos.IOrderDAO; import org.libreplan.business.orders.entities.Order; import org.libreplan.business.orders.entities.Order.SchedulingMode; import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.orders.entities.OrderStatusEnum; import org.libreplan.business.planner.entities.PositionConstraintType; import org.libreplan.business.resources.entities.Criterion; import org.libreplan.business.templates.entities.OrderTemplate; import org.libreplan.business.users.entities.User; import org.libreplan.business.users.entities.UserRole; import org.libreplan.web.common.ConfirmCloseUtil; import org.libreplan.web.common.FilterUtils; import org.libreplan.web.common.IMessagesForUser; import org.libreplan.web.common.Level; import org.libreplan.web.common.MessagesForUser; import org.libreplan.web.common.OnlyOneVisible; import org.libreplan.web.common.Util; import org.libreplan.web.common.Util.ReloadStrategy; import org.libreplan.web.common.components.bandboxsearch.BandboxMultipleSearch; import org.libreplan.web.common.components.bandboxsearch.BandboxSearch; import org.libreplan.web.common.components.finders.FilterPair; import org.libreplan.web.common.components.finders.OrderFilterEnum; import org.libreplan.web.common.components.finders.TaskGroupFilterEnum; import org.libreplan.web.orders.criterionrequirements.AssignedCriterionRequirementToOrderElementController; import org.libreplan.web.orders.criterionrequirements.OrderElementCriterionRequirementComponent; import org.libreplan.web.orders.files.OrderFilesController; import org.libreplan.web.orders.labels.AssignedLabelsToOrderElementController; import org.libreplan.web.orders.labels.LabelsAssignmentToOrderElementComponent; import org.libreplan.web.orders.materials.AssignedMaterialsToOrderElementController; import org.libreplan.web.orders.materials.OrderElementMaterialAssignmentsComponent; import org.libreplan.web.planner.order.IOrderPlanningGate; import org.libreplan.web.security.SecurityUtils; import org.libreplan.web.templates.IOrderTemplatesControllerEntryPoints; import org.libreplan.web.tree.TreeComponent; import org.libreplan.web.users.OrderAuthorizationController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.zkoss.ganttz.util.LongOperationFeedback; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.SelectEvent; import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.Button; import org.zkoss.zul.Column; import org.zkoss.zul.Combobox; import org.zkoss.zul.Comboitem; import org.zkoss.zul.ComboitemRenderer; import org.zkoss.zul.Constraint; import org.zkoss.zul.Datebox; import org.zkoss.zul.Grid; import org.zkoss.zul.Hbox; import org.zkoss.zul.Label; import org.zkoss.zul.Messagebox; import org.zkoss.zul.Row; import org.zkoss.zul.RowRenderer; import org.zkoss.zul.Rows; import org.zkoss.zul.SimpleListModel; import org.zkoss.zul.Tab; import org.zkoss.zul.Tabbox; import org.zkoss.zul.Tabpanel; import org.zkoss.zul.Textbox; import org.zkoss.zul.Tree; import org.zkoss.zul.Treeitem; import org.zkoss.zul.Vbox; import org.zkoss.zul.Window; import org.zkoss.zul.Listbox; import javax.annotation.Resource; import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import static org.libreplan.web.I18nHelper._; /** * Controller for CRUD actions. * <br /> * @author Óscar González Fernández <ogonzalez@igalia.com> * @author Lorenzo Tilve Álvaro <ltilve@igalia.com> * @author Manuel Rego Casasnovas <rego@igalia.com> * @author Vova Perebykivskyi <vova@libreplan-enterprise.com> */ @org.springframework.stereotype.Component @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class OrderCRUDController extends GenericForwardComposer { private static final String DEFAULT_TAB = "tabOrderElements"; private final String DELETE = "Delete"; private final String ON_CLICK_EVENT = "onClick"; private final String ICONO_CLASS = "icono"; private final String TAB_ADVANCES = "tabAdvances"; private final String INFORMATION = "Information"; @Autowired private IOrderModel orderModel; @Autowired private IOrderDAO orderDAO; @Resource private IOrderTemplatesControllerEntryPoints orderTemplates; private IMessagesForUser messagesForUser; private Component messagesContainer; private Window editWindow; private Window editOrderElementWindow; private Window listWindow; private Tab selectedTab; private Grid listing; private Hbox orderFilter; private Vbox orderElementFilter; private Button createOrderButton; private Button saveOrderAndContinueButton; private Button cancelEditionButton; private Datebox filterStartDate; private Datebox filterFinishDate; private BandboxMultipleSearch bdFilters; private BandboxSearch bdExternalCompanies; private OnlyOneVisible cachedOnlyOneVisible; private IOrderPlanningGate planningControllerEntryPoints; private BaseCalendarsComboitemRenderer baseCalendarsComboitemRenderer = new BaseCalendarsComboitemRenderer(); private OrdersRowRenderer ordersRowRenderer = new OrdersRowRenderer(); private OrderElementTreeController orderElementTreeController; private ProjectDetailsController projectDetailsController; private JiraSynchronizationController jiraSynchronizationController; private TimSynchronizationController timSynchronizationController; private AssignedLabelsToOrderElementController assignedLabelsController; private AssignedHoursToOrderElementController assignedHoursController; private ManageOrderElementAdvancesController manageOrderElementAdvancesController; private AssignedCriterionRequirementToOrderElementController assignedCriterionRequirementController; private AssignedMaterialsToOrderElementController assignedMaterialsController; private AssignedTaskQualityFormsToOrderElementController assignedTaskQualityFormController; private OrderAuthorizationController orderAuthorizationController; private OrderFilesController orderFilesController; private Grid gridAskedEndDates; private EndDatesRenderer endDatesRenderer = new EndDatesRenderer(); private Textbox filterProjectName; private Runnable onUp; private boolean readOnly = true; public void showCreateFormFromTemplate(OrderTemplate template) { showOrderElementFilter(); showCreateButtons(false); orderModel.prepareCreationFrom(template, getDesktop()); prepareEditWindow(); } @Override public void doAfterCompose(Component comp) throws Exception { super.doAfterCompose(comp); messagesForUser = new MessagesForUser(messagesContainer); comp.setAttribute("controller", this, true); // Configuration of the order filter Component filterComponent = Executions.createComponents("/orders/_orderFilter.zul", orderFilter, new HashMap<String, String>()); filterComponent.setAttribute("orderFilterController", this, true); filterStartDate = (Datebox) filterComponent.getFellow("filterStartDate"); filterFinishDate = (Datebox) filterComponent.getFellow("filterFinishDate"); bdFilters = (BandboxMultipleSearch) filterComponent.getFellow("bdFilters"); filterProjectName = (Textbox) filterComponent.getFellow("filterProjectName"); checkCreationPermissions(); setupGlobalButtons(); initializeFilter(); } private void initializeFilter() { Date startDate = FilterUtils.readProjectsStartDate(); Date endDate = FilterUtils.readProjectsEndDate(); boolean calculateStartDate = startDate == null; boolean calculateEndDate = endDate == null; // Filter predicate needs to be calculated based on the projects dates if ( (calculateStartDate) || (calculateEndDate) ) { User user = orderModel.getUser(); // Calculate filter based on user preferences if ( user != null ) { if ( (startDate == null ) && !FilterUtils.hasProjectsStartDateChanged() && (user.getProjectsFilterPeriodSince() != null) ) { startDate = new LocalDate() .minusMonths(user.getProjectsFilterPeriodSince()) .toDateTimeAtStartOfDay() .toDate(); } if ( (endDate == null ) && !FilterUtils.hasProjectsEndDateChanged() && (user.getProjectsFilterPeriodTo() != null) ) { endDate = new LocalDate() .plusMonths(user.getProjectsFilterPeriodTo()) .toDateTimeAtStartOfDay() .toDate(); } } } filterStartDate.setValue(startDate); filterFinishDate.setValue(endDate); filterProjectName.setValue(FilterUtils.readProjectsName()); loadLabels(); FilterUtils.writeProjectPlanningFilterChanged(false); createDeleteAllProjectsButton(); } /** * This method is needed to create "Delete all projects" button, * that is visible only for developers on orders list page. */ private void createDeleteAllProjectsButton() { if (!isDeleteAllProjectsButtonDisabled()) { Button deleteAllProjectButton = new Button(); deleteAllProjectButton.setLabel("Delete all projects"); deleteAllProjectButton.setDisabled(isDeleteAllProjectsButtonDisabled()); deleteAllProjectButton.addEventListener(Events.ON_CLICK, event -> deleteAllProjects()); orderFilter.appendChild(deleteAllProjectButton); } } private void loadLabels() { List<FilterPair> sessionFilters = FilterUtils.readProjectsParameters(); // Allow labels when list is empty if ( sessionFilters != null ) { bdFilters.addSelectedElements(toOrderFilterEnum(sessionFilters)); return; } User user = orderModel.getUser(); // Calculate filter based on user preferences if ( (user != null) && (user.getProjectsFilterLabel() != null) ) { bdFilters.addSelectedElement(new FilterPair( OrderFilterEnum.Label, user.getProjectsFilterLabel().getFinderPattern(), user.getProjectsFilterLabel())); } } private List<FilterPair> toOrderFilterEnum(List<FilterPair> filterPairs) { List<FilterPair> result = new ArrayList<>(); for (FilterPair filterPair : filterPairs) { TaskGroupFilterEnum type = (TaskGroupFilterEnum) filterPair.getType(); switch (type) { case Label: result.add(new FilterPair(OrderFilterEnum.Label, filterPair.getPattern(), filterPair.getValue())); break; case Criterion: result.add(new FilterPair( OrderFilterEnum.Criterion, filterPair.getPattern(), filterPair.getValue())); break; case ExternalCompany: result.add(new FilterPair( OrderFilterEnum.ExternalCompany, filterPair.getPattern(), filterPair.getValue())); break; case State: result.add(new FilterPair(OrderFilterEnum.State, filterPair.getPattern(), filterPair.getValue())); break; default: break; } } return result; } private void setupGlobalButtons() { saveOrderAndContinueButton.addEventListener(Events.ON_CLICK, event -> saveAndContinue()); cancelEditionButton.addEventListener(Events.ON_CLICK, event -> Messagebox.show( _("Unsaved changes will be lost. Are you sure?"), _("Confirm exit dialog"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION, evt -> { if ( "onOK".equals(evt.getName()) ) { ConfirmCloseUtil.resetConfirmClose(); Executions.sendRedirect("/planner/index.zul;company_scheduling"); } })); } private void initEditOrderElementWindow() { final Component parent = listWindow.getParent(); Map<String, Object> editOrderElementArgs = new HashMap<>(); editOrderElementArgs.put("top_id", "editOrderElement"); editOrderElementWindow = (Window) Executions.createComponents("/orders/_editOrderElement.zul", parent, editOrderElementArgs); Util.createBindingsFor(editOrderElementWindow); Util.reloadBindings(editOrderElementWindow); } private void addEditWindowIfNecessary() { if ( editWindow != null ) { return; } listWindow.setVisible(false); cachedOnlyOneVisible = null; Map<String, Object> editWindowArgs = new HashMap<>(); editWindowArgs.put("top_id", "editWindow"); Component parent = listWindow.getParent(); editWindow = (Window) Executions.createComponents("/orders/_edition.zul", parent, editWindowArgs); Util.createBindingsFor(editWindow); Util.reloadBindings(editWindow); } private class OrderDatesHandler { private final Combobox schedulingMode; private final Datebox initDate; private final Datebox deadline; public OrderDatesHandler(Window editWindow) { schedulingMode = Util.findComponentAt(editWindow, "schedulingMode"); initDate = Util.findComponentAt(editWindow, "initDate"); deadline = Util.findComponentAt(editWindow, "deadline"); initializeSchedulingModeCombobox(); } private void initializeSchedulingModeCombobox() { fillSchedulingModes(); listenToChangeOfMode(); } private void fillSchedulingModes() { List options = schedulingMode.getChildren(); if ( options != null && options.isEmpty() ) { schedulingMode.appendChild(createCombo( SchedulingMode.FORWARD, _("Forward"), _("Schedule from start to deadline"))); schedulingMode.appendChild(createCombo( SchedulingMode.BACKWARDS, _("Backwards"), _("Schedule from deadline to start"))); } } void chooseCurrentSchedulingMode() { @SuppressWarnings("unchecked") List<Comboitem> items = schedulingMode.getItems(); SchedulingMode currentMode = getOrder().getSchedulingMode(); for (Comboitem each : items) { if ( each.getValue().equals(currentMode) ) { schedulingMode.setSelectedItem(each); setConstraintsFor(currentMode); return; } } } private void listenToChangeOfMode() { schedulingMode.addEventListener(Events.ON_SELECT, event -> { SchedulingMode chosen = schedulingMode.getSelectedItem().getValue(); if (chosen != null) { getOrder().setSchedulingMode(chosen); setConstraintsFor(chosen); changeFocusAccordingTo(chosen); } }); } private Comboitem createCombo(SchedulingMode value, String label, String description) { Comboitem result = new Comboitem(); result.setValue(value); result.setLabel(label); result.setDescription(description); return result; } private void setConstraintsFor(final SchedulingMode mode) { initDate.setConstraint((comp, value) -> { if (value == null) { if (mode == SchedulingMode.FORWARD) { throw new WrongValueException(comp, _("Starting date cannot be empty in forward mode")); } if ( orderModel.isAnyTaskWithConstraint(PositionConstraintType.AS_SOON_AS_POSSIBLE) ) { throw new WrongValueException( comp, _("Starting date cannot be empty because there is a task with constraint " + "\"as soon as possible\"")); } } }); deadline.setConstraint((comp, value) -> { if (value == null) { if (mode == SchedulingMode.BACKWARDS) { throw new WrongValueException(comp, _("Deadline cannot be empty in backwards mode")); } if (orderModel.isAnyTaskWithConstraint(PositionConstraintType.AS_LATE_AS_POSSIBLE)) { throw new WrongValueException( comp, _("Deadline cannot be empty because there is a task with constraint " + "\"as late as possible\"")); } } }); } private void changeFocusAccordingTo(SchedulingMode chosen) { initDate.setFocus(SchedulingMode.FORWARD == chosen); deadline.setFocus(SchedulingMode.BACKWARDS == chosen); } public Constraint getCheckConstraintFinishDate() { return (comp, value) -> { Date finishDate = (Date) value; if ( (finishDate != null) && (initDate.getValue() != null) && (finishDate.compareTo(initDate.getValue()) < 0) ) { deadline.setValue(null); getOrder().setDeadline(null); throw new WrongValueException(comp, _("must be after start date")); } }; } public Constraint checkConstraintStartDate() { return (comp, value) -> { Date startDate = (Date) value; if ( (startDate != null) && (deadline.getValue() != null) && (startDate.compareTo(deadline.getValue()) > 0) ) { initDate.setValue(null); getOrder().setInitDate(null); throw new WrongValueException(comp, _("must be lower than end date")); } }; } } private void bindListOrderStatusSelectToOnStatusChange() { Listbox listOrderStatus = (Listbox) editWindow.getFellow("listOrderStatus"); listOrderStatus.addEventListener(Events.ON_SELECT, event -> updateDisabilitiesOnInterface()); } public void setupOrderElementTreeController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); if ( orderElementTreeController == null ) { // Create order element edit window OrderElementController orderElementController = new OrderElementController(); if ( editOrderElementWindow == null ) { initEditOrderElementWindow(); } try { orderElementController.doAfterCompose(self.getFellow("editOrderElement")); } catch (Exception e) { throw new RuntimeException(e); } // Prepare tree, attach edit window to tree orderElementTreeController = new OrderElementTreeController(orderModel, orderElementController, messagesForUser); TreeComponent orderElementsTree = (TreeComponent) editWindow.getFellow("orderElementTree"); orderElementTreeController.setTreeComponent(orderElementsTree); orderElementsTree.useController(orderElementTreeController); orderElementTreeController.setReadOnly(readOnly); Tree tree = (Tree) orderElementsTree.getFellowIfAny("tree"); tree.setModel(null); tree.setItemRenderer(orderElementTreeController.getRenderer()); reloadTree(orderElementsTree); } } private void reloadTree(TreeComponent orderElementsTree) { final Tree tree = (Tree) orderElementsTree.getFellowIfAny("tree"); tree.setModel(orderElementTreeController.getFilteredTreeModel()); tree.addEventListener(Events.ON_SELECT, event -> tree.clearSelection()); } /** * Operations to do before to change the selected tab. */ private boolean confirmLastTab() { if ( getCurrentTab() != null ) { // Confirm advances tab if ( TAB_ADVANCES.equals(getCurrentTab().getId()) ) { if ( manageOrderElementAdvancesController != null && !manageOrderElementAdvancesController.save() ) { resetSelectedTab(); selectTab(TAB_ADVANCES); return false; } } } return true; } private IOrderElementModel getOrderElementModel() { return orderModel.getOrderElementModel(orderModel.getOrder()); } public void setupAssignedHoursToOrderElementController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); Component orderElementHours = editWindow.getFellowIfAny("orderElementHours"); if (assignedHoursController == null) { assignedHoursController = (AssignedHoursToOrderElementController) orderElementHours.getAttribute("assignedHoursToOrderElementController", true); final IOrderElementModel orderElementModel = getOrderElementModel(); assignedHoursController.openWindow(orderElementModel); } else { Util.createBindingsFor(orderElementHours); Util.reloadBindings(orderElementHours); assignedHoursController.paintProgressBars(); } } public void setupManageOrderElementAdvancesController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); Component orderElementAdvances = editWindow.getFellowIfAny("orderElementAdvances"); if ( manageOrderElementAdvancesController == null ) { final IOrderElementModel orderElementModel = getOrderElementModel(); manageOrderElementAdvancesController = (ManageOrderElementAdvancesController) orderElementAdvances.getAttribute("manageOrderElementAdvancesController", true); manageOrderElementAdvancesController.openWindow(orderElementModel); } else { manageOrderElementAdvancesController.refreshChangesFromOrderElement(); manageOrderElementAdvancesController.createAndLoadBindings(); manageOrderElementAdvancesController.refreshSelectedAdvance(); } } public void setupAssignedLabelsToOrderElementController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); if ( assignedLabelsController == null ) { LabelsAssignmentToOrderElementComponent labelsAssignment = (LabelsAssignmentToOrderElementComponent) editWindow.getFellow("orderElementLabels"); assignedLabelsController = labelsAssignment.getController(); final IOrderElementModel orderElementModel = getOrderElementModel(); assignedLabelsController.openWindow(orderElementModel); } } public void setupAssignedCriterionRequirementsToOrderElementController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); if ( assignedCriterionRequirementController == null ) { Component orderElementCriterionRequirements = editWindow.getFellowIfAny("orderElementCriterionRequirements"); assignedCriterionRequirementController = ((OrderElementCriterionRequirementComponent) orderElementCriterionRequirements).getController(); final IOrderElementModel orderElementModel = getOrderElementModel(); assignedCriterionRequirementController.openWindow(orderElementModel); } else { reloadHoursGroupOrder(); } } public void setupAssignedMaterialsToOrderElementController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); if ( assignedMaterialsController == null ) { OrderElementMaterialAssignmentsComponent assignmentsComponent = (OrderElementMaterialAssignmentsComponent) editWindow.getFellowIfAny("orderElementMaterials"); assignedMaterialsController = assignmentsComponent.getController(); final IOrderElementModel orderElementModel = getOrderElementModel(); assignedMaterialsController.openWindow(orderElementModel.getOrderElement()); } } public void setupAssignedTaskQualityFormsToOrderElementController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); Component orderElementTaskQualityForms = editWindow.getFellowIfAny("orderElementTaskQualityForms"); if ( assignedTaskQualityFormController == null ) { assignedTaskQualityFormController = (AssignedTaskQualityFormsToOrderElementController) orderElementTaskQualityForms.getAttribute("assignedTaskQualityFormsController", true); final IOrderElementModel orderElementModel = getOrderElementModel(); assignedTaskQualityFormController.openWindow(orderElementModel); } else { Util.createBindingsFor(orderElementTaskQualityForms); Util.reloadBindings(orderElementTaskQualityForms); } } public void setupOrderFilesController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); Component orderFiles = editWindow.getFellowIfAny("orderElementFiles"); if ( orderFilesController == null ){ orderFilesController = (OrderFilesController) orderFiles.getAttribute("orderFilesController", true); final IOrderElementModel orderElementModel = getOrderElementModel(); orderFilesController.openWindow(orderElementModel); } } public void setupOrderAuthorizationController() { if ( !confirmLastTab() ) { return; } setCurrentTab(); Component orderElementAuthorizations = editWindow.getFellowIfAny("orderElementAuthorizations"); if (orderAuthorizationController == null) { orderAuthorizationController = (OrderAuthorizationController) orderElementAuthorizations.getAttribute("orderAuthorizationController", true); orderAuthorizationController.setMessagesForUserComponent(messagesForUser); initOrderAuthorizations(); } else { Util.createBindingsFor(orderElementAuthorizations); Util.reloadBindings(orderElementAuthorizations); } } private void initOrderAuthorizations() { Component orderElementAuthorizations = editWindow.getFellowIfAny("orderElementAuthorizations"); final Order order = orderModel.getOrder(); if ( order.isNewObject() ) { orderAuthorizationController.initCreate(orderModel.getPlanningState()); } else { orderAuthorizationController.initEdit(orderModel.getPlanningState()); } Util.createBindingsFor(orderElementAuthorizations); Util.reloadBindings(orderElementAuthorizations); } public List<Order> getOrders() { return getOrdersFiltered(); } private List<Order> getOrdersFiltered() { List<org.libreplan.business.labels.entities.Label> labels = new ArrayList<>(); List<Criterion> criteria = new ArrayList<>(); ExternalCompany customer = null; OrderStatusEnum state = null; for (FilterPair filterPair : (List<FilterPair>) bdFilters.getSelectedElements()) { OrderFilterEnum type = (OrderFilterEnum) filterPair.getType(); switch (type) { case Label: labels.add((org.libreplan.business.labels.entities.Label) filterPair.getValue()); break; case Criterion: criteria.add((Criterion) filterPair.getValue()); break; case ExternalCompany: if ( customer != null ) { // It's impossible to have an Order associated to more than 1 customer return Collections.emptyList(); } customer = (ExternalCompany) filterPair.getValue(); break; case State: if ( state != null ) { // It's impossible to have an Order associated with more than 1 state return Collections.emptyList(); } state = (OrderStatusEnum) filterPair.getValue(); break; default: break; } } return orderModel.getOrders( filterStartDate.getValue(), filterFinishDate.getValue(), labels, criteria, customer, state); } private OnlyOneVisible getVisibility() { if (cachedOnlyOneVisible == null) { cachedOnlyOneVisible = new OnlyOneVisible(listWindow); } return cachedOnlyOneVisible; } public Order getOrder() { return orderModel.getOrder(); } public void saveAndContinue() { saveAndContinue(true); } protected void saveAndContinue(boolean showSaveMessage) { Order order = orderModel.getOrder(); final boolean isNewObject = order.isNewObject(); setCurrentTab(); Tab previousTab = getCurrentTab(); save(showSaveMessage); if ( orderModel.userCanRead(order, SecurityUtils.getSessionUserLoginName()) ) { refreshOrderWindow(); // Come back to the current tab after initialize all tabs resetSelectedTab(); selectTab(previousTab.getId()); Events.sendEvent(new SelectEvent<>(Events.ON_SELECT, previousTab, null)); if ( isNewObject ) { this.planningControllerEntryPoints.goToOrderDetails(order); } } else { Messagebox.show( _("You don't have read access to this project"), _(INFORMATION), Messagebox.OK, Messagebox.INFORMATION); goToList(); } } private void refreshOrderWindow() { if ( orderElementTreeController != null ) { orderElementTreeController.resetCellsMarkedAsModified(); } updateDisabilitiesOnInterface(); refreshCodeTextboxesOnly(); getVisibility().showOnly(editWindow); } private void refreshCodeTextboxesOnly() { if ( orderElementTreeController != null ) { Map<OrderElement, Textbox> orderElementCodeTextBoxes = orderElementTreeController.getOrderElementCodeTextboxes(); for (OrderElement element : orderElementCodeTextBoxes.keySet()) { if ( element.getId() != null ) { orderElementCodeTextBoxes.get(element).setValue(element.getCode()); } } } } private void save(boolean showSaveMessage) { if ( manageOrderElementAdvancesController != null ) { selectTab(TAB_ADVANCES); if ( !manageOrderElementAdvancesController.save() ) { setCurrentTab(); return; } } if ( assignedCriterionRequirementController != null ) { selectTab("tabRequirements"); if ( !assignedCriterionRequirementController.close() ) { setCurrentTab(); return; } } if ( assignedTaskQualityFormController != null ) { selectTab("tabTaskQualityForm"); if (!assignedTaskQualityFormController.confirm()) { setCurrentTab(); return; } } // Come back to the default tab if ( getCurrentTab() != null ) { selectTab(getCurrentTab().getId()); } orderModel.save(showSaveMessage); } private void selectDefaultTab() { selectTab(DEFAULT_TAB); } private void resetSelectedTab() { selectedTab = null; } private void setCurrentTab() { Tabbox tabboxOrder = (Tabbox) editWindow.getFellowIfAny("tabboxOrder"); if ( tabboxOrder != null ) { selectedTab = tabboxOrder.getSelectedTab(); } } Tab getCurrentTab() { return selectedTab; } void selectTab(String str) { Tab tab = (Tab) editWindow.getFellowIfAny(str); if ( tab != null ) { tab.setSelected(true); } } public void goToList() { loadComponents(); showWindow(listWindow); } private void loadComponents() { // Load the components of the order list listing = (Grid) listWindow.getFellow("listing"); showOrderFilter(); showCreateButtons(true); } private void showWindow(Window window) { getVisibility().showOnly(window); Util.reloadBindings(ReloadStrategy.ONE_PER_REQUEST, window); } public void reloadHoursGroupOrder() { if ("tabRequirements".equals(getCurrentTab().getId())) { assignedCriterionRequirementController.reload(); } } public void cancel() { goToList(); } public void up() { if ( onUp == null ) { throw new IllegalStateException("in order to call up onUp action should have been set"); } onUp.run(); } public void confirmRemove(Order order) { if ( orderModel.userCanWrite(order) ) { int status = Messagebox.show( _("Confirm deleting {0}. Are you sure?", order.getName()), DELETE, Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION); if ( Messagebox.OK == status ) { remove(order); } } else { Messagebox.show( _("Not enough permissions to edit this project"), _(INFORMATION), Messagebox.OK, Messagebox.INFORMATION); } } private void remove(Order order) { boolean hasImputedExpenseSheets = orderModel.hasImputedExpenseSheetsThisOrAnyOfItsChildren(order); if ( hasImputedExpenseSheets ) { messagesForUser.showMessage( Level.ERROR, _("You can not remove the project \"{0}\" because this one has imputed expense sheets.", order.getName())); return; } boolean alreadyInUse = orderModel.isAlreadyInUseAndIsOnlyInCurrentScenario(order); if ( alreadyInUse ) { messagesForUser.showMessage( Level.ERROR, _("You can not remove the project \"{0}\" because it has time tracked at some of its tasks", order.getName())); } else { if ( !StringUtils.isBlank(order.getExternalCode()) ) { if ( Messagebox.show( _("This project is a subcontracted project. If you delete it, " + "you won't be able to report progress anymore. Are you sure?"), _("Confirm"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.CANCEL ) { return; } } orderModel.remove(order); Util.reloadBindings(self); messagesForUser.clearMessages(); messagesForUser.showMessage(Level.INFO, _("Removed {0}", order.getName())); } } public void schedule(Order order) { orderModel.useSchedulingDataForCurrentScenario(order); if ( orderModel.userCanRead(order, SecurityUtils.getSessionUserLoginName()) ) { if ( order.isScheduled() ) { planningControllerEntryPoints.goToScheduleOf(order); showCreateButtons(false); } else { Messagebox.show( _("The project has no scheduled elements"), _(INFORMATION), Messagebox.OK, Messagebox.INFORMATION); } } else { Messagebox.show( _("You don't have read access to this project"), _(INFORMATION), Messagebox.OK, Messagebox.INFORMATION); } } private void createTemplate(Order order) { orderTemplates.goToCreateTemplateFrom(order); } public void createFromTemplate(OrderTemplate template) { orderModel.prepareCreationFrom(template, getDesktop()); } public void goToEditForm(Order order) { showOrderElementFilter(); showCreateButtons(false); planningControllerEntryPoints.goToOrderDetails(order); } public void initEdit(Order order) { checkUserCanRead(order); orderModel.initEdit(order, getDesktop()); prepareEditWindow(); } public void checkUserCanRead(Order order) { if ( !orderModel.userCanRead(order, SecurityUtils.getSessionUserLoginName()) ) { Messagebox.show( _("Sorry, you do not have permissions to access this project"), _(INFORMATION), Messagebox.OK, Messagebox.INFORMATION); } } public IOrderModel getOrderModel() { return orderModel; } private Desktop getDesktop() { return listWindow.getDesktop(); } private void resetTabControllers() { orderElementTreeController = null; assignedHoursController = null; manageOrderElementAdvancesController = null; assignedLabelsController = null; assignedCriterionRequirementController = null; assignedMaterialsController = null; assignedTaskQualityFormController = null; orderAuthorizationController = null; } private void prepareEditWindow() { resetTabControllers(); addEditWindowIfNecessary(); updateDisabilitiesOnInterface(); setupOrderElementTreeController(); selectDefaultTab(); } private void initializeCustomerComponent() { bdExternalCompanies = (BandboxSearch) editWindow.getFellow("bdExternalCompanies"); bdExternalCompanies.setListboxEventListener(Events.ON_SELECT, event -> { final Object object = bdExternalCompanies.getSelectedElement(); orderModel.setExternalCompany((ExternalCompany) object); }); bdExternalCompanies.setListboxEventListener(Events.ON_OK, event -> { final Object object = bdExternalCompanies.getSelectedElement(); orderModel.setExternalCompany((ExternalCompany) object); bdExternalCompanies.close(); }); gridAskedEndDates = (Grid) editWindow.getFellow("gridAskedEndDates"); } public void setupOrderDetails() { if ( !confirmLastTab() ) { return; } setCurrentTab(); OrderDatesHandler orderDatesHandler = new OrderDatesHandler(editWindow); bindListOrderStatusSelectToOnStatusChange(); initializeCustomerComponent(); reloadOrderDetailsTab(); orderDatesHandler.chooseCurrentSchedulingMode(); setupJiraSynchronizationController(); setupTimSynchronizationController(); } private void reloadOrderDetailsTab() { Tabpanel tabPanel = (Tabpanel) editWindow.getFellow("tabPanelGeneralData"); Util.createBindingsFor(tabPanel); Util.reloadBindings(tabPanel); } public void goToCreateForm() { prepareForCreate(getDesktop()); getCreationPopup().showWindow(this, null); } public void prepareForCreate(Desktop desktop) { orderModel.prepareForCreate(desktop); } void editNewCreatedOrder(Window detailsWindow) { showOrderElementFilter(); hideCreateButtons(); prepareEditWindow(); detailsWindow.setVisible(false); setupOrderAuthorizationController(); detailsWindow.getAttributes(); } public ProjectDetailsController getCreationPopup() { if ( projectDetailsController == null ) { projectDetailsController = new ProjectDetailsController(); } return projectDetailsController; } private void hideCreateButtons() { showCreateButtons(false); } public void setPlanningControllerEntryPoints(IOrderPlanningGate planningControllerEntryPoints) { this.planningControllerEntryPoints = planningControllerEntryPoints; } public IOrderPlanningGate getPlanningControllerEntryPoints() { return this.planningControllerEntryPoints; } public void setActionOnUp(Runnable onUp) { this.onUp = onUp; } public List<BaseCalendar> getBaseCalendars() { return orderModel.getBaseCalendars(); } public BaseCalendarsComboitemRenderer getBaseCalendarsComboitemRenderer() { return baseCalendarsComboitemRenderer; } private class BaseCalendarsComboitemRenderer implements ComboitemRenderer { @Override public void render(Comboitem comboitem, Object o, int i) throws Exception { BaseCalendar calendar = (BaseCalendar) o; comboitem.setLabel(calendar.getName()); comboitem.setValue(calendar); BaseCalendar current = orderModel.getCalendar(); if ( (current != null) && calendar.getId().equals(current.getId()) ) { Combobox combobox = (Combobox) comboitem.getParent(); combobox.setSelectedItem(comboitem); } } } public void setBaseCalendar(BaseCalendar calendar) { orderModel.setCalendar(calendar); } public boolean isCodeAutogenerated() { return orderModel.isCodeAutogenerated(); } public void setCodeAutogenerated(boolean codeAutogenerated) { try { orderModel.setCodeAutogenerated(codeAutogenerated); if ( orderElementTreeController != null ) { orderElementTreeController.disabledCodeBoxes(codeAutogenerated); } } catch (ConcurrentModificationException e) { messagesForUser.showMessage(Level.ERROR, e.getMessage()); } Util.reloadBindings(editWindow); } public void setCodeAutogeneratedInModel(boolean codeAutogenerated) { orderModel.setCodeAutogenerated(codeAutogenerated); } public OrderStatusEnum[] getOrderStatus() { return OrderStatusEnum.values(); } public List<ExternalCompany> getExternalCompaniesAreClient() { return orderModel.getExternalCompaniesAreClient(); } public OrdersRowRenderer getOrdersRowRender() { return ordersRowRenderer; } public class OrdersRowRenderer implements RowRenderer { @Override public void render(Row row, Object o, int i) throws Exception { final Order order = (Order) o; row.setValue(order); appendLabel(row, order.getName()); appendLabel(row, order.getCode()); appendDate(row, order.getInitDate()); appendDate(row, order.getDeadline()); appendCustomer(row, order.getCustomer()); appendObject(row, Util.addCurrencySymbol(order.getTotalManualBudget())); appendObject(row, order.getTotalHours()); appendObject(row, _(order.getState().toString())); appendOperations(row, order); row.setTooltiptext(getTooltipText(order)); row.addEventListener(ON_CLICK_EVENT, event -> goToEditForm(order)); } private void appendObject(final Row row, Serializable object) { String text = ""; if ( object != null ) { text = object.toString(); } appendLabel(row, text); } private void appendCustomer(final Row row, ExternalCompany externalCompany) { String customerName = ""; if ( externalCompany != null ) { customerName = externalCompany.getName(); } appendLabel(row, customerName); } private void appendDate(final Row row, Date date) { String labelDate = ""; if ( date != null ) { labelDate = Util.formatDate(date); } appendLabel(row, labelDate); } private void appendOperations(final Row row,final Order order){ Hbox hbox = new Hbox(); appendButtonEdit(hbox,order); appendButtonDelete(hbox, order); appendButtonPlan(hbox, order); appendButtonDerived(hbox, order); row.appendChild(hbox); } private void appendLabel(final Row row, String value) { Label label = new Label(value); row.appendChild(label); } private void appendButtonEdit(final Hbox hbox, final Order order) { Button buttonEdit = new Button(); buttonEdit.setSclass(ICONO_CLASS); buttonEdit.setImage("/common/img/ico_editar1.png"); buttonEdit.setHoverImage("/common/img/ico_editar.png"); buttonEdit.setTooltiptext(_("Edit")); buttonEdit.addEventListener(ON_CLICK_EVENT, event -> goToEditForm(order)); hbox.appendChild(buttonEdit); } private void appendButtonDelete(final Hbox hbox, final Order order) { if ( orderModel.userCanWrite(order) ) { Button buttonDelete = new Button(); buttonDelete.setSclass(ICONO_CLASS); buttonDelete.setImage("/common/img/ico_borrar1.png"); buttonDelete.setHoverImage("/common/img/ico_borrar.png"); buttonDelete.setTooltiptext(_(DELETE)); buttonDelete.addEventListener(ON_CLICK_EVENT, event -> confirmRemove(order)); hbox.appendChild(buttonDelete); } } private void appendButtonPlan(final Hbox hbox, final Order order) { Button buttonPlan = new Button(); buttonPlan.setSclass(ICONO_CLASS); buttonPlan.setImage("/common/img/ico_planificador1.png"); buttonPlan.setHoverImage("/common/img/ico_planificador.png"); buttonPlan.setTooltiptext(_("See scheduling")); buttonPlan.addEventListener(ON_CLICK_EVENT, event -> schedule(order)); hbox.appendChild(buttonPlan); } private void appendButtonDerived(final Hbox hbox, final Order order) { Button buttonDerived = new Button(); buttonDerived.setSclass(ICONO_CLASS); buttonDerived.setImage("/common/img/ico_derived1.png"); buttonDerived.setHoverImage("/common/img/ico_derived.png"); buttonDerived.setTooltiptext(_("Create Template")); buttonDerived.addEventListener(ON_CLICK_EVENT, event -> createTemplate(order)); if ( !SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_TEMPLATES) ) { buttonDerived.setDisabled(true); buttonDerived.setTooltiptext(_("Not enough permissions to create templates")); } hbox.appendChild(buttonDerived); } } public String getTooltipText(final Order order) { return orderModel.gettooltipText(order); } public void reloadTotalBudget(Label labelTotalBudget) { Util.reloadBindings(labelTotalBudget); } /** * Operations to filter the orders by multiple filters. */ public Constraint checkConstraintFinishDate() { return (comp, value) -> { Date finishDate = (Date) value; if ( (finishDate != null) && (filterStartDate.getRawValue() != null) && (finishDate.compareTo((Date) filterStartDate.getRawValue()) < 0) ) { throw new WrongValueException(comp, _("must be after start date")); } }; } public Constraint checkConstraintStartDate() { return (comp, value) -> { Date startDate = (Date) value; if ( (startDate != null) && (filterFinishDate.getRawValue() != null) && (startDate.compareTo((Date) filterFinishDate.getRawValue()) > 0) ) { throw new WrongValueException(comp, _("must be lower than end date")); } }; } public void onApplyFilter() { OrderPredicate predicate = createPredicate(); storeSessionVariables(); FilterUtils.writeProjectFilterChanged(true); if ( predicate != null ) { // Force reload conversation state in oderModel getOrders(); filterByPredicate(predicate); } else { showAllOrders(); } } private void storeSessionVariables() { FilterUtils.writeProjectsFilter( filterStartDate.getValue(), filterFinishDate.getValue(), getSelectedBandboxAsTaskGroupFilters(), filterProjectName.getValue()); } private List<FilterPair> getSelectedBandboxAsTaskGroupFilters() { List<FilterPair> result = new ArrayList<>(); for (FilterPair filterPair : (List<FilterPair>) bdFilters.getSelectedElements()) { OrderFilterEnum type = (OrderFilterEnum) filterPair.getType(); switch (type) { case Label: result.add(new FilterPair( TaskGroupFilterEnum.Label, filterPair.getPattern(), filterPair.getValue())); break; case Criterion: result.add(new FilterPair( TaskGroupFilterEnum.Criterion, filterPair.getPattern(), filterPair.getValue())); break; case ExternalCompany: result.add(new FilterPair( TaskGroupFilterEnum.ExternalCompany, filterPair.getPattern(), filterPair.getValue())); break; case State: result.add(new FilterPair( TaskGroupFilterEnum.State, filterPair.getPattern(), filterPair.getValue())); break; default: result.add(new FilterPair( OrderFilterEnum.Label, filterPair.getPattern(), filterPair.getValue())); break; } } return result; } private OrderPredicate createPredicate() { List<FilterPair> listFilters = (List<FilterPair>) bdFilters.getSelectedElements(); Date startDate = filterStartDate.getValue(); Date finishDate = filterFinishDate.getValue(); String name = filterProjectName.getValue(); return listFilters.isEmpty() && startDate == null && finishDate == null && name == null ? null : new OrderPredicate(listFilters, startDate, finishDate, name); } private void filterByPredicate(OrderPredicate predicate) { List<Order> filterOrders = orderModel.getFilterOrders(predicate); listing.setModel(new SimpleListModel<>(filterOrders.toArray())); listing.invalidate(); } private void showAllOrders() { listing.setModel(new SimpleListModel<>(getOrders().toArray())); listing.invalidate(); } private void showOrderFilter() { orderFilter.setVisible(true); orderElementFilter.setVisible(false); } public void showOrderElementFilter() { if ( orderFilter != null ) { orderFilter.setVisible(false); } if ( orderElementFilter != null ) { orderElementFilter.setVisible(true); } } public void showCreateButtons(boolean showCreate) { if ( !showCreate ) { Hbox perspectiveButtonsInsertionPoint = (Hbox) page.getFellow("perspectiveButtonsInsertionPoint"); perspectiveButtonsInsertionPoint.getChildren().clear(); saveOrderAndContinueButton.setParent(perspectiveButtonsInsertionPoint); cancelEditionButton.setParent(perspectiveButtonsInsertionPoint); } if ( createOrderButton != null ) { createOrderButton.setVisible(showCreate); } if ( saveOrderAndContinueButton != null ) { saveOrderAndContinueButton.setVisible(!showCreate); } if ( cancelEditionButton != null ) { cancelEditionButton.setVisible(!showCreate); } } public void highLight(final OrderElement orderElement) { final Tab tab = (Tab) editWindow.getFellowIfAny("tabOrderElements"); LongOperationFeedback.executeLater(tab, () -> { if ( tab != null ) { tab.setSelected(true); Events.sendEvent(new SelectEvent<>(Events.ON_SELECT, tab, null)); } if ( !(orderElement instanceof Order) && orderElementTreeController != null ) { final Treeitem item = orderElementTreeController.getTreeitemByOrderElement(orderElement); if ( item != null) { orderElementTreeController.showEditionOrderElement(item); } } }); } /** * Checks the creation permissions of the current user and enables/disables the create buttons accordingly. */ private void checkCreationPermissions() { if ( !SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_CREATE_PROJECTS) && createOrderButton != null ) { createOrderButton.setDisabled(true); } } private void updateDisabilitiesOnInterface() { Order order = orderModel.getOrder(); boolean permissionForWriting = orderModel.userCanWrite(order); boolean isInStoredState = order.getState() == OrderStatusEnum.STORED; boolean isInitiallyStored = orderModel.getPlanningState().getSavedOrderState() == OrderStatusEnum.STORED; readOnly = !permissionForWriting || isInStoredState; if ( orderElementTreeController != null ) { orderElementTreeController.setReadOnly(readOnly); } saveOrderAndContinueButton.setDisabled(!permissionForWriting || (isInitiallyStored && isInStoredState)); } public void sortOrders() { Column columnDateStart = (Column) listWindow.getFellow("columnDateStart"); if (columnDateStart != null) { if ( "ascending".equals(columnDateStart.getSortDirection()) ) { columnDateStart.sort(false, false); columnDateStart.setSortDirection("ascending"); } else if ( "descending".equals(columnDateStart.getSortDirection()) ) { columnDateStart.sort(true, false); columnDateStart.setSortDirection("descending"); } } } public SortedSet<DeadlineCommunication> getDeliverDates() { return getOrder() != null ? getOrder().getDeliveringDates() : new TreeSet<>(new DeliverDateComparator()); } public Constraint checkValidProjectName() { return (comp, value) -> { if ( StringUtils.isBlank((String) value) ) { throw new WrongValueException(comp, _("cannot be empty")); } try { Order found = orderDAO.findByNameAnotherTransaction((String) value); if ( !found.getId().equals(getOrder().getId()) ) { throw new WrongValueException(comp, _("project name already being used")); } } catch (InstanceNotFoundException ignored) {} }; } public Constraint checkValidProjectCode() { return (comp, value) -> { if ( StringUtils.isBlank((String) value) ) { throw new WrongValueException(comp, _("cannot be empty")); } try { Order found = orderDAO.findByCodeAnotherTransaction((String) value); if ( !found.getId().equals(getOrder().getId()) ) { throw new WrongValueException(comp, _("project code already being used")); } } catch (InstanceNotFoundException ignored) {} }; } public boolean isSubcontractedProject() { return (getOrder() != null) && (getOrder().getExternalCode() != null); } public String getProjectType() { return isSubcontractedProject() ? _("Subcontracted by client") : _("Regular project"); } public void setCurrentDeliveryDate(Grid listDeliveryDates) { if ( getOrder() != null && getOrder().getDeliveringDates() != null && !getOrder().getDeliveringDates().isEmpty() ) { DeadlineCommunication lastDeliveryDate = getOrder().getDeliveringDates().first(); if ( listDeliveryDates != null ) { listDeliveryDates.renderAll(); final Rows rows = listDeliveryDates.getRows(); for (Component component : rows.getChildren()) { final Row row = (Row) component; final DeadlineCommunication deliveryDate = row.getValue(); if (deliveryDate.equals(lastDeliveryDate)) { row.setSclass("current-delivery-date"); return; } } } } } public SortedSet<EndDateCommunication> getEndDates() { return orderModel.getEndDates(); } public void addAskedEndDate(Datebox newEndDate) { if ( newEndDate == null || newEndDate.getValue() == null ) { messagesForUser.showMessage(Level.ERROR, _("You must select a valid date. ")); return; } if ( thereIsSomeCommunicationDateEmpty() ) { messagesForUser.showMessage( Level.ERROR, _("It will only be possible to add an end date if all the exiting ones in the table " + "have already been sent to the customer.")); return; } if ( orderModel.alreadyExistsRepeatedEndDate(newEndDate.getValue()) ) { messagesForUser.showMessage(Level.ERROR, _("It already exists a end date with the same date. ")); return; } orderModel.addAskedEndDate(newEndDate.getValue()); reloadGridAskedEndDates(); } private void reloadGridAskedEndDates() { Util.reloadBindings(gridAskedEndDates); } private boolean thereIsSomeCommunicationDateEmpty() { for (EndDateCommunication endDate : orderModel.getEndDates()) { if ( endDate.getCommunicationDate() == null ) { return true; } } return false; } public EndDatesRenderer getEndDatesRenderer() { return this.endDatesRenderer; } private class EndDatesRenderer implements RowRenderer { @Override public void render(Row row, Object o, int i) throws Exception { EndDateCommunication endDate = (EndDateCommunication) o; row.setValue(endDate); appendLabel(row, Util.formatDateTime(endDate.getSaveDate())); appendLabel(row, Util.formatDate(endDate.getEndDate())); appendLabel(row, Util.formatDateTime(endDate.getCommunicationDate())); appendOperations(row, endDate); } private void appendLabel(Row row, String label) { row.appendChild(new Label(label)); } private void appendOperations(Row row, EndDateCommunication endDate) { Hbox hbox = new Hbox(); hbox.appendChild(getDeleteButton(endDate)); row.appendChild(hbox); } private Button getDeleteButton(final EndDateCommunication endDate) { Button deleteButton = new Button(); deleteButton.setDisabled(isNotUpdate(endDate)); deleteButton.setSclass(ICONO_CLASS); deleteButton.setImage("/common/img/ico_borrar1.png"); deleteButton.setHoverImage("/common/img/ico_borrar.png"); deleteButton.setTooltiptext(_(DELETE)); deleteButton.addEventListener(Events.ON_CLICK, event -> removeAskedEndDate(endDate)); return deleteButton; } private boolean isNotUpdate(final EndDateCommunication endDate) { EndDateCommunication lastAskedEndDate = getOrder().getEndDateCommunicationToCustomer().first(); return !((lastAskedEndDate != null) && (lastAskedEndDate.equals(endDate))) || (lastAskedEndDate.getCommunicationDate() != null); } } public void removeAskedEndDate(EndDateCommunication endDate) { orderModel.removeAskedEndDate(endDate); reloadGridAskedEndDates(); } public String getMoneyFormat() { return Util.getMoneyFormat(); } public String getCurrencySymbol() { return Util.getCurrencySymbol(); } public void readSessionFilterDates() { filterStartDate.setValue(FilterUtils.readProjectsStartDate()); filterFinishDate.setValue(FilterUtils.readProjectsEndDate()); filterProjectName.setValue(FilterUtils.readProjectsName()); loadLabels(); } /** * Setup the connector, JiraSynchronization controller. */ public void setupJiraSynchronizationController() { if ( jiraSynchronizationController == null ) { jiraSynchronizationController = new JiraSynchronizationController(); jiraSynchronizationController.setOrderController(this); } try { jiraSynchronizationController.doAfterCompose(editWindow); } catch (Exception e) { throw new RuntimeException(e); } } /** * Setup the connector, TimSynchronization controller. */ public void setupTimSynchronizationController() { if ( timSynchronizationController == null ) { timSynchronizationController = new TimSynchronizationController(); timSynchronizationController.setOrderController(this); } try { timSynchronizationController.doAfterCompose(editWindow); } catch (Exception e) { throw new RuntimeException(e); } } public BigDecimal getResourcesBudget() { return Registry .getTransactionService() .runOnReadOnlyTransaction(() -> getOrderElementModel().getOrderElement().getResourcesBudget()); } public BigDecimal getTotalBudget() { return getOrder().getBudget().add(getResourcesBudget()); } private Boolean isDeleteAllProjectsButtonDisabled() { return Configuration.getInstance().isDeleteAllProjectsButtonDisabled(); } /** * Should be public! * Used in orders/_orderFilter.zul */ public void deleteAllProjects() { boolean canNotDelete = false; for (Order order : orderModel.getOrders()) { try { orderModel.remove(order); } catch (Exception ignored) { canNotDelete = true; continue; } } if (canNotDelete) { messagesForUser.showMessage(Level.ERROR, "Not all projects were removed") ; } listing.setModel(new SimpleListModel<>(orderModel.getOrders())); listing.invalidate(); } }