org.libreplan.web.planner.taskedition.TaskPropertiesController.java Source code

Java tutorial

Introduction

Here is the source code for org.libreplan.web.planner.taskedition.TaskPropertiesController.java

Source

/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 2009-2010 Fundacin para o Fomento da Calidade Industrial e
 *                         Desenvolvemento Tecnolxico 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.planner.taskedition;

import static org.libreplan.web.I18nHelper._;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.joda.time.LocalDate;
import org.libreplan.business.advance.bootstrap.PredefinedAdvancedTypes;
import org.libreplan.business.advance.entities.AdvanceType;
import org.libreplan.business.advance.entities.DirectAdvanceAssignment;
import org.libreplan.business.advance.exceptions.DuplicateAdvanceAssignmentForOrderElementException;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.planner.entities.ITaskPositionConstrained;
import org.libreplan.business.planner.entities.PositionConstraintType;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.planner.entities.TaskPositionConstraint;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.scenarios.IScenarioManager;
import org.libreplan.business.users.entities.User;
import org.libreplan.business.users.entities.UserRole;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.web.I18nHelper;
import org.libreplan.web.common.Util;
import org.libreplan.web.email.IEmailNotificationModel;
import org.libreplan.web.planner.allocation.AllocationResult;
import org.libreplan.web.planner.order.SaveCommandBuilder;
import org.libreplan.web.resources.worker.IWorkerModel;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.dao.DataIntegrityViolationException;
import org.zkoss.ganttz.TaskEditFormComposer;
import org.zkoss.ganttz.TaskEditFormComposer.TaskDTO;
import org.zkoss.ganttz.data.TaskContainer;
import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.spring.SpringUtil;
import org.zkoss.zul.Comboitem;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Intbox;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Row;
import org.zkoss.zul.Tabpanel;

/**
 * Controller for edit {@link Task} popup.
 *
 * @author Manuel Rego Casasnovas <mrego@igalia.com>
 * @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
 */
@org.springframework.stereotype.Component("taskPropertiesController")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class TaskPropertiesController extends GenericForwardComposer<Component> {

    private final String WARNING = "Warning";

    private IScenarioManager scenarioManager;

    private TaskEditFormComposer taskEditFormComposer = new TaskEditFormComposer();

    private EditTaskController editTaskController;

    private TaskElement currentTaskElement;

    private Tabpanel tabpanel;

    private Intbox hours;

    private Intbox duration;

    private Decimalbox budget;

    private Datebox startDateBox;

    private Datebox endDateBox;

    private Datebox deadLineDateBox;

    private Combobox startConstraintTypes;

    private Datebox startConstraintDate;

    private Row startConstraint;

    private IContextWithPlannerTask<TaskElement> currentContext;

    private Row resourceAllocationType;

    private Listbox lbResourceAllocationType;

    private ResourceAllocationTypeEnum originalState;

    private boolean disabledConstraintsAndAllocations = false;

    public static AllocationResult allocationResult;

    private IEmailNotificationModel emailNotificationModel;

    private IWorkerModel workerModel;

    private boolean isResourcesAdded = false;

    private List<Resource> listToDelete = new ArrayList<>();

    private List<Resource> listToAdd = new ArrayList<>();

    public TaskPropertiesController() {
        if (emailNotificationModel == null) {
            emailNotificationModel = (IEmailNotificationModel) SpringUtil.getBean("emailNotificationModel");
        }

        if (workerModel == null) {
            workerModel = (IWorkerModel) SpringUtil.getBean("workerModel");
        }

        if (scenarioManager == null) {
            scenarioManager = (IScenarioManager) SpringUtil.getBean("scenarioManager");
        }
    }

    public void init(final EditTaskController editTaskController, IContextWithPlannerTask<TaskElement> context,
            TaskElement taskElement) {

        this.editTaskController = editTaskController;
        this.currentContext = context;
        this.currentTaskElement = taskElement;

        Order order;
        if (context != null) {
            order = findOrderIn(context);
        } else {
            order = taskElement.getOrderElement().getOrder();
        }

        setItemsStartConstraintTypesCombo(order);
        originalState = getResourceAllocationType(currentTaskElement);
        setOldState(originalState);

        disabledConstraintsAndAllocations = currentTaskElement.isSubcontractedAndWasAlreadySent()
                || currentTaskElement.isLimitingAndHasDayAssignments()
                || currentTaskElement.isUpdatedFromTimesheets();

        if (!disabledConstraintsAndAllocations && (currentTaskElement.isTask())) {
            disabledConstraintsAndAllocations = ((Task) currentTaskElement).isManualAnyAllocation();
        }

        startConstraintTypes.setDisabled(disabledConstraintsAndAllocations);
        startConstraintDate.setDisabled(disabledConstraintsAndAllocations);
        lbResourceAllocationType.setDisabled(disabledConstraintsAndAllocations);
        deadLineDateBox.setDisabled(currentTaskElement.isSubcontracted());

        if (context != null) {
            taskEditFormComposer.init(context.getTask());
        }

        updateComponentValuesForTask();
    }

    private void setItemsStartConstraintTypesCombo(Order order) {
        startConstraintTypes.getChildren().clear();
        for (PositionConstraintType type : PositionConstraintType.values()) {

            boolean firstCondition = type != PositionConstraintType.AS_LATE_AS_POSSIBLE
                    && type != PositionConstraintType.AS_SOON_AS_POSSIBLE;

            boolean secondCondition = type == PositionConstraintType.AS_LATE_AS_POSSIBLE
                    && order.getDeadline() != null;

            boolean thirdCondition = type == PositionConstraintType.AS_SOON_AS_POSSIBLE
                    && order.getInitDate() != null;

            if (firstCondition || secondCondition || thirdCondition) {
                Comboitem comboitem = new Comboitem(_(type.getName()));
                comboitem.setValue(type);
                startConstraintTypes.appendChild(comboitem);
            }
        }
    }

    private Order findOrderIn(IContextWithPlannerTask<TaskElement> context) {
        return context.getMapper().findAssociatedDomainObject(findTopMostTask(context)).getParent()
                .getOrderElement().getOrder();
    }

    private OrderElement findOrderElementIn(IContextWithPlannerTask<TaskElement> context) {
        return context.getMapper().findAssociatedDomainObject(findTopMostTask(context)).getOrderElement();
    }

    private org.zkoss.ganttz.data.Task findTopMostTask(IContextWithPlannerTask<TaskElement> context) {
        List<? extends TaskContainer> parents = context.getMapper().getParents(context.getTask());
        return parents.isEmpty() ? context.getTask() : parents.get(parents.size() - 1);
    }

    private void setOldState(ResourceAllocationTypeEnum state) {
        lbResourceAllocationType.setAttribute("oldState", state, true);
    }

    private ResourceAllocationTypeEnum getOldState() {
        return (ResourceAllocationTypeEnum) lbResourceAllocationType.getAttribute("oldState", true);
    }

    private void setResourceAllocationType(Listbox listbox, ResourceAllocationTypeEnum value) {
        setResourceAllocationType(listbox, value.toString());
    }

    private void setResourceAllocationType(Listbox listbox, String label) {
        for (Component component : listbox.getChildren()) {
            Listitem item = (Listitem) component;
            Listcell cell = (Listcell) item.getFirstChild();

            if (cell.getLabel() != null && cell.getLabel().equals(label)) {
                item.setSelected(true);
            }
        }
    }

    private void updateComponentValuesForTask() {
        if (currentTaskElement instanceof Task) {
            Task task = (Task) currentTaskElement;
            showDurationRow(task);
            showStartConstraintRow(task);
            showResourceAllocationTypeRow();
        } else {
            hideDurationRow();
            if (currentTaskElement instanceof ITaskPositionConstrained) {
                showStartConstraintRow((ITaskPositionConstrained) currentTaskElement);
            } else {
                hideStartConstraintRow();
            }
            hideResourceAllocationTypeRow();
        }

        hours.setValue(currentTaskElement.getWorkHours());
        budget.setValue(currentTaskElement.getBudget());
        Util.reloadBindings(tabpanel);
    }

    private void hideResourceAllocationTypeRow() {
        resourceAllocationType.setVisible(false);
    }

    private void showResourceAllocationTypeRow() {
        resourceAllocationType.setVisible(true);
    }

    private void hideStartConstraintRow() {
        startConstraint.setVisible(false);
    }

    private void showStartConstraintRow(ITaskPositionConstrained task) {
        startConstraint.setVisible(true);
        PositionConstraintType type = task.getPositionConstraint().getConstraintType();
        startConstraintTypes.setSelectedItem(findComboWithType(type));
        updateStartConstraint(type);
    }

    private Comboitem findComboWithType(PositionConstraintType type) {
        for (Object component : startConstraintTypes.getChildren()) {
            if (component instanceof Comboitem) {
                Comboitem item = (Comboitem) component;
                if ((item.getValue()) == type) {
                    return item;
                }
            }
        }

        return null;
    }

    private void constraintTypeChosen(PositionConstraintType constraint) {
        startConstraintDate.setVisible(constraint.isAssociatedDateRequired());
        updateStartConstraint(constraint);
    }

    private void updateStartConstraint(PositionConstraintType type) {
        TaskPositionConstraint taskStartConstraint = currentTaskElementAsTaskLeafConstraint()
                .getPositionConstraint();
        startConstraintDate.setVisible(type.isAssociatedDateRequired());
        if (taskStartConstraint.getConstraintDateAsDate() != null) {
            startConstraintDate.setValue(taskStartConstraint.getConstraintDateAsDate());
        }
    }

    private boolean saveConstraintChanges() {
        TaskPositionConstraint taskConstraint = currentTaskElementAsTaskLeafConstraint().getPositionConstraint();
        PositionConstraintType type = startConstraintTypes.getSelectedItem().getValue();

        IntraDayDate inputDate = type.isAssociatedDateRequired()
                ? IntraDayDate.startOfDay(LocalDate.fromDateFields(startConstraintDate.getValue()))
                : null;

        if (taskConstraint.isValid(type, inputDate)) {
            taskConstraint.update(type, inputDate);
            /*
             * At this point we could call currentContext.recalculatePosition(currentTaskElement)
             * to trigger the scheduling algorithm, but we don't do it because
             * the ResourceAllocationController, which is attached to the other
             * tab of the same window, will do it anyway.
             */
            return true;
        } else {
            return false;
        }
    }

    private ITaskPositionConstrained currentTaskElementAsTaskLeafConstraint() {
        return (ITaskPositionConstrained) currentTaskElement;
    }

    private void hideDurationRow() {
        hours.getFellow("durationRow").setVisible(false);
    }

    private void showDurationRow(Task task) {
        hours.getFellow("durationRow").setVisible(true);
        duration.setValue(task.getWorkableDays());
    }

    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        tabpanel = (Tabpanel) comp;
        taskEditFormComposer.doAfterCompose(comp);

        startConstraintTypes.addEventListener(Events.ON_SELECT, event -> {
            PositionConstraintType constraint = startConstraintTypes.getSelectedItem().getValue();
            constraintTypeChosen(constraint);
        });

        lbResourceAllocationType.addEventListener(Events.ON_SELECT, new EventListener() {

            @Override
            public void onEvent(Event event) {
                SelectEvent se = (SelectEvent) event;

                final ResourceAllocationTypeEnum oldState = getOldState();
                ResourceAllocationTypeEnum newState = getSelectedValue(new ArrayList(se.getSelectedItems()));
                if (thereIsTransition(newState)) {
                    if (isConsolidatedTask()) {
                        restoreOldState();
                        editTaskController.showNonPermitChangeResourceAllocationType();
                    } else {
                        if (newState.equals(ResourceAllocationTypeEnum.SUBCONTRACT)
                                && !checkCompatibleAllocation()) {
                            restoreOldState();
                            Messagebox.show(_("This resource allocation type is incompatible. The task has "
                                    + "an associated order element which has a progress that is of type subcontractor. "),
                                    _("Error"), Messagebox.OK, Messagebox.ERROR);
                        } else {
                            changeResourceAllocationType(oldState, newState);
                            editTaskController.selectAssignmentTab(lbResourceAllocationType.getSelectedIndex() + 1);
                        }
                    }
                }
                if (oldState == null) {
                    setOldState(newState);
                }
            }

            private ResourceAllocationTypeEnum getSelectedValue(List<Listitem> selectedItems) {
                final Listitem item = selectedItems.get(0);
                return ResourceAllocationTypeEnum.asEnum(((Listcell) item.getChildren().get(0)).getLabel());
            }

            private void restoreOldState() {
                Util.reloadBindings(lbResourceAllocationType);
            }

        });

    }

    private boolean checkCompatibleAllocation() {
        OrderElement orderElement;
        AdvanceType advanceType = PredefinedAdvancedTypes.SUBCONTRACTOR.getType();

        if (this.currentContext != null) {
            orderElement = findOrderElementIn(this.currentContext);
        } else {
            orderElement = this.currentTaskElement.getOrderElement();
        }

        if (orderElement.getAdvanceAssignmentByType(advanceType) != null) {
            return false;
        }

        try {
            DirectAdvanceAssignment newAdvanceAssignment = DirectAdvanceAssignment.create();
            newAdvanceAssignment.setAdvanceType(advanceType);

            orderElement.checkAncestorsNoOtherAssignmentWithSameAdvanceType(orderElement.getParent(),
                    newAdvanceAssignment);

        } catch (DuplicateAdvanceAssignmentForOrderElementException e) {
            return false;
        }

        return true;
    }

    private boolean thereIsTransition(ResourceAllocationTypeEnum newState) {
        return getOldState() != null && !getOldState().equals(newState);
    }

    public TaskDTO getGanttTaskDTO() {
        return taskEditFormComposer == null ? null : taskEditFormComposer.getTaskDTO();
    }

    public void accept() {
        if (!isResourcesAdded) {
            listToAdd.clear();
        }

        SaveCommandBuilder.taskPropertiesController = getObject();

        boolean ok = true;

        if (currentTaskElement instanceof ITaskPositionConstrained) {
            ok = saveConstraintChanges();
        }
        if (ok) {
            if (disabledConstraintsAndAllocations) {
                taskEditFormComposer.accept();
            } else {
                taskEditFormComposer.acceptWithoutCopyingDates();
            }
        }
    }

    public void cancel() {
        taskEditFormComposer.cancel();
    }

    /**
     * Enum for showing type of resource assignation option list.
     *
     * @author Diego Pino Garcia <dpino@igalia.com>
     */
    enum ResourceAllocationTypeEnum {
        NON_LIMITING_RESOURCES(_("Normal resource assignment")), LIMITING_RESOURCES(
                _("Queue-based resource assignation")), SUBCONTRACT(_("Subcontract"));

        private String option;

        private static final List<ResourceAllocationTypeEnum> nonMasterOptionList = new ArrayList<ResourceAllocationTypeEnum>() {
            {
                add(NON_LIMITING_RESOURCES);
                add(SUBCONTRACT);
            }
        };

        ResourceAllocationTypeEnum(String option) {
            this.option = option;
        }

        /**
         * Forces to mark the string as needing translation.
         */
        private static String _(String string) {
            return string;
        }

        @Override
        public String toString() {
            return I18nHelper._(option);
        }

        public static List<ResourceAllocationTypeEnum> getOptionList() {
            return Arrays.asList(values());
        }

        public static List<ResourceAllocationTypeEnum> getOptionListForNonMasterBranch() {
            return nonMasterOptionList;
        }

        public static ResourceAllocationTypeEnum getDefault() {
            return NON_LIMITING_RESOURCES;
        }

        public static ResourceAllocationTypeEnum asEnum(String label) {
            if (NON_LIMITING_RESOURCES.toString().equals(label)) {
                return NON_LIMITING_RESOURCES;

            } else if (LIMITING_RESOURCES.toString().equals(label)) {
                return LIMITING_RESOURCES;

            } else if (SUBCONTRACT.toString().equals(label)) {
                return SUBCONTRACT;
            }

            return getDefault();
        }

    }

    public List<ResourceAllocationTypeEnum> getResourceAllocationTypeOptionList() {
        return scenarioManager.getCurrent().isMaster() ? ResourceAllocationTypeEnum.getOptionList()
                : ResourceAllocationTypeEnum.getOptionListForNonMasterBranch();
    }

    public ResourceAllocationTypeEnum getResourceAllocationType() {
        return getResourceAllocationType(currentTaskElement);
    }

    /**
     * Does nothing, but it must exist for receiving selected value from ListBox.
     *
     * @param resourceAllocation
     */
    public void setResourceAllocationType(ResourceAllocationTypeEnum resourceAllocation) {
    }

    ResourceAllocationTypeEnum getResourceAllocationType(TaskElement taskElement) {
        return taskElement == null || !isTask(taskElement) ? null
                : getResourceAllocationType(asTask(currentTaskElement));
    }

    /**
     * Returns type of resource allocation depending on state of task.
     *
     * If task is subcontracted, return a SUBCONTRACT state.
     * If task has at least one limiting resource, returns a LIMITING RESOURCE state.
     * Otherwise, return default state (NON-LIMITING RESOURCE).
     *
     * @return {@link ResourceAllocationTypeEnum}
     */
    private ResourceAllocationTypeEnum getResourceAllocationType(Task task) {
        ResourceAllocationTypeEnum result = ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES;

        if (task.isSubcontracted()) {
            result = ResourceAllocationTypeEnum.SUBCONTRACT;
        }
        if (task.isLimiting()) {
            result = ResourceAllocationTypeEnum.LIMITING_RESOURCES;
        }

        return result;
    }

    private boolean isTask(TaskElement taskElement) {
        return taskElement instanceof Task;
    }

    private Task asTask(TaskElement taskElement) {
        return (Task) taskElement;
    }

    private void changeResourceAllocationType(ResourceAllocationTypeEnum from, ResourceAllocationTypeEnum to) {
        if (from.equals(ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES)) {
            fromNonLimitingResource(to);
        } else if (from.equals(ResourceAllocationTypeEnum.LIMITING_RESOURCES)) {
            fromLimitingResource(to);
        } else if (from.equals(ResourceAllocationTypeEnum.SUBCONTRACT)) {
            fromSubcontract(to);
        }
    }

    /**
     * Change state from NonLimitingResource assignation type to a new state (limiting, subcontract).
     *
     * @param newState
     */
    private void fromNonLimitingResource(ResourceAllocationTypeEnum newState) {
        if (!isTask(currentTaskElement)) {
            return;
        }

        Task task = asTask(currentTaskElement);
        if (task.hasResourceAllocations()) {
            if (Messagebox.show(_("Assigned resources for this task will be deleted. Are you sure?"), _(WARNING),
                    Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.OK) {
                task.removeAllResourceAllocations();
                setStateTo(newState);
            } else {
                resetStateTo(ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES);
            }
            return;
        }

        setStateTo(newState);
    }

    private void setStateTo(ResourceAllocationTypeEnum state) {
        setOldState(state);
        editTaskController.showTabPanel(state);
    }

    private void resetStateTo(ResourceAllocationTypeEnum state) {
        setResourceAllocationType(lbResourceAllocationType, state);
        setOldState(state);
    }

    /**
     * Change state from LimitingResource assignation type to a new state (non-limiting, subcontract).
     *
     * @param newState
     */
    private void fromLimitingResource(ResourceAllocationTypeEnum newState) {
        if (!isTask(currentTaskElement)) {
            return;
        }

        Task task = asTask(currentTaskElement);
        if (task.hasResourceAllocations()) {
            if (Messagebox.show(_("Assigned resources for this task will be deleted. Are you sure?"), _(WARNING),
                    Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.OK) {
                task.removeAllResourceAllocations();
                setStateTo(newState);
            } else {
                resetStateTo(ResourceAllocationTypeEnum.LIMITING_RESOURCES);
            }
            return;
        }

        setStateTo(newState);
    }

    /**
     * Change state from Subcontract assignation type to a new state (non-limiting, limiting).
     *
     * @param newState
     */
    private void fromSubcontract(ResourceAllocationTypeEnum newState) {
        Task task = asTask(currentTaskElement);

        if (task.isSubcontracted()) {
            final Date communicationDate = (task.getSubcontractedTaskData() != null)
                    ? task.getSubcontractedTaskData().getSubcontractCommunicationDate()
                    : null;

            // Notification has been sent
            if (communicationDate != null) {

                if (Messagebox.show(_(
                        "IMPORTANT: Don't forget to communicate to subcontractor that his contract has been cancelled"),
                        _(WARNING), Messagebox.OK, Messagebox.EXCLAMATION) == Messagebox.OK) {

                    setStateTo(newState);
                } else {
                    resetStateTo(ResourceAllocationTypeEnum.SUBCONTRACT);
                }
                return;
            }
        }
        setStateTo(newState);
    }

    boolean stateHasChanged() {
        final ResourceAllocationTypeEnum currentState = getCurrentState();
        return currentState != null && !currentState.equals(getOriginalState());
    }

    ResourceAllocationTypeEnum getOriginalState() {
        return originalState;
    }

    ResourceAllocationTypeEnum getCurrentState() {
        return getSelectedResourceAllocationType();
    }

    private ResourceAllocationTypeEnum getSelectedResourceAllocationType() {
        final Listitem item = lbResourceAllocationType.getSelectedItem();
        if (item == null) {
            return null;
        }

        final Listcell cell = (Listcell) item.getChildren().get(0);

        return ResourceAllocationTypeEnum.asEnum(cell.getLabel());
    }

    private boolean isConsolidatedTask() {
        Task task = asTask(currentTaskElement);
        return task != null && task.hasConsolidations();
    }

    public void updateTaskEndDate(LocalDate endDate) {
        getGanttTaskDTO().endDate = endDate.toDateTimeAtStartOfDay().toDate();
        Util.reloadBindings(endDateBox);
    }

    public void updateTaskStartDate(LocalDate newStart) {
        getGanttTaskDTO().beginDate = newStart.toDateTimeAtStartOfDay().toDate();
        Util.reloadBindings(startDateBox);
    }

    TaskEditFormComposer getTaskEditFormComposer() {
        return taskEditFormComposer;
    }

    public void refreshTaskEndDate() {
        Util.reloadBindings(endDateBox);
    }

    public String getMoneyFormat() {
        return Util.getMoneyFormat();
    }

    /**
     * Check if resources in allocation are bound by user and in what ROLE they are.
     * setUser method calling manually because, after initialization user will be null.
     * Then send valid data to notification_queue table.
     */
    public void emailNotificationAddNew() {
        proceedList(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE, listToAdd);
        proceedList(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK, listToDelete);
        listToAdd.clear();
        listToDelete.clear();
    }

    private void proceedList(EmailTemplateEnum enumeration, List<Resource> list) {
        if (!list.isEmpty()) {
            List<Worker> workersList = workerModel.getWorkers();
            Worker currentWorker;
            Resource currentResource;

            for (Worker aWorkersList : workersList)
                for (Resource aList : list) {

                    currentWorker = aWorkersList;
                    currentResource = aList;

                    if (currentWorker.getId().equals(currentResource.getId())) {

                        aWorkersList.setUser(workerModel.getBoundUserFromDB(currentWorker));
                        User currentUser = currentWorker.getUser();

                        if (currentUser != null
                                && (currentUser.isInRole(UserRole.ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE)
                                        || currentUser.isInRole(UserRole.ROLE_EMAIL_RESOURCE_REMOVED_FROM_TASK))) {
                            setEmailNotificationEntity(enumeration, currentResource);
                        }

                        break;
                    }
                }
        }
    }

    private void setEmailNotificationEntity(EmailTemplateEnum enumeration, Resource resource) {
        try {
            emailNotificationModel.setNewObject();

            if (enumeration.equals(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE)) {
                emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE);
            } else if (enumeration.equals(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK)) {
                emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK);
            }

            emailNotificationModel.setUpdated(new Date());

            emailNotificationModel.setResource(resource);

            emailNotificationModel.setTask(currentTaskElement.getTaskSource().getTask());

            emailNotificationModel.setProject(currentTaskElement.getParent().getTaskSource().getTask());

            emailNotificationModel.confirmSave();
        } catch (DataIntegrityViolationException e) {
            Messagebox.show(_("You cannot email user twice with the same info"), _("Error"), Messagebox.OK,
                    Messagebox.ERROR);
        }
    }

    public List<Resource> getListToDelete() {
        return listToDelete;
    }

    public List<Resource> getListToAdd() {
        return listToAdd;
    }

    public void setResourcesAdded(boolean resourcesAdded) {
        isResourcesAdded = resourcesAdded;
    }

    public TaskPropertiesController getObject() {
        return this;
    }

}