diff --git a/doc/src/user/en/15-1-report-hours-worked-by-resource.rst b/doc/src/user/en/15-1-report-hours-worked-by-resource.rst
index ec030c766..690e97acb 100644
--- a/doc/src/user/en/15-1-report-hours-worked-by-resource.rst
+++ b/doc/src/user/en/15-1-report-hours-worked-by-resource.rst
@@ -8,22 +8,22 @@ Purpose
This report allows to extract a list of the tasks and time devoted to them by workers in a period of time. There are several filters which allow users to adjust the query to get just the wanted information and avoiding extra data.
-Input paratemers and filters
+Input parameters and filters
============================
* **Dates**.
* *Type*: Optional.
* *Two date fields*:
- * *Start Date.* This is the minimum date of the work reports which are wanted. Work reports with an earlier date than the *start date* are ignored. If this parameter is not filled, there is not inferior filtering date.
- * *End Date.* This is the maximum date of the work reports which will be included in the results. Work reports with a later date than the *end date* will be skipped. If this parameter is not filled, there is not upper limit of the work reports filtered.
+ * *Start Date.* This is the minimum date of the work reports which are wanted. Work reports with an earlier date than the *start date* are ignored. If this parameter is not filled, there is no filtering of work reports by *start date*.
+ * *End Date.* This is the maximum date of the work reports which will be included in the results. Work reports with a later date than the *end date* will be ignored. If this parameter is not filled, there is no filtering of work reports by *end date*.
* **Filter by workers**
* *Type*: Optional.
- * *How it works*: You can select one worker to restrict the work reports to the time tracking of that particular worker. If you leave it empty, the work reports are retrieved independently of the worker.
+ * *How it works*: You can select one or several workers to restrict the work reports to the time tracking of that particular worker. You can add a worker to be used as a filter by searching them in the selector and by pressing the *Add* button. If you leave it empty, the work reports are retrieved independently of the worker.
* **Filter by labels**
* *Type:* Optional.
- * *How it works*: You can add one or several labels by searching them in the selector and by pressing the *Add* button to be used as filter. They are used to select the tasks that will be included in the results to compute the hours devoted in them.
+ * *How it works*: You can add one or several labels to be used as filter by searching them in the selector and by pressing the *Add* button. They are used to select the tasks that will be included in the results to compute the hours devoted in them. This filter can be applied to timesheets, tasks, both, or any.
* **Filter by criteria**
* *Type:* Optional.
@@ -39,7 +39,7 @@ In the heading of the report is informed about the filters that were configured
Foot page
---------
-The date in which the repot was got is showed.
+The date on which the report was run is listed.
Body
----
diff --git a/doc/src/user/en/17-project-dashboard.rst b/doc/src/user/en/17-1-project-dashboard.rst
similarity index 98%
rename from doc/src/user/en/17-project-dashboard.rst
rename to doc/src/user/en/17-1-project-dashboard.rst
index 950d78e2f..4e26e6cf9 100644
--- a/doc/src/user/en/17-project-dashboard.rst
+++ b/doc/src/user/en/17-1-project-dashboard.rst
@@ -30,6 +30,8 @@ The progress is represented with two bars:
* *Expected progress*. It is the progress the project should have at the
moment according to the planning created.
+To view each bar's actual measured valued hover the mouse cursor over the bar.
+
The project global progress is estimated in several different ways as there
is not a unique right method to do it:
@@ -79,7 +81,6 @@ There are several *Earned Value Management* cost indicators calculated:
* = 100 is also good, means the cost is right on plan.
* < 100 is bad, means that the cost of completing the work is higher than
planned.
-
* **ETC (Estimate To Complete)**. It is the time that is pending to devote
to the project to finish it.
* **BAC (Budget At Completion)**. It is the total amount of work allocated
diff --git a/doc/src/user/en/17-2-pipeline-dashboard.rst b/doc/src/user/en/17-2-pipeline-dashboard.rst
new file mode 100644
index 000000000..34a3af1bb
--- /dev/null
+++ b/doc/src/user/en/17-2-pipeline-dashboard.rst
@@ -0,0 +1,24 @@
+Pipeline planning dashboard
+###############################
+
+.. contents::
+
+The pipeline planning dashboard is a *LibrePlan* perspective which lists the names of all company projects in a table.
+This 'pipeline' table has nine columns each corresponding to a project status:
+
+ * PRE-SALES
+ * OFFERED
+ * OUTSOURCED
+ * ACCEPTED
+ * STARTED
+ * ON HOLD
+ * FINISHED
+ * CANCELLED
+ * ARCHIVED
+
+Projects are listed by name in each column based on their current status.
+
+A project's start date, end date, and current progress can be viewed in a 'tool tip' popup by hovering the mouse pointer
+over a project's name.
+
+Projects with an *ARCHIVED* status can be hidden by unchecking the 'Show archived column data' checkbox.
\ No newline at end of file
diff --git a/doc/src/user/en/17-dashboards.rst b/doc/src/user/en/17-dashboards.rst
new file mode 100644
index 000000000..3c09d420d
--- /dev/null
+++ b/doc/src/user/en/17-dashboards.rst
@@ -0,0 +1,19 @@
+Dashboards
+##########
+
+.. _informes:
+.. contents::
+
+
+"LibrePlan" has dashboard views for projects that provide an overview of the current state of projects.
+
+The two dashboard views are:
+
+.. raw:: html
+
+
diff --git a/doc/src/user/en/parts b/doc/src/user/en/parts
index 760539e57..8fec6673f 100644
--- a/doc/src/user/en/parts
+++ b/doc/src/user/en/parts
@@ -25,7 +25,8 @@
14-custos Xavier Castaño (xcastanho@igalia.com)
15-informes Xavier Castaño (xcastanho@igalia.com)
16-ldap-authentication Ignacio Diaz Teijido (ignacio.diaz@cafedered.com), Javier Moran Rua (jmoran@igalia.com)
-17-project-dashboard Javier Moran Rua (jmoran@igalia.com)
+17-dashboards Javier Moran Rua (jmoran@igalia.com)
18-connectors Miciele Ghiorghis (m.ghiorghis@antoniusziekenhuis.nl)
19-scheduler Miciele Ghiorghis (m.ghiorghis@antoniusziekenhuis.nl)
20-acerca-de Xavier Castaño (xcastanho@igalia.com)
+21-communications Xavier Castaño (xcastanho@igalia.com)
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/FunctionalityExposedForExtensions.java b/ganttzk/src/main/java/org/zkoss/ganttz/FunctionalityExposedForExtensions.java
index 23e74d03d..6d3622ad0 100644
--- a/ganttzk/src/main/java/org/zkoss/ganttz/FunctionalityExposedForExtensions.java
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/FunctionalityExposedForExtensions.java
@@ -243,6 +243,8 @@ public class FunctionalityExposedForExtensions implements IContext {
result.setShowingReportedHours(planner.showReportedHoursRightNow());
result.setShowingMoneyCostBar(planner.showMoneyCostBarRightNow());
result.setShowingAdvances(planner.showAdvancesRightNow());
+ result.setShowingLabels(planner.showLabelsRightNow());
+ result.setShowingResources(planner.showResourcesRightNow());
mapper.register(position, result, data);
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java b/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java
index 568d08154..1cc579285 100644
--- a/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java
@@ -156,6 +156,10 @@ public class Planner extends HtmlMacroComponent {
private boolean shownMoneyCostBarByDefault = false;
+ private boolean shownLabelsByDefault = false;
+
+ private boolean shownResourcesByDefault = false;
+
private FilterAndParentExpandedPredicates predicate;
private boolean visibleChart;
@@ -430,6 +434,27 @@ public class Planner extends HtmlMacroComponent {
showMoneyCostBarButton.setVisible(false);
}
+ // view buttons toggle state so set all off prior to toggling
+ if ( configuration.isShowResourcesOn() ) {
+ showAllResources();
+ }
+
+ if ( configuration.isShowAdvancesOn() ) {
+ showAdvances();
+ }
+
+ if ( configuration.isShowReportedHoursOn() ) {
+ showReportedHours();
+ }
+
+ if ( configuration.isShowLabelsOn() ) {
+ showAllLabels();
+ }
+
+ if ( configuration.isShowMoneyCostBarOn() ) {
+ showMoneyCostBar();
+ }
+
listZoomLevels.setSelectedIndex(getZoomLevel().ordinal());
this.visibleChart = configuration.isExpandPlanningViewCharts();
@@ -656,7 +681,6 @@ public class Planner extends HtmlMacroComponent {
public void showReportedHours() {
Button showReportedHoursButton = (Button) getFellow("showReportedHours");
if ( disabilityConfiguration.isReportedHoursEnabled() ) {
-
if ( isShowingReportedHours ) {
context.hideReportedHours();
diagramGraph.removePostGraphChangeListener(showReportedHoursOnChange);
@@ -694,28 +718,33 @@ public class Planner extends HtmlMacroComponent {
public void showAllLabels() {
Button showAllLabelsButton = (Button) getFellow("showAllLabels");
- if ( isShowingLabels ) {
- Clients.evalJavaScript("ganttz.TaskList.getInstance().hideAllTaskLabels()");
- showAllLabelsButton.setSclass("planner-command show-labels");
- } else {
- Clients.evalJavaScript("ganttz.TaskList.getInstance().showAllTaskLabels()");
- showAllLabelsButton.setSclass("planner-command show-labels clicked");
- }
+ if ( disabilityConfiguration.isLabelsEnabled() ) {
+ if ( isShowingLabels ) {
+ Clients.evalJavaScript("ganttz.TaskList.getInstance().hideAllTaskLabels()");
+ showAllLabelsButton.setSclass("planner-command show-labels");
+ } else {
+ Clients.evalJavaScript("ganttz.TaskList.getInstance().showAllTaskLabels()");
+ showAllLabelsButton.setSclass("planner-command show-labels clicked");
+ }
- isShowingLabels = !isShowingLabels;
+ isShowingLabels = !isShowingLabels;
+ }
}
public void showAllResources() {
Button showAllLabelsButton = (Button) getFellow("showAllResources");
- if ( isShowingResources ) {
- Clients.evalJavaScript("ganttz.TaskList.getInstance().hideResourceTooltips()");
- showAllLabelsButton.setSclass("planner-command show-resources");
- } else {
- Clients.evalJavaScript("ganttz.TaskList.getInstance().showResourceTooltips()");
- showAllLabelsButton.setSclass("planner-command show-resources clicked");
- }
+ if ( disabilityConfiguration.isResourcesEnabled() ) {
+ if ( isShowingResources ) {
+ Clients.evalJavaScript("ganttz.TaskList.getInstance().hideResourceTooltips()");
+ showAllLabelsButton.setSclass("planner-command show-resources");
+ } else {
+ Clients.evalJavaScript("ganttz.TaskList.getInstance().showResourceTooltips()");
+ showAllLabelsButton.setSclass("planner-command show-resources clicked");
+ }
- isShowingResources = !isShowingResources;
+ isShowingResources = !isShowingResources;
+
+ }
}
public void print() {
@@ -752,7 +781,6 @@ public class Planner extends HtmlMacroComponent {
public void setAreShownAdvancesByDefault(boolean shownAdvanceByDefault) {
this.shownAdvanceByDefault = shownAdvanceByDefault;
- this.isShowingAdvances = shownAdvanceByDefault;
}
public void setAreShownReportedHoursByDefault(boolean shownReportedHoursByDefault) {
@@ -779,6 +807,30 @@ public class Planner extends HtmlMacroComponent {
return areShownMoneyCostBarByDefault() || isShowingMoneyCostBar;
}
+ public void setAreShownLabelsByDefault(boolean shownLabelsByDefault) {
+ this.shownLabelsByDefault = shownLabelsByDefault;
+ }
+
+ public boolean areShownLabelsByDefault() {
+ return shownLabelsByDefault;
+ }
+
+ public boolean showLabelsRightNow() {
+ return areShownLabelsByDefault() || isShowingLabels;
+ }
+
+ public void setAreShownResourcesByDefault(boolean shownResourcesByDefault) {
+ this.shownResourcesByDefault = shownResourcesByDefault;
+ }
+
+ public boolean areShownResourcesByDefault() {
+ return shownResourcesByDefault;
+ }
+
+ public boolean showResourcesRightNow() {
+ return areShownResourcesByDefault() || isShowingResources;
+ }
+
public void expandAll() {
Button expandAllButton = (Button) getFellow(EXPAND_ALL_BUTTON);
if ( disabilityConfiguration.isExpandAllEnabled() ) {
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/adapters/IDisabilityConfiguration.java b/ganttzk/src/main/java/org/zkoss/ganttz/adapters/IDisabilityConfiguration.java
index 6f5b50b38..19a28ee5e 100644
--- a/ganttzk/src/main/java/org/zkoss/ganttz/adapters/IDisabilityConfiguration.java
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/adapters/IDisabilityConfiguration.java
@@ -42,6 +42,10 @@ public interface IDisabilityConfiguration {
public boolean isMoneyCostBarEnabled();
+ public boolean isLabelsEnabled();
+
+ public boolean isResourcesEnabled();
+
public boolean isExpandAllEnabled();
public boolean isFlattenTreeEnabled();
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/adapters/PlannerConfiguration.java b/ganttzk/src/main/java/org/zkoss/ganttz/adapters/PlannerConfiguration.java
index e13f5bb88..e7464bd36 100644
--- a/ganttzk/src/main/java/org/zkoss/ganttz/adapters/PlannerConfiguration.java
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/adapters/PlannerConfiguration.java
@@ -157,6 +157,10 @@ public class PlannerConfiguration implements IDisabilityConfiguration {
private boolean moneyCostBarEnabled = true;
+ private boolean labelsEnabled = true;
+
+ private boolean ResourcesEnabled = true;
+
private boolean expandAllEnabled = true;
private boolean flattenTreeEnabled = true;
@@ -167,6 +171,18 @@ public class PlannerConfiguration implements IDisabilityConfiguration {
private boolean treeEditable = true;
+ private boolean showResourcesOn = false;
+
+ private boolean showAdvancesOn = false;
+
+ private boolean showReportedHoursOn = false;
+
+ private boolean showLabelsOn = false;
+
+ private boolean showMoneyCostBarOn = false;
+
+ private boolean filterExcludeFinishedProject = false;
+
private IDetailItemModifier firstLevelModifiers = SeveralModifiers.empty();
private IDetailItemModifier secondLevelModifiers = SeveralModifiers.empty();
@@ -355,6 +371,24 @@ public class PlannerConfiguration implements IDisabilityConfiguration {
return moneyCostBarEnabled;
}
+ public void setLabelsEnabled(boolean labelsEnabled) {
+ this.labelsEnabled = labelsEnabled;
+ }
+
+ @Override
+ public boolean isLabelsEnabled() {
+ return labelsEnabled;
+ }
+
+ public void setResourcesEnabled(boolean ResourcesEnabled) {
+ this.ResourcesEnabled = ResourcesEnabled;
+ }
+
+ @Override
+ public boolean isResourcesEnabled() {
+ return ResourcesEnabled;
+ }
+
public void setExpandAllEnabled(boolean expandAllEnabled) {
this.expandAllEnabled = expandAllEnabled;
}
@@ -495,4 +529,52 @@ public class PlannerConfiguration implements IDisabilityConfiguration {
this.scheduleBackwards = scheduleBackwards;
}
+ public boolean isShowResourcesOn() {
+ return showResourcesOn;
+ }
+
+ public void setShowResourcesOn(boolean showResourcesOn) {
+ this.showResourcesOn = showResourcesOn;
+ }
+
+ public boolean isShowAdvancesOn() {
+ return showAdvancesOn;
+ }
+
+ public void setShowAdvancesOn(boolean showAdvancesOn) {
+ this.showAdvancesOn = showAdvancesOn;
+ }
+
+ public boolean isShowReportedHoursOn() {
+ return showReportedHoursOn;
+ }
+
+ public void setShowReportedHoursOn(boolean showReportedHoursOn) {
+ this.showReportedHoursOn = showReportedHoursOn;
+ }
+
+ public boolean isShowLabelsOn() {
+ return showLabelsOn;
+ }
+
+ public void setShowLabelsOn(boolean showLabelsOn) {
+ this.showLabelsOn = showLabelsOn;
+ }
+
+ public boolean isShowMoneyCostBarOn() {
+ return showMoneyCostBarOn;
+ }
+
+ public void setShowMoneyCostBarOn(boolean showMoneyCostBarOn) {
+ this.showMoneyCostBarOn = showMoneyCostBarOn;
+ }
+
+ public boolean isFilterExcludeFinishedProject() {
+ return filterExcludeFinishedProject;
+ }
+
+ public void setFilterExcludeFinishedProject(boolean filterExcludeFinishedProject) {
+ this.filterExcludeFinishedProject = filterExcludeFinishedProject;
+ }
+
}
diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/data/Task.java b/ganttzk/src/main/java/org/zkoss/ganttz/data/Task.java
index 086156365..3c9a370ef 100644
--- a/ganttzk/src/main/java/org/zkoss/ganttz/data/Task.java
+++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/Task.java
@@ -73,6 +73,10 @@ public abstract class Task implements ITaskFundamentalProperties {
private PropertyChangeSupport moneyCostBarProperty = new PropertyChangeSupport(this);
+ private PropertyChangeSupport labelsProperty = new PropertyChangeSupport(this);
+
+ private PropertyChangeSupport resourcesProperty = new PropertyChangeSupport(this);
+
private final ITaskFundamentalProperties fundamentalProperties;
private boolean visible = true;
@@ -85,6 +89,10 @@ public abstract class Task implements ITaskFundamentalProperties {
private boolean showingMoneyCostBar = false;
+ private boolean showingLabels = false;
+
+ private boolean showingResources = false;
+
private ConstraintViolationNotificator violationNotificator = ConstraintViolationNotificator.create();
private IDependenciesEnforcerHook dependenciesEnforcerHook = GanttDiagramGraph.doNothingHook();
@@ -231,6 +239,26 @@ public abstract class Task implements ITaskFundamentalProperties {
return showingMoneyCostBar;
}
+ public void setShowingResources(boolean showingResources) {
+ boolean previousValue = this.showingResources;
+ this.showingResources = showingResources;
+ resourcesProperty.firePropertyChange("showingResources", previousValue, this.showingResources);
+ }
+
+ public boolean isShowingResources() {
+ return showingResources;
+ }
+
+ public void setShowingLabels(boolean showingLabels) {
+ boolean previousValue = this.showingLabels;
+ this.showingLabels = showingLabels;
+ labelsProperty.firePropertyChange("showingLabels", previousValue, this.showingLabels);
+ }
+
+ public boolean isShowingLabels() {
+ return showingLabels;
+ }
+
public String getName() {
return fundamentalProperties.getName();
}
diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/AdHocTransactionService.java b/libreplan-business/src/main/java/org/libreplan/business/common/AdHocTransactionService.java
index d33a40507..f4cee5e70 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/common/AdHocTransactionService.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/common/AdHocTransactionService.java
@@ -103,6 +103,7 @@ public class AdHocTransactionService implements IAdHocTransactionService {
};
}
+ @Override
@Transactional
public T runOnTransaction(IOnTransaction onTransaction) {
return onTransaction.execute();
diff --git a/libreplan-business/src/main/java/org/libreplan/business/email/daos/EmailNotificationDAO.java b/libreplan-business/src/main/java/org/libreplan/business/email/daos/EmailNotificationDAO.java
index 109ef16bb..b114159f3 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/email/daos/EmailNotificationDAO.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/email/daos/EmailNotificationDAO.java
@@ -23,8 +23,12 @@ import org.hibernate.criterion.Restrictions;
import org.libreplan.business.common.daos.GenericDAOHibernate;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
+import org.libreplan.business.orders.entities.Order;
+import org.libreplan.business.planner.entities.TaskElement;
import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+//import java.util.ArrayList;
import java.util.List;
/**
@@ -50,6 +54,22 @@ public class EmailNotificationDAO
.list();
}
+ @Override
+ public List getAllByProject(TaskElement taskElement) {
+ return getSession()
+ .createCriteria(EmailNotification.class)
+ .add(Restrictions.eq("project", taskElement))
+ .list();
+ }
+
+ @Override
+ public List getAllByTask(TaskElement taskElement) {
+ return getSession()
+ .createCriteria(EmailNotification.class)
+ .add(Restrictions.eq("task", taskElement))
+ .list();
+ }
+
@Override
public boolean deleteAll() {
List notifications = list(EmailNotification.class);
@@ -89,4 +109,26 @@ public class EmailNotificationDAO
.uniqueResult() == null;
}
+ @Override
+ public boolean deleteByProject(TaskElement taskElement) {
+ List notifications = getAllByProject(taskElement);
+
+ for (Object item : notifications){
+ getSession().delete(item);
+ }
+
+ return getAllByProject(taskElement).isEmpty();
+ }
+
+ @Override
+ public boolean deleteByTask(TaskElement taskElement) {
+ List notifications = getAllByTask(taskElement);
+
+ for (Object item : notifications){
+ getSession().delete(item);
+ }
+
+ return getAllByTask(taskElement).isEmpty();
+ }
+
}
diff --git a/libreplan-business/src/main/java/org/libreplan/business/email/daos/IEmailNotificationDAO.java b/libreplan-business/src/main/java/org/libreplan/business/email/daos/IEmailNotificationDAO.java
index 92a32c886..881e7ff4e 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/email/daos/IEmailNotificationDAO.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/email/daos/IEmailNotificationDAO.java
@@ -22,6 +22,8 @@ package org.libreplan.business.email.daos;
import org.libreplan.business.common.daos.IGenericDAO;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
+import org.libreplan.business.orders.entities.Order;
+import org.libreplan.business.planner.entities.TaskElement;
import java.util.List;
@@ -36,9 +38,18 @@ public interface IEmailNotificationDAO extends IGenericDAO getAllByType(EmailTemplateEnum enumeration);
+ List getAllByProject(TaskElement taskElement);
+
+ List getAllByTask(TaskElement taskElement);
+
boolean deleteAll();
boolean deleteAllByType(EmailTemplateEnum enumeration);
boolean deleteById(EmailNotification notification);
+
+ boolean deleteByProject(TaskElement taskElement);
+
+ boolean deleteByTask(TaskElement taskElement);
+
}
diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/IOrderDAO.java b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/IOrderDAO.java
index ca8cd9f62..7457879ce 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/IOrderDAO.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/IOrderDAO.java
@@ -86,7 +86,7 @@ public interface IOrderDAO extends IIntegrationEntityDAO {
List getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
String username, Scenario scenario, Date startDate, Date endDate,
List labels, List criteria,
- ExternalCompany customer, OrderStatusEnum state);
+ ExternalCompany customer, OrderStatusEnum state, Boolean excludeFinishedProject);
/**
* Returns the order filtered by the name.
diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderDAO.java b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderDAO.java
index 223dfe04e..3e82cd7ff 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderDAO.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderDAO.java
@@ -231,9 +231,10 @@ public class OrderDAO extends IntegrationEntityDAO implements IOrderDAO {
List labels,
List criteria,
ExternalCompany customer,
- OrderStatusEnum state) {
+ OrderStatusEnum state,
+ Boolean excludeFinishedProject) {
- List ordersIdsFiltered = getOrdersIdsFiltered(user, labels, criteria, customer, state);
+ List ordersIdsFiltered = getOrdersIdsFiltered(user, labels, criteria, customer, state, excludeFinishedProject);
if (ordersIdsFiltered != null && ordersIdsFiltered.isEmpty()) {
return Collections.emptyList();
}
@@ -354,7 +355,8 @@ public class OrderDAO extends IntegrationEntityDAO implements IOrderDAO {
List labels,
List criteria,
ExternalCompany customer,
- OrderStatusEnum state) {
+ OrderStatusEnum state,
+ Boolean excludeFinishedProject) {
List ordersIdsByReadAuthorization = getOrdersIdsByReadAuthorization(user);
@@ -405,6 +407,15 @@ public class OrderDAO extends IntegrationEntityDAO implements IOrderDAO {
where += "o.state = :state ";
}
+ if (excludeFinishedProject != null && excludeFinishedProject == true) {
+ if (where.isEmpty()) {
+ where += "WHERE ";
+ } else {
+ where += "AND ";
+ }
+ where += "o.state <> '" + OrderStatusEnum.FINISHED.getIndex() + "'";
+ }
+
// If not restrictions by labels, criteria, customer or state
if (where.isEmpty()) {
return ordersIdsByReadAuthorization;
@@ -550,7 +561,8 @@ public class OrderDAO extends IntegrationEntityDAO implements IOrderDAO {
List labels,
List criteria,
ExternalCompany customer,
- OrderStatusEnum state) {
+ OrderStatusEnum state,
+ Boolean excludeFinishedProject) {
User user;
try {
@@ -559,7 +571,7 @@ public class OrderDAO extends IntegrationEntityDAO implements IOrderDAO {
throw new RuntimeException(e);
}
return existsInScenario(getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
- user, startDate, endDate, labels, criteria, customer, state), scenario);
+ user, startDate, endDate, labels, criteria, customer, state, excludeFinishedProject), scenario);
}
private List existsInScenario(List orders, Scenario scenario) {
diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderElementDAO.java b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderElementDAO.java
index 8f6ff4e5f..3a57fed87 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderElementDAO.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderElementDAO.java
@@ -39,6 +39,7 @@ import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.libreplan.business.common.daos.IntegrationEntityDAO;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
+import org.libreplan.business.email.daos.IEmailNotificationDAO;
import org.libreplan.business.expensesheet.daos.IExpenseSheetLineDAO;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.orders.entities.Order;
@@ -46,6 +47,7 @@ import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.SchedulingDataForVersion;
import org.libreplan.business.orders.entities.TaskSource;
import org.libreplan.business.planner.daos.ITaskSourceDAO;
+import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.templates.entities.OrderElementTemplate;
import org.libreplan.business.workingday.EffortDuration;
@@ -84,6 +86,9 @@ public class OrderElementDAO extends IntegrationEntityDAO implemen
@Autowired
private ITaskSourceDAO taskSourceDAO;
+ @Autowired
+ private IEmailNotificationDAO emailNotificationDAO;
+
@Override
public List findWithoutParent() {
return getSession()
@@ -142,6 +147,9 @@ public class OrderElementDAO extends IntegrationEntityDAO implemen
@Override
public void remove(Long id) throws InstanceNotFoundException {
OrderElement orderElement = find(id);
+
+ removeNotifications(orderElement);
+
removeTaskSourcesFor(this.taskSourceDAO, orderElement);
for (WorkReport each : getWorkReportsPointingTo(orderElement)) {
@@ -151,6 +159,17 @@ public class OrderElementDAO extends IntegrationEntityDAO implemen
super.remove(id);
}
+ public void removeNotifications(OrderElement orderElement) {
+
+ List allVersions = orderElement.getSchedulingDataForVersionFromBottomToTop();
+ for (TaskSource each : taskSourcesFrom(allVersions)) {
+ TaskElement taskElement = each.getTask();
+ if ( taskElement != null) {
+ emailNotificationDAO.deleteByTask(taskElement);
+ }
+ }
+ }
+
public static void removeTaskSourcesFor(ITaskSourceDAO taskSourceDAO, OrderElement orderElement)
throws InstanceNotFoundException {
diff --git a/libreplan-business/src/main/java/org/libreplan/business/planner/entities/TaskElement.java b/libreplan-business/src/main/java/org/libreplan/business/planner/entities/TaskElement.java
index 249c8b6c0..d7b1d444e 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/planner/entities/TaskElement.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/planner/entities/TaskElement.java
@@ -243,7 +243,8 @@ public abstract class TaskElement extends BaseEntity {
}
public String getProjectCode() {
- return getOrderElement().getOrder().getCode();
+ //then get the top level project code
+ return getTopMost().getOrderElement().getOrder().getCode();
}
public void setName(String name) {
diff --git a/libreplan-business/src/main/java/org/libreplan/business/resources/daos/IWorkerDAO.java b/libreplan-business/src/main/java/org/libreplan/business/resources/daos/IWorkerDAO.java
index 913ed8702..65208663b 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/resources/daos/IWorkerDAO.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/resources/daos/IWorkerDAO.java
@@ -122,8 +122,11 @@ public interface IWorkerDAO extends IIntegrationEntityDAO {
public List findByFirstNameSecondNameAnotherTransaction(
String firstname, String secondname);
+ public Worker getCurrentWorker(Long resourceID);
+
/**
* Return the list of {@link Worker Workers} bound to any {@link User}.
*/
List getBound();
+
}
diff --git a/libreplan-business/src/main/java/org/libreplan/business/resources/daos/WorkerDAO.java b/libreplan-business/src/main/java/org/libreplan/business/resources/daos/WorkerDAO.java
index 341fb01e6..0162f94f2 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/resources/daos/WorkerDAO.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/resources/daos/WorkerDAO.java
@@ -198,4 +198,18 @@ public class WorkerDAO extends IntegrationEntityDAO
criteria.add(Restrictions.isNotNull("user"));
return criteria.list();
}
-}
\ No newline at end of file
+
+ @Override
+ @Transactional(readOnly = true)
+ public Worker getCurrentWorker(Long resourceID) {
+ List workerList = getWorkers();
+
+ for (Worker worker : workerList) {
+ if (worker.getId().equals(resourceID)) {
+ return worker;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/libreplan-business/src/main/java/org/libreplan/business/users/daos/OrderAuthorizationDAO.java b/libreplan-business/src/main/java/org/libreplan/business/users/daos/OrderAuthorizationDAO.java
index 65918cd37..e2a5aaa29 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/users/daos/OrderAuthorizationDAO.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/users/daos/OrderAuthorizationDAO.java
@@ -26,6 +26,7 @@ import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
+import org.libreplan.business.common.Registry;
import org.libreplan.business.common.daos.GenericDAOHibernate;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.users.entities.OrderAuthorization;
@@ -68,6 +69,7 @@ public class OrderAuthorizationDAO extends GenericDAOHibernate listByUserAndItsProfiles(User user) {
List list = new ArrayList();
list.addAll(listByUser(user));
+ Registry.getUserDAO().reattach(user);
for(Profile profile : user.getProfiles()) {
list.addAll(listByProfile(profile));
}
@@ -79,6 +81,7 @@ public class OrderAuthorizationDAO extends GenericDAOHibernate listByOrderUserAndItsProfiles(Order order, User user) {
List list = new ArrayList();
list.addAll(listByOrderAndUser(order,user));
+ Registry.getUserDAO().reattach(user);
for(Profile profile : user.getProfiles()) {
list.addAll(listByOrderAndProfile(order, profile));
}
diff --git a/libreplan-business/src/main/java/org/libreplan/business/users/entities/User.java b/libreplan-business/src/main/java/org/libreplan/business/users/entities/User.java
index 277d506b2..28b88d328 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/users/entities/User.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/users/entities/User.java
@@ -93,12 +93,24 @@ public class User extends BaseEntity implements IHumanIdentifiable{
private Integer projectsFilterPeriodTo;
+ private Boolean projectsFilterFinishedOn = false;
+
private Criterion resourcesLoadFilterCriterion = null;
private Integer resourcesLoadFilterPeriodSince;
private Integer resourcesLoadFilterPeriodTo;
+ private boolean showResourcesOn = false;
+
+ private boolean showAdvancesOn = false;
+
+ private boolean showReportedHoursOn = false;
+
+ private boolean showLabelsOn = false;
+
+ private boolean showMoneyCostBarOn = false;
+
/**
* Necessary for Hibernate. Please, do not call it.
*/
@@ -434,6 +446,14 @@ public class User extends BaseEntity implements IHumanIdentifiable{
projectsFilterPeriodTo = period;
}
+ public boolean isProjectsFilterFinishedOn() {
+ return projectsFilterFinishedOn;
+ }
+
+ public void setProjectsFilterFinishedOn(boolean projectsFilterFinishedOn) {
+ this.projectsFilterFinishedOn = projectsFilterFinishedOn;
+ }
+
public Integer getResourcesLoadFilterPeriodSince() {
return resourcesLoadFilterPeriodSince;
}
@@ -450,4 +470,44 @@ public class User extends BaseEntity implements IHumanIdentifiable{
resourcesLoadFilterPeriodTo = period;
}
+ public boolean isShowResourcesOn() {
+ return showResourcesOn;
+ }
+
+ public void setShowResourcesOn(boolean showResourcesOn) {
+ this.showResourcesOn = showResourcesOn;
+ }
+
+ public boolean isShowAdvancesOn() {
+ return showAdvancesOn;
+ }
+
+ public void setShowAdvancesOn(boolean showAdvancesOn) {
+ this.showAdvancesOn = showAdvancesOn;
+ }
+
+ public boolean isShowReportedHoursOn() {
+ return showReportedHoursOn;
+ }
+
+ public void setShowReportedHoursOn(boolean showReportedHoursOn) {
+ this.showReportedHoursOn = showReportedHoursOn;
+ }
+
+ public boolean isShowLabelsOn() {
+ return showLabelsOn;
+ }
+
+ public void setShowLabelsOn(boolean showLabelsOn) {
+ this.showLabelsOn = showLabelsOn;
+ }
+
+ public boolean isShowMoneyCostBarOn() {
+ return showMoneyCostBarOn;
+ }
+
+ public void setShowMoneyCostBarOn(boolean showMoneyCostBarOn) {
+ this.showMoneyCostBarOn = showMoneyCostBarOn;
+ }
+
}
diff --git a/libreplan-business/src/main/resources/db.changelog-1.6.xml b/libreplan-business/src/main/resources/db.changelog-1.6.xml
new file mode 100644
index 000000000..a35ea404a
--- /dev/null
+++ b/libreplan-business/src/main/resources/db.changelog-1.6.xml
@@ -0,0 +1,109 @@
+
+
+
+
+ Add columns to store user default setting of show/hide reported hours button
+
+
+
+
+
+
+ Add columns to store user default setting of show/hide resources button
+
+
+
+
+
+
+ Add columns to store user default setting of show/hide advances button
+
+
+
+
+
+
+ Add columns to store user default setting of show/hide labels button
+
+
+
+
+
+
+ Add columns to store user default setting of show/hide moneycostbar button
+
+
+
+
+
+
+ Add columns to store user default setting of filter finished projects in views
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libreplan-business/src/main/resources/db.changelog.xml b/libreplan-business/src/main/resources/db.changelog.xml
index 4f07060cb..99bc85a99 100644
--- a/libreplan-business/src/main/resources/db.changelog.xml
+++ b/libreplan-business/src/main/resources/db.changelog.xml
@@ -12,4 +12,5 @@
+
diff --git a/libreplan-business/src/main/resources/org/libreplan/business/orders/entities/Orders.hbm.xml b/libreplan-business/src/main/resources/org/libreplan/business/orders/entities/Orders.hbm.xml
index c4f710cb9..a0e809b57 100644
--- a/libreplan-business/src/main/resources/org/libreplan/business/orders/entities/Orders.hbm.xml
+++ b/libreplan-business/src/main/resources/org/libreplan/business/orders/entities/Orders.hbm.xml
@@ -40,7 +40,7 @@
-
+
@@ -86,7 +86,7 @@
-
+
@@ -216,7 +216,7 @@
-
+
diff --git a/libreplan-business/src/main/resources/org/libreplan/business/requirements/entities/Requirements.hbm.xml b/libreplan-business/src/main/resources/org/libreplan/business/requirements/entities/Requirements.hbm.xml
index 38cae2b0c..42b5040ce 100644
--- a/libreplan-business/src/main/resources/org/libreplan/business/requirements/entities/Requirements.hbm.xml
+++ b/libreplan-business/src/main/resources/org/libreplan/business/requirements/entities/Requirements.hbm.xml
@@ -35,7 +35,7 @@
+ name="criterion" lazy="false"/>
diff --git a/libreplan-business/src/main/resources/org/libreplan/business/users/entities/Users.hbm.xml b/libreplan-business/src/main/resources/org/libreplan/business/users/entities/Users.hbm.xml
index 3c90d5507..c0a889026 100644
--- a/libreplan-business/src/main/resources/org/libreplan/business/users/entities/Users.hbm.xml
+++ b/libreplan-business/src/main/resources/org/libreplan/business/users/entities/Users.hbm.xml
@@ -53,7 +53,7 @@
-
+
@@ -66,10 +66,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/libreplan-business/src/test/java/org/libreplan/business/test/planner/daos/TaskElementDAOTest.java b/libreplan-business/src/test/java/org/libreplan/business/test/planner/daos/TaskElementDAOTest.java
index d4b5a3af7..ccb873460 100644
--- a/libreplan-business/src/test/java/org/libreplan/business/test/planner/daos/TaskElementDAOTest.java
+++ b/libreplan-business/src/test/java/org/libreplan/business/test/planner/daos/TaskElementDAOTest.java
@@ -303,6 +303,42 @@ public class TaskElementDAOTest {
assertThat(child.getParent(), equalTo(reloaded));
}
+ @Test
+ @Transactional
+ public void theTopMostPropertyIsTheToplevelTask() {
+ TaskGroup taskGroup = createValidTaskGroup();
+ TaskElement taskElement = createValidTask();
+ taskGroup.addTaskElement(taskElement);
+ taskElementDAO.save(taskGroup);
+
+ TaskGroup taskGroup2 = createValidTaskGroup();
+ TaskElement taskElement2 = createValidTask();
+ taskGroup2.addTaskElement(taskElement2);
+ taskElementDAO.save(taskGroup2);
+
+ taskGroup.addTaskElement(taskGroup2);
+ taskElementDAO.save(taskGroup);
+
+ flushAndEvict(taskGroup);
+ flushAndEvict(taskGroup2);
+
+ TaskElement reloaded;
+ try {
+ reloaded = taskElementDAO.find(taskGroup.getId());
+ } catch (InstanceNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ List children = reloaded.getChildren();
+
+ for (TaskElement child : children) {
+ if (child instanceof TaskGroup) {
+ TaskElement child2 = child.getChildren().get(0);
+ assertThat(child2.getTopMost(), equalTo(reloaded));
+ }
+ }
+ }
+
@Test
@Transactional
public void savingGroupSavesAssociatedTaskElements() {
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerManager.java b/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerManager.java
index 5e758e34f..2d65379db 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerManager.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerManager.java
@@ -150,7 +150,7 @@ public class SchedulerManager implements ISchedulerManager {
String triggerName = jobSchedulerConfiguration.getJobName() + TRIGGER_SUFFIX;
String triggerGroup = jobSchedulerConfiguration.getJobGroup() + TRIGGER_SUFFIX;
- CronTriggerFactoryBean trigger = getTriggerBean(triggerName, triggerGroup);
+ CronTrigger trigger = getTriggerBean(triggerName, triggerGroup);
if ( trigger == null ) {
LOG.warn("Trigger not found");
@@ -164,7 +164,7 @@ public class SchedulerManager implements ISchedulerManager {
}
// deleteJob doesn't work using unscheduleJob
- this.scheduler.unscheduleJob(trigger.getObject().getKey());
+ this.scheduler.unscheduleJob(trigger.getKey());
}
/**
@@ -230,7 +230,7 @@ public class SchedulerManager implements ISchedulerManager {
* create it
*/
private CronTriggerFactoryBean createCronTriggerBean(JobSchedulerConfiguration jobSchedulerConfiguration) {
- CronTriggerFactoryBean cronTriggerBean = new CronTriggerFactoryBean();
+ final CronTriggerFactoryBean cronTriggerBean = new CronTriggerFactoryBean();
cronTriggerBean.setName(jobSchedulerConfiguration.getJobName() + TRIGGER_SUFFIX);
cronTriggerBean.setGroup(jobSchedulerConfiguration.getJobGroup() + TRIGGER_SUFFIX);
@@ -238,9 +238,8 @@ public class SchedulerManager implements ISchedulerManager {
cronTriggerBean.setCronExpression(
String.valueOf(new CronExpression(jobSchedulerConfiguration.getCronExpression())));
- cronTriggerBean.setName(jobSchedulerConfiguration.getJobName());
- cronTriggerBean.setGroup(jobSchedulerConfiguration.getJobGroup());
-
+ cronTriggerBean.afterPropertiesSet();
+
return cronTriggerBean;
} catch (ParseException e) {
@@ -259,7 +258,7 @@ public class SchedulerManager implements ISchedulerManager {
* @return the created JobDetailFactoryBean or null if unable to it
*/
private JobDetailFactoryBean createJobDetailBean(JobSchedulerConfiguration jobSchedulerConfiguration) {
- JobDetailFactoryBean jobDetailBean = new JobDetailFactoryBean();
+ final JobDetailFactoryBean jobDetailBean = new JobDetailFactoryBean();
Class> jobClass = getJobClass(jobSchedulerConfiguration.getJobClassName());
if ( jobClass == null ) {
@@ -274,6 +273,8 @@ public class SchedulerManager implements ISchedulerManager {
jobDataAsMap.put("applicationContext", applicationContext);
jobDetailBean.setJobDataAsMap(jobDataAsMap);
+ jobDetailBean.afterPropertiesSet();
+
return jobDetailBean;
}
@@ -322,9 +323,9 @@ public class SchedulerManager implements ISchedulerManager {
* the trigger group
* @return CronTriggerFactoryBean if found, otherwise null
*/
- private CronTriggerFactoryBean getTriggerBean(String triggerName, String triggerGroup) {
+ private CronTrigger getTriggerBean(String triggerName, String triggerGroup) {
try {
- return (CronTriggerFactoryBean) this.scheduler.getTrigger(TriggerKey.triggerKey(triggerName, triggerGroup));
+ return (CronTrigger) this.scheduler.getTrigger(TriggerKey.triggerKey(triggerName, triggerGroup));
} catch (SchedulerException e) {
LOG.error("Unable to get job trigger", e);
}
@@ -333,3 +334,4 @@ public class SchedulerManager implements ISchedulerManager {
}
}
+
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/ComposeMessage.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/ComposeMessage.java
index 55045847a..31897184c 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/ComposeMessage.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/ComposeMessage.java
@@ -19,12 +19,15 @@
package org.libreplan.importers.notifications;
+//import javax.annotation.Resource;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.libreplan.business.common.entities.ConnectorProperty;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplate;
import org.libreplan.business.email.entities.EmailTemplateEnum;
+import org.libreplan.business.resources.daos.IWorkerDAO;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.settings.entities.Language;
@@ -33,9 +36,20 @@ import org.libreplan.web.email.IEmailTemplateModel;
import org.libreplan.web.planner.tabs.MultipleTabsPlannerController;
import org.libreplan.web.resources.worker.IWorkerModel;
import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.beans.factory.annotation;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Configuration;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.AbstractEnvironment;
+
+import org.springframework.web.context.WebApplicationContext;
+
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
+import javax.servlet.ServletContext;
+
import org.zkoss.zul.Messagebox;
import javax.mail.Message;
@@ -45,243 +59,283 @@ import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.Query;
+import javax.management.ReflectionException;
+import javax.naming.InitialContext;
+import javax.naming.Context;
+
import java.util.List;
import java.util.Locale;
import java.util.Properties;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.lang.String;
+import java.lang.management.ManagementFactory;
+import java.io.File;
+import java.net.InetAddress;
+import java.net.URLDecoder;
+import java.net.UnknownHostException;
+import java.io.UnsupportedEncodingException;
+
+import org.springframework.core.env.MapPropertySource;
import static org.libreplan.web.I18nHelper._;
/**
- * Sends E-mail to users with data that storing in notification_queue table
- * and that are treat to incoming {@link EmailNotification}.
+ * Sends E-mail to users with data that storing in notification_queue table and
+ * that are treat to incoming {@link EmailNotification}.
*
* @author Vova Perebykivskyi
*/
+@Configuration
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ComposeMessage {
- @Autowired
- private IWorkerModel workerModel;
+ @Autowired
+ private IWorkerDAO workerDAO;
- @Autowired
- private IEmailTemplateModel emailTemplateModel;
+ @Autowired
+ private IEmailTemplateModel emailTemplateModel;
- @Autowired
- private EmailConnectionValidator emailConnectionValidator;
+ @Autowired
+ private EmailConnectionValidator emailConnectionValidator;
- private String protocol;
+ private String protocol;
- private String host;
+ private String host;
- private String port;
+ private String port;
- private String sender;
+ private String sender;
- private String usrnme;
+ private String usrnme;
- private String psswrd;
+ private String psswrd;
- private Properties properties;
+ private Properties properties;
- private static final Log LOG = LogFactory.getLog(ComposeMessage.class);
+ private static final Log LOG = LogFactory.getLog(ComposeMessage.class);
+ public boolean composeMessageForUser(EmailNotification notification) {
+ // Gather data about EmailTemplate needs to be used
+ Resource resource = notification.getResource();
+ EmailTemplateEnum type = notification.getType();
+ Locale locale;
+ Worker currentWorker = workerDAO.getCurrentWorker(resource.getId());
- public boolean composeMessageForUser(EmailNotification notification) {
- // Gather data about EmailTemplate needs to be used
- Resource resource = notification.getResource();
- EmailTemplateEnum type = notification.getType();
- Locale locale;
- Worker currentWorker = getCurrentWorker(resource.getId());
+ UserRole currentUserRole = getCurrentUserRole(notification.getType());
- UserRole currentUserRole = getCurrentUserRole(notification.getType());
+ if (currentWorker != null && (currentWorker.getUser() != null) && currentWorker.getUser().isInRole(currentUserRole)) {
+ if (currentWorker.getUser().getApplicationLanguage().equals(Language.BROWSER_LANGUAGE)) {
+ locale = new Locale(System.getProperty("user.language"));
+ } else {
+ locale = new Locale(currentWorker.getUser().getApplicationLanguage().getLocale().getLanguage());
+ }
- if (currentWorker != null && currentWorker.getUser().isInRole(currentUserRole)) {
- if (currentWorker.getUser().getApplicationLanguage().equals(Language.BROWSER_LANGUAGE)) {
- locale = new Locale(System.getProperty("user.language"));
- } else {
- locale = new Locale(currentWorker.getUser().getApplicationLanguage().getLocale().getLanguage());
- }
+ EmailTemplate currentEmailTemplate = findCurrentEmailTemplate(type, locale);
- EmailTemplate currentEmailTemplate = findCurrentEmailTemplate(type, locale);
+ if (currentEmailTemplate == null) {
+ LOG.error("Email template is null");
+ return false;
+ }
- if (currentEmailTemplate == null) {
- LOG.error("Email template is null");
- return false;
- }
+ // Modify text that will be composed
+ String text = currentEmailTemplate.getContent();
+ text = replaceKeywords(text, currentWorker, notification);
- // Modify text that will be composed
- String text = currentEmailTemplate.getContent();
- text = replaceKeywords(text, currentWorker, notification);
+ String receiver = currentWorker.getUser().getEmail();
- String receiver = currentWorker.getUser().getEmail();
+ setupConnectionProperties();
- setupConnectionProperties();
+ final String username = usrnme;
+ final String password = psswrd;
- final String username = usrnme;
- final String password = psswrd;
+ // It is very important to use Session.getInstance() instead of
+ // Session.getDefaultInstance()
+ Session mailSession = Session.getInstance(properties, new javax.mail.Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
- // It is very important to use Session.getInstance() instead of Session.getDefaultInstance()
- Session mailSession = Session.getInstance(properties, new javax.mail.Authenticator() {
- @Override
- protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(username, password);
- }
- });
+ // Send message
+ try {
+ MimeMessage message = new MimeMessage(mailSession);
- // Send message
- try {
- MimeMessage message = new MimeMessage(mailSession);
+ message.setFrom(new InternetAddress(sender));
+ message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver));
- message.setFrom(new InternetAddress(sender));
- message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver));
+ String subject = currentEmailTemplate.getSubject();
+ message.setSubject(subject);
- String subject = currentEmailTemplate.getSubject();
- message.setSubject(subject);
+ message.setText(text);
- message.setText(text);
+ Transport.send(message);
- Transport.send(message);
+ return true;
- return true;
+ } catch (MessagingException e) {
+ throw new RuntimeException(e);
+ } catch (NullPointerException e) {
+ if (receiver == null) {
+ Messagebox.show(_(currentWorker.getUser().getLoginName() + " - this user have not filled E-mail"),
+ _("Error"), Messagebox.OK, Messagebox.ERROR);
+ }
+ }
+ }
+ return false;
+ }
- } catch (MessagingException e) {
- throw new RuntimeException(e);
- } catch (NullPointerException e) {
- if (receiver == null) {
- Messagebox.show(
- _(currentWorker.getUser().getLoginName() + " - this user have not filled E-mail"),
- _("Error"), Messagebox.OK, Messagebox.ERROR);
- }
- }
- }
- return false;
- }
+ private EmailTemplate findCurrentEmailTemplate(EmailTemplateEnum templateEnum, Locale locale) {
+ List emailTemplates;
+ emailTemplates = emailTemplateModel.getAll();
- private Worker getCurrentWorker(Long resourceID){
- List workerList = workerModel.getWorkers();
+ for (EmailTemplate item : emailTemplates) {
+ if (item.getType().equals(templateEnum) && item.getLanguage().getLocale().equals(locale)) {
+ return item;
+ }
- for (Worker aWorkerList : workerList) {
- if (aWorkerList.getId().equals(resourceID)) {
- return aWorkerList;
- }
- }
+ }
- return null;
- }
+ return null;
+ }
- private EmailTemplate findCurrentEmailTemplate(EmailTemplateEnum templateEnum, Locale locale) {
- List emailTemplates;
- emailTemplates = emailTemplateModel.getAll();
+ private String replaceKeywords(String text, Worker currentWorker, EmailNotification notification) {
+ String newText = text;
- for (EmailTemplate item : emailTemplates) {
- if ( item.getType().equals(templateEnum) && item.getLanguage().getLocale().equals(locale) ) {
- return item;
- }
+ // replace {url} in all messages even timesheet reminder emails
+ // as a link may be helpful
+ newText = newText.replaceAll("\\{url\\}", MultipleTabsPlannerController.WELCOME_URL);
+ if (notification.getType().equals(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET)) {
+ // It is because there is no other data for
+ // EmailNotification of TEMPLATE_ENTER_DATA_IN_TIMESHEET
+ // notification type
+ newText = newText.replaceAll("\\{resource\\}", notification.getResource().getName());
+ } else {
+ newText = newText.replaceAll("\\{username\\}", currentWorker.getUser().getLoginName());
+ newText = newText.replaceAll("\\{firstname\\}", currentWorker.getUser().getFirstName());
+ newText = newText.replaceAll("\\{lastname\\}", currentWorker.getUser().getLastName());
+ newText = newText.replaceAll("\\{project\\}", notification.getProject().getName());
+ newText = newText.replaceAll("\\{resource\\}", notification.getResource().getName());
+ newText = newText.replaceAll("\\{task\\}", notification.getTask().getName());
+ newText = newText.replaceAll("\\{projecturl\\}", MultipleTabsPlannerController.WELCOME_URL+ ";order=" + notification.getProject().getProjectCode());
+ }
+ return newText;
+ }
- }
+ List getEndPoints() throws MalformedObjectNameException, NullPointerException, UnknownHostException,
+ AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException {
+
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ Set objs = mbs.queryNames(new ObjectName("*:type=Connector,*"),
+ Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
+
+ String hostname = InetAddress.getLocalHost().getHostName();
+
+ InetAddress[] addresses = InetAddress.getAllByName(hostname);
+
+ ArrayList endPoints = new ArrayList();
+ for (Iterator i = objs.iterator(); i.hasNext();) {
+ ObjectName obj = i.next();
+ String scheme = mbs.getAttribute(obj, "scheme").toString();
+ String port = obj.getKeyProperty("port");
+ for (InetAddress addr : addresses) {
+ String host = addr.getHostAddress();
+ String ep = scheme + "://" + host + ":" + port;
+ endPoints.add(ep);
+ }
+ }
+ return endPoints;
+ }
- return null;
- }
+ private void setupConnectionProperties() {
+ List emailConnectorProperties = emailConnectionValidator.getEmailConnectorProperties();
- private String replaceKeywords(String text, Worker currentWorker, EmailNotification notification) {
- String newText = text;
+ for (int i = 0; i < emailConnectorProperties.size(); i++) {
+ switch (i) {
- if ( notification.getType().equals(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET) ) {
- // It is because there is no other data for
- // EmailNotification of TEMPLATE_ENTER_DATA_IN_TIMESHEET notification type
- newText = newText.replaceAll("\\{resource\\}", notification.getResource().getName());
- }
- else {
- newText = newText.replaceAll("\\{username\\}", currentWorker.getUser().getLoginName());
- newText = newText.replaceAll("\\{firstname\\}", currentWorker.getUser().getFirstName());
- newText = newText.replaceAll("\\{lastname\\}", currentWorker.getUser().getLastName());
- newText = newText.replaceAll("\\{project\\}", notification.getProject().getName());
- newText = newText.replaceAll("\\{resource\\}", notification.getResource().getName());
- newText = newText.replaceAll("\\{task\\}", notification.getTask().getName());
- newText = newText.replaceAll("\\{url\\}", MultipleTabsPlannerController.WELCOME_URL);
- }
- return newText;
- }
+ case 1:
+ protocol = emailConnectorProperties.get(1).getValue();
+ break;
- private void setupConnectionProperties() {
- List emailConnectorProperties = emailConnectionValidator.getEmailConnectorProperties();
+ case 2:
+ host = emailConnectorProperties.get(2).getValue();
+ break;
- for (int i = 0; i < emailConnectorProperties.size(); i++) {
- switch (i) {
+ case 3:
+ port = emailConnectorProperties.get(3).getValue();
+ break;
- case 1:
- protocol = emailConnectorProperties.get(1).getValue();
- break;
+ case 4:
+ sender = emailConnectorProperties.get(4).getValue();
+ break;
- case 2:
- host = emailConnectorProperties.get(2).getValue();
- break;
+ case 5:
+ usrnme = emailConnectorProperties.get(5).getValue();
+ break;
- case 3:
- port = emailConnectorProperties.get(3).getValue();
- break;
+ case 6:
+ psswrd = emailConnectorProperties.get(6).getValue();
+ break;
- case 4:
- sender = emailConnectorProperties.get(4).getValue();
- break;
+ default:
+ break;
- case 5:
- usrnme = emailConnectorProperties.get(5).getValue();
- break;
+ }
+ }
- case 6:
- psswrd = emailConnectorProperties.get(6).getValue();
- break;
+ properties = new Properties();
- default:
- break;
+ if ("STARTTLS".equals(protocol)) {
+ properties.put("mail.smtp.starttls.enable", "true");
+ properties.put("mail.smtp.host", host);
+ properties.put("mail.smtp.socketFactory.port", port);
+ properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+ properties.put("mail.smtp.auth", "true");
+ properties.put("mail.smtp.port", port);
+ } else if ("SMTP".equals(protocol)) {
+ properties.put("mail.smtp.host", host);
+ properties.put("mail.smtp.port", port);
+ }
+ }
- }
- }
+ private UserRole getCurrentUserRole(EmailTemplateEnum type) {
+ switch (type) {
- properties = new Properties();
+ case TEMPLATE_TASK_ASSIGNED_TO_RESOURCE:
+ return UserRole.ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE;
- if ( "STARTTLS".equals(protocol) ) {
- properties.put("mail.smtp.starttls.enable", "true");
- properties.put("mail.smtp.host", host);
- properties.put("mail.smtp.socketFactory.port", port);
- properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
- properties.put("mail.smtp.auth", "true");
- properties.put("mail.smtp.port", port);
- }
- else if ( "SMTP".equals(protocol) ) {
- properties.put("mail.smtp.host", host);
- properties.put("mail.smtp.port", port);
- }
- }
+ case TEMPLATE_RESOURCE_REMOVED_FROM_TASK:
+ return UserRole.ROLE_EMAIL_RESOURCE_REMOVED_FROM_TASK;
- private UserRole getCurrentUserRole(EmailTemplateEnum type) {
- switch (type) {
+ case TEMPLATE_MILESTONE_REACHED:
+ return UserRole.ROLE_EMAIL_MILESTONE_REACHED;
- case TEMPLATE_TASK_ASSIGNED_TO_RESOURCE:
- return UserRole.ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE;
+ case TEMPLATE_TODAY_TASK_SHOULD_START:
+ return UserRole.ROLE_EMAIL_TASK_SHOULD_START;
- case TEMPLATE_RESOURCE_REMOVED_FROM_TASK:
- return UserRole.ROLE_EMAIL_RESOURCE_REMOVED_FROM_TASK;
+ case TEMPLATE_TODAY_TASK_SHOULD_FINISH:
+ return UserRole.ROLE_EMAIL_TASK_SHOULD_FINISH;
- case TEMPLATE_MILESTONE_REACHED:
- return UserRole.ROLE_EMAIL_MILESTONE_REACHED;
-
- case TEMPLATE_TODAY_TASK_SHOULD_START:
- return UserRole.ROLE_EMAIL_TASK_SHOULD_START;
-
- case TEMPLATE_TODAY_TASK_SHOULD_FINISH:
- return UserRole.ROLE_EMAIL_TASK_SHOULD_FINISH;
-
- case TEMPLATE_ENTER_DATA_IN_TIMESHEET:
- return UserRole.ROLE_EMAIL_TIMESHEET_DATA_MISSING;
-
- default:
- /* There is no other template */
- return null;
- }
- }
+ case TEMPLATE_ENTER_DATA_IN_TIMESHEET:
+ return UserRole.ROLE_EMAIL_TIMESHEET_DATA_MISSING;
+ default:
+ /* There is no other template */
+ return null;
+ }
+ }
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnMilestoneReachedJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnMilestoneReachedJob.java
index 58090d415..03016788e 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnMilestoneReachedJob.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnMilestoneReachedJob.java
@@ -43,7 +43,7 @@ public class SendEmailOnMilestoneReachedJob extends QuartzJobBean {
(ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob milestoneReached =
- (SendEmailOnMilestoneReached) applicationContext.getBean("SendEmailOnMilestoneReached");
+ (IEmailNotificationJob) applicationContext.getBean("sendEmailOnMilestoneReached");
milestoneReached.sendEmail();
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnResourceRemovedFromTaskJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnResourceRemovedFromTaskJob.java
index 295f44084..797ead622 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnResourceRemovedFromTaskJob.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnResourceRemovedFromTaskJob.java
@@ -42,7 +42,7 @@ public class SendEmailOnResourceRemovedFromTaskJob extends QuartzJobBean {
(ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob resourceRemovedFromTask =
- (IEmailNotificationJob) applicationContext.getBean("SendEmailOnResourceRemovedFromTask");
+ (IEmailNotificationJob) applicationContext.getBean("sendEmailOnResourceRemovedFromTask");
resourceRemovedFromTask.sendEmail();
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskAssignedToResourceJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskAssignedToResourceJob.java
index 369539c44..9cdd652b3 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskAssignedToResourceJob.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskAssignedToResourceJob.java
@@ -43,7 +43,7 @@ public class SendEmailOnTaskAssignedToResourceJob extends QuartzJobBean {
(ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob taskAssignedToResource =
- (IEmailNotificationJob) applicationContext.getBean("SendEmailOnTaskAssignedToResource");
+ (IEmailNotificationJob) applicationContext.getBean("sendEmailOnTaskAssignedToResource");
taskAssignedToResource.sendEmail();
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskShouldFinishJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskShouldFinishJob.java
index 587aa3557..469823755 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskShouldFinishJob.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskShouldFinishJob.java
@@ -43,7 +43,7 @@ public class SendEmailOnTaskShouldFinishJob extends QuartzJobBean {
(ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob taskShouldFinish =
- (IEmailNotificationJob) applicationContext.getBean("SendEmailOnTaskShouldFinish");
+ (IEmailNotificationJob) applicationContext.getBean("sendEmailOnTaskShouldFinish");
taskShouldFinish.sendEmail();
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskShouldStartJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskShouldStartJob.java
index b7b7b8407..dfe11862a 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskShouldStartJob.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTaskShouldStartJob.java
@@ -43,7 +43,7 @@ public class SendEmailOnTaskShouldStartJob extends QuartzJobBean {
context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob taskShouldStart =
- (IEmailNotificationJob) applicationContext.getBean("SendEmailOnTaskShouldStart");
+ (IEmailNotificationJob) applicationContext.getBean("sendEmailOnTaskShouldStart");
taskShouldStart.sendEmail();
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTimesheetDataMissingJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTimesheetDataMissingJob.java
index 887a891b2..2ee844356 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTimesheetDataMissingJob.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/jobs/SendEmailOnTimesheetDataMissingJob.java
@@ -42,7 +42,7 @@ public class SendEmailOnTimesheetDataMissingJob extends QuartzJobBean {
(ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob timesheetMissing =
- (IEmailNotificationJob) applicationContext.getBean("SendEmailOnTimesheetDataMissing");
+ (IEmailNotificationJob) applicationContext.getBean("sendEmailOnTimesheetDataMissing");
timesheetMissing.sendEmail();
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnMilestoneReached.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnMilestoneReached.java
index b27fbecf3..ba090f3a8 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnMilestoneReached.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnMilestoneReached.java
@@ -112,32 +112,30 @@ public class SendEmailOnMilestoneReached implements IEmailNotificationJob {
}
private void sendEmailNotificationToManager(TaskElement item) {
- emailNotificationModel.setNewObject();
- emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_MILESTONE_REACHED);
- emailNotificationModel.setUpdated(new Date());
-
String responsible = "";
- if ( item.getParent().getOrderElement().getOrder().getResponsible() != null ) {
- responsible = item.getParent().getOrderElement().getOrder().getResponsible();
+ if ( item.getTopMost().getOrderElement().getOrder().getResponsible() != null ) {
+ responsible = item.getTopMost().getOrderElement().getOrder().getResponsible();
}
User user = null;
try {
- // FIXME: Code below can produce NullPointerException if "Responsible" field is not set in Project Details -> General data
user = userDAO.findByLoginName(responsible);
- } catch (InstanceNotFoundException e) {
- e.printStackTrace();
- }
- boolean userHasNeededRoles =
+ boolean userHasNeededRoles =
user.isInRole(UserRole.ROLE_SUPERUSER) || user.isInRole(UserRole.ROLE_EMAIL_MILESTONE_REACHED);
- if ( user.getWorker() != null && userHasNeededRoles ) {
- emailNotificationModel.setResource(user.getWorker());
- emailNotificationModel.setTask(item);
- emailNotificationModel.setProject(item.getParent());
- emailNotificationModel.confirmSave();
- }
+ if ( user.getWorker() != null && userHasNeededRoles ) {
+ emailNotificationModel.setNewObject();
+ emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_MILESTONE_REACHED);
+ emailNotificationModel.setUpdated(new Date());
+ emailNotificationModel.setResource(user.getWorker());
+ emailNotificationModel.setTask(item);
+ emailNotificationModel.setProject(item.getTopMost());
+ emailNotificationModel.confirmSave();
+ }
+ } catch (InstanceNotFoundException e) {
+ // do nothing, responsible user is either blank or free text in order
+ }
}
public void checkMilestoneDate() {
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTaskShouldFinish.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTaskShouldFinish.java
index de57411a7..f06fee3a0 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTaskShouldFinish.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTaskShouldFinish.java
@@ -28,11 +28,15 @@ import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.planner.daos.ITaskElementDAO;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.TaskElement;
+import org.libreplan.business.resources.daos.IWorkerDAO;
import org.libreplan.business.resources.entities.Resource;
+import org.libreplan.business.resources.entities.Worker;
+import org.libreplan.business.users.entities.UserRole;
import org.libreplan.importers.notifications.ComposeMessage;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.email.IEmailNotificationModel;
+import org.libreplan.web.resources.worker.IWorkerModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
@@ -68,6 +72,9 @@ public class SendEmailOnTaskShouldFinish implements IEmailNotificationJob {
@Autowired
private EmailConnectionValidator emailConnectionValidator;
+ @Autowired
+ private IWorkerDAO workerDAO;
+
/**
* Transactional here is needed because without this annotation we are getting
* "LazyInitializationException: could not initialize proxy - no Session" error,
@@ -115,14 +122,13 @@ public class SendEmailOnTaskShouldFinish implements IEmailNotificationJob {
for (TaskElement item : tasks) {
DateTime endDate = new DateTime(item.getEndDate());
- if ( dateTimeComparator.compare(currentDate, endDate) == 0 ) {
+ if ( dateTimeComparator.compare(currentDate, endDate) == 0 && item.isLeaf() ) {
// Get all resources for current task and send them email notification
sendEmailNotificationAboutTaskShouldFinish(item);
}
}
}
-
private void sendEmailNotificationAboutTaskShouldFinish(TaskElement item){
List> resourceAllocations = new ArrayList<>(item.getAllResourceAllocations());
@@ -131,13 +137,17 @@ public class SendEmailOnTaskShouldFinish implements IEmailNotificationJob {
resources.add(allocation.getAssociatedResources().get(0));
for (Resource resourceItem : resources){
- emailNotificationModel.setNewObject();
- emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_FINISH);
- emailNotificationModel.setUpdated(new Date());
- emailNotificationModel.setResource(resourceItem);
- emailNotificationModel.setTask(item);
- emailNotificationModel.setProject(item.getParent());
- emailNotificationModel.confirmSave();
+ Worker currentWorker = workerDAO.getCurrentWorker(resourceItem.getId());
+
+ if (currentWorker != null && (currentWorker.getUser() != null) && currentWorker.getUser().isInRole(UserRole.ROLE_EMAIL_TASK_SHOULD_FINISH)) {
+ emailNotificationModel.setNewObject();
+ emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_FINISH);
+ emailNotificationModel.setUpdated(new Date());
+ emailNotificationModel.setResource(resourceItem);
+ emailNotificationModel.setTask(item);
+ emailNotificationModel.setProject(item.getTopMost());
+ emailNotificationModel.confirmSave();
+ }
}
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTaskShouldStart.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTaskShouldStart.java
index 075007d41..09ee3e2a7 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTaskShouldStart.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTaskShouldStart.java
@@ -28,16 +28,22 @@ import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.planner.daos.ITaskElementDAO;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.TaskElement;
+import org.libreplan.business.resources.daos.IWorkerDAO;
import org.libreplan.business.resources.entities.Resource;
+import org.libreplan.business.resources.entities.Worker;
+import org.libreplan.business.users.entities.User;
+import org.libreplan.business.users.entities.UserRole;
import org.libreplan.importers.notifications.ComposeMessage;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.email.IEmailNotificationModel;
+import org.libreplan.web.resources.worker.IWorkerModel;
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.springframework.transaction.annotation.Transactional;
+import org.zkoss.zkplus.spring.SpringUtil;
import java.util.ArrayList;
import java.util.Date;
@@ -68,6 +74,9 @@ public class SendEmailOnTaskShouldStart implements IEmailNotificationJob {
@Autowired
private EmailConnectionValidator emailConnectionValidator;
+ @Autowired
+ private IWorkerDAO workerDAO;
+
/**
* Transactional here is needed because without this annotation we are getting
* "LazyInitializationException: could not initialize proxy - no Session" error,
@@ -115,7 +124,7 @@ public class SendEmailOnTaskShouldStart implements IEmailNotificationJob {
for (TaskElement item : tasks) {
DateTime startDate = new DateTime(item.getStartDate());
- if ( dateTimeComparator.compare(currentDate, startDate) == 0) {
+ if ( dateTimeComparator.compare(currentDate, startDate) == 0 && item.isLeaf() ) {
// Get all resources for current task and send them email notification
sendEmailNotificationAboutTaskShouldStart(item);
}
@@ -130,13 +139,17 @@ public class SendEmailOnTaskShouldStart implements IEmailNotificationJob {
resources.add(allocation.getAssociatedResources().get(0));
for (Resource resourceItem : resources) {
- emailNotificationModel.setNewObject();
- emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START);
- emailNotificationModel.setUpdated(new Date());
- emailNotificationModel.setResource(resourceItem);
- emailNotificationModel.setTask(item);
- emailNotificationModel.setProject(item.getParent());
- emailNotificationModel.confirmSave();
+ Worker currentWorker = workerDAO.getCurrentWorker(resourceItem.getId());
+
+ if (currentWorker != null && (currentWorker.getUser() != null) && currentWorker.getUser().isInRole(UserRole.ROLE_EMAIL_TASK_SHOULD_START)) {
+ emailNotificationModel.setNewObject();
+ emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START);
+ emailNotificationModel.setUpdated(new Date());
+ emailNotificationModel.setResource(resourceItem);
+ emailNotificationModel.setTask(item);
+ emailNotificationModel.setProject(item.getTopMost());
+ emailNotificationModel.confirmSave();
+ }
}
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTimesheetDataMissing.java b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTimesheetDataMissing.java
index f2cfa0e44..09d469dca 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTimesheetDataMissing.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/importers/notifications/realization/SendEmailOnTimesheetDataMissing.java
@@ -33,6 +33,7 @@ import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.users.entities.User;
+import org.libreplan.business.users.entities.UserRole;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.business.workreports.daos.IWorkReportDAO;
@@ -159,11 +160,13 @@ public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
private void addRowsToNotificationTable(List users){
for (User user : users){
- emailNotificationModel.setNewObject();
- emailNotificationModel.setResource(user.getWorker());
- emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET);
- emailNotificationModel.setUpdated(new Date());
- emailNotificationModel.confirmSave();
+ if ( user.isInRole(UserRole.ROLE_EMAIL_TIMESHEET_DATA_MISSING) ) {
+ emailNotificationModel.setNewObject();
+ emailNotificationModel.setResource(user.getWorker());
+ emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET);
+ emailNotificationModel.setUpdated(new Date());
+ emailNotificationModel.confirmSave();
+ }
}
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java
index 22d7c2d04..32cb0c323 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/ConfigurationController.java
@@ -1577,7 +1577,7 @@ public class ConfigurationController extends GenericForwardComposer {
.getCurrentWebApplicationContext()
.getResource("/")
.getFile()
- .getPath() + "\\" + media.getName());
+ .getPath() + "/" + media.getName());
OutputStream outputStream = new FileOutputStream(fileToSave);
out = new BufferedOutputStream(outputStream);
@@ -1628,9 +1628,9 @@ public class ConfigurationController extends GenericForwardComposer {
if ( !"".equals(companyLogoURL.getValue()) ) {
((org.zkoss.zul.Image) configurationWindow.getFellow(LOGO_PREVIEW_COMPONENT)).setSrc("");
findAndRemoveLogoFromTarget(companyLogoURL.getValue());
- Util.logo = null;
}
+ Util.logo = null;
companyLogoURL.setValue("");
configurationModel.setCompanyLogoURL("");
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/FilterUtils.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/FilterUtils.java
index 17a0b0739..80403558f 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/common/FilterUtils.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/FilterUtils.java
@@ -50,6 +50,11 @@ public class FilterUtils {
return (String) Sessions.getCurrent().getAttribute("companyFilterOrderName");
}
+ public static Boolean readExcludeFinishedProjects() {
+ Boolean res = (Boolean) Sessions.getCurrent().getAttribute("companyFilterFinished");
+ return res;
+ }
+
public static List readProjectsParameters() {
return (List) Sessions.getCurrent().getAttribute("companyFilterLabel");
}
@@ -76,6 +81,15 @@ public class FilterUtils {
Sessions.getCurrent().setAttribute("companyFilterOrderName", name);
}
+ public static void writeExcludeFinishedProjects(Boolean excludeFinishedProject) {
+ Sessions.getCurrent().setAttribute("companyFilterFinished", excludeFinishedProject);
+ Sessions.getCurrent().setAttribute("companyFilterFinishedChanged", true);
+ }
+
+ public static boolean hasExcludeFinishedProjects() {
+ return Sessions.getCurrent().hasAttribute("companyFilterFinishedChanged");
+ }
+
public static void writeProjectsParameters(List parameters) {
Sessions.getCurrent().setAttribute("companyFilterLabel", parameters);
}
@@ -83,12 +97,14 @@ public class FilterUtils {
public static void writeProjectsFilter(Date startDate,
Date endDate,
List parameters,
- String projectName) {
+ String projectName,
+ Boolean excludeFinishedProject) {
writeProjectsStartDate(startDate);
writeProjectsEndDate(endDate);
writeProjectsParameters(parameters);
writeProjectsName(projectName);
+ writeExcludeFinishedProjects(excludeFinishedProject);
}
public static void writeProjectFilterChanged(boolean changed) {
@@ -159,6 +175,10 @@ public class FilterUtils {
return (String) Sessions.getCurrent().getAttribute(order.getCode() + "-tasknameFilter");
}
+ public static String readOrderStatus(Order order) {
+ return (String) Sessions.getCurrent().getAttribute(order.getCode() + "-orderStatus");
+ }
+
public static List readOrderParameters(Order order) {
return (List) Sessions.getCurrent().getAttribute(order.getCode() + "-labelsandcriteriaFilter");
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/components/bandboxsearch/BandboxSearch.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/components/bandboxsearch/BandboxSearch.java
index 4cfb85fb5..961ac923c 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/common/components/bandboxsearch/BandboxSearch.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/components/bandboxsearch/BandboxSearch.java
@@ -143,10 +143,11 @@ public class BandboxSearch extends HtmlMacroComponent {
}
public void pickElementFromList() {
- final Object object = getSelectedItem().getValue();
- bandbox.setValue(finder.objectToString(object));
- setSelectedElement(object);
- Util.getBinder(this).saveAttribute(this, SELECTED_ELEMENT_ATTRIBUTE);
+ final Listitem listitem = getSelectedItem();
+
+ if ( listitem != null ) {
+ setSelectedElement(listitem.getValue());
+ }
}
private void clearSelectedElement() {
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailNotificationModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailNotificationModel.java
index 3a309b1ad..ab7945ac3 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailNotificationModel.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/email/EmailNotificationModel.java
@@ -22,6 +22,7 @@ package org.libreplan.web.email;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.email.daos.IEmailNotificationDAO;
import org.libreplan.business.email.entities.EmailTemplateEnum;
+import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.planner.entities.TaskElement;
@@ -68,6 +69,17 @@ public class EmailNotificationModel implements IEmailNotificationModel {
return emailNotificationDAO.getAllByType(enumeration);
}
+ @Override
+ @Transactional
+ public List getAllByProject(TaskElement taskElement) {
+ return emailNotificationDAO.getAllByProject(taskElement);
+ }
+ @Override
+ @Transactional
+ public List getAllByTask(TaskElement taskElement) {
+ return emailNotificationDAO.getAllByTask(taskElement);
+ }
+
@Override
@Transactional
public boolean deleteAll() {
@@ -85,6 +97,18 @@ public class EmailNotificationModel implements IEmailNotificationModel {
return emailNotificationDAO.deleteById(notification);
}
+ @Override
+ @Transactional
+ public boolean deleteByProject(TaskElement taskElement) {
+ return emailNotificationDAO.deleteByProject(taskElement);
+ }
+
+ @Override
+ @Transactional
+ public boolean deleteByTask(TaskElement taskElement) {
+ return emailNotificationDAO.deleteByTask(taskElement);
+ }
+
@Override
public void setType(EmailTemplateEnum type) {
this.emailNotification.setType(type);
@@ -110,11 +134,12 @@ public class EmailNotificationModel implements IEmailNotificationModel {
this.emailNotification.setProject(project);
}
-
+ @Override
public EmailNotification getEmailNotification() {
return emailNotification;
}
+ @Override
public void setNewObject(){
this.emailNotification = new EmailNotification();
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/email/IEmailNotificationModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/email/IEmailNotificationModel.java
index fed30a3e4..ae983e7ca 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/email/IEmailNotificationModel.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/email/IEmailNotificationModel.java
@@ -21,6 +21,7 @@ package org.libreplan.web.email;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.email.entities.EmailTemplateEnum;
+import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.entities.Resource;
@@ -41,12 +42,20 @@ public interface IEmailNotificationModel {
List getAllByType(EmailTemplateEnum enumeration);
+ List getAllByProject(TaskElement taskElement);
+
+ List getAllByTask(TaskElement taskElement);
+
boolean deleteAll();
boolean deleteAllByType(EmailTemplateEnum enumeration);
boolean deleteById(EmailNotification notification);
+ boolean deleteByProject(TaskElement taskElement);
+
+ boolean deleteByTask(TaskElement taskElement);
+
void setType(EmailTemplateEnum type);
void setUpdated(Date date);
@@ -60,4 +69,5 @@ public interface IEmailNotificationModel {
EmailNotification getEmailNotification();
void setNewObject();
+
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/orders/IOrderModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/orders/IOrderModel.java
index 0892692f9..de518b110 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/orders/IOrderModel.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/orders/IOrderModel.java
@@ -91,7 +91,7 @@ public interface IOrderModel extends IIntegrationEntityModel {
List getOrders(Date startDate, Date endDate, List labels,
List criteria, ExternalCompany customer,
- OrderStatusEnum state);
+ OrderStatusEnum state, Boolean excludeFinishedProject);
void initEdit(Order order, Desktop desktop);
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/orders/ManageOrderElementAdvancesController.java b/libreplan-webapp/src/main/java/org/libreplan/web/orders/ManageOrderElementAdvancesController.java
index 455e7d57f..124580804 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/orders/ManageOrderElementAdvancesController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/orders/ManageOrderElementAdvancesController.java
@@ -849,7 +849,6 @@ public class ManageOrderElementAdvancesController extends GenericForwardComposer
this.manageOrderElementAdvancesModel.sortListAdvanceMeasurement();
Util.reloadBindings(editAdvancesMeasurement);
- this.setCurrentDate();
this.setPercentage();
this.setCurrentValue();
Util.reloadBindings(chart);
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/orders/OrderCRUDController.java b/libreplan-webapp/src/main/java/org/libreplan/web/orders/OrderCRUDController.java
index a5b9a618e..02bcf9ca3 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/orders/OrderCRUDController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/orders/OrderCRUDController.java
@@ -78,6 +78,7 @@ 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.Checkbox;
import org.zkoss.zul.Column;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Comboitem;
@@ -220,6 +221,8 @@ public class OrderCRUDController extends GenericForwardComposer {
private Textbox filterProjectName;
+ private Checkbox filterExcludeFinishedProject;
+
private Runnable onUp;
private boolean readOnly = true;
@@ -248,6 +251,8 @@ public class OrderCRUDController extends GenericForwardComposer {
filterProjectName = (Textbox) filterComponent.getFellow("filterProjectName");
+ filterExcludeFinishedProject = (Checkbox) filterComponent.getFellow("filterExcludeFinishedProject");
+
checkCreationPermissions();
setupGlobalButtons();
initializeFilter();
@@ -291,6 +296,8 @@ public class OrderCRUDController extends GenericForwardComposer {
filterProjectName.setValue(FilterUtils.readProjectsName());
+ filterExcludeFinishedProject.setValue(FilterUtils.readExcludeFinishedProjects());
+
loadLabels();
FilterUtils.writeProjectPlanningFilterChanged(false);
@@ -802,6 +809,7 @@ public class OrderCRUDController extends GenericForwardComposer {
List criteria = new ArrayList<>();
ExternalCompany customer = null;
OrderStatusEnum state = null;
+ //Boolean excludeFinishedProject = false;
for (FilterPair filterPair : (List) bdFilters.getSelectedElements()) {
OrderFilterEnum type = (OrderFilterEnum) filterPair.getType();
@@ -837,7 +845,7 @@ public class OrderCRUDController extends GenericForwardComposer {
}
return orderModel.getOrders(
- filterStartDate.getValue(), filterFinishDate.getValue(), labels, criteria, customer, state);
+ filterStartDate.getValue(), filterFinishDate.getValue(), labels, criteria, customer, state, filterExcludeFinishedProject.isChecked());
}
private OnlyOneVisible getVisibility() {
@@ -1286,6 +1294,7 @@ public class OrderCRUDController extends GenericForwardComposer {
appendDate(row, order.getDeadline());
appendCustomer(row, order.getCustomer());
appendObject(row, Util.addCurrencySymbol(order.getTotalManualBudget()));
+ appendObject(row, Util.addCurrencySymbol(order.getTotalBudget()));
appendObject(row, order.getTotalHours());
appendObject(row, _(order.getState().toString()));
appendOperations(row, order);
@@ -1437,7 +1446,8 @@ public class OrderCRUDController extends GenericForwardComposer {
filterStartDate.getValue(),
filterFinishDate.getValue(),
getSelectedBandboxAsTaskGroupFilters(),
- filterProjectName.getValue());
+ filterProjectName.getValue(),
+ filterExcludeFinishedProject.getValue());
}
private List getSelectedBandboxAsTaskGroupFilters() {
@@ -1768,6 +1778,7 @@ public class OrderCRUDController extends GenericForwardComposer {
filterStartDate.setValue(FilterUtils.readProjectsStartDate());
filterFinishDate.setValue(FilterUtils.readProjectsEndDate());
filterProjectName.setValue(FilterUtils.readProjectsName());
+ filterExcludeFinishedProject.setValue(FilterUtils.readExcludeFinishedProjects());
loadLabels();
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/orders/OrderModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/orders/OrderModel.java
index 43eee6b6c..681b11ef5 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/orders/OrderModel.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/orders/OrderModel.java
@@ -47,6 +47,7 @@ import org.libreplan.business.common.daos.IConfigurationDAO;
import org.libreplan.business.common.entities.Configuration;
import org.libreplan.business.common.entities.EntityNameEnum;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
+import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO;
import org.libreplan.business.externalcompanies.entities.EndDateCommunication;
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
@@ -60,6 +61,7 @@ import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderLineGroup;
import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.planner.entities.PositionConstraintType;
+import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.qualityforms.daos.IQualityFormDAO;
import org.libreplan.business.qualityforms.entities.QualityForm;
import org.libreplan.business.requirements.entities.DirectCriterionRequirement;
@@ -84,6 +86,7 @@ import org.libreplan.business.users.entities.UserRole;
import org.libreplan.web.calendars.BaseCalendarModel;
import org.libreplan.web.common.IntegrationEntityModel;
import org.libreplan.web.common.concurrentdetection.OnConcurrentModification;
+import org.libreplan.web.email.IEmailNotificationModel;
import org.libreplan.web.logs.IIssueLogModel;
import org.libreplan.web.logs.IRiskLogModel;
import org.libreplan.web.orders.files.IOrderFileModel;
@@ -181,6 +184,9 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
@Autowired
private IIssueLogModel issueLogModel;
+ @Autowired
+ private IEmailNotificationModel emailNotificationModel;
+
private List orderList = new ArrayList<>();
@Override
@@ -235,13 +241,13 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
@Transactional(readOnly = true)
public List getOrders(Date startDate, Date endDate,
List labels, List criteria,
- ExternalCompany customer, OrderStatusEnum state) {
+ ExternalCompany customer, OrderStatusEnum state, Boolean excludeFinishedProject) {
getLabelsOnConversation().reattachLabels();
List orders = orderDAO
.getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
SecurityUtils.getSessionUserLoginName(),
scenarioManager.getCurrent(), startDate, endDate,
- labels, criteria, customer, state);
+ labels, criteria, customer, state, excludeFinishedProject);
initializeOrders(orders);
@@ -436,7 +442,8 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
newOrder.setCustomer(getOrder().getCustomer());
newOrder.setCalendar(getCalendar());
newOrder.setInitDate(getOrder().getInitDate());
-
+ newOrder.setDescription(getOrder().getDescription());
+
if ( getOrder().getDeadline() != null ) {
newOrder.setDeadline(getOrder().getDeadline());
}
@@ -521,6 +528,8 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
public void remove(Order detachedOrder) {
Order order = orderDAO.findExistingEntity(detachedOrder.getId());
+ removeNotifications(order);
+
removeFiles(order);
removeLogs(order);
@@ -541,6 +550,18 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
orderFileModel.findByParent(order).forEach(orderFile -> orderFileModel.delete(orderFile));
}
+ private void removeNotifications(Order order) {
+
+ for ( Scenario scenario: currentAndDerivedScenarios()) {
+ order.useSchedulingDataFor(scenario.getOrderVersion(order));
+
+ TaskElement taskElement = order.getTaskElement();
+ if ( taskElement != null) {
+ emailNotificationModel.deleteByProject(taskElement);
+ }
+ }
+ }
+
private void removeVersions(Order order) {
Map versionsRemovedById = new HashMap<>();
List currentAndDerived = currentAndDerivedScenarios();
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/orders/ProjectDetailsController.java b/libreplan-webapp/src/main/java/org/libreplan/web/orders/ProjectDetailsController.java
index 870b7d420..0d9b2798c 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/orders/ProjectDetailsController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/orders/ProjectDetailsController.java
@@ -80,6 +80,8 @@ public class ProjectDetailsController extends GenericForwardComposer
private Textbox txtName;
+ private Textbox txtDescription;
+
private Datebox deadline;
private Checkbox generateCode;
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/TaskGroupPredicate.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/TaskGroupPredicate.java
index 1611eda5b..f105db5da 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/TaskGroupPredicate.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/TaskGroupPredicate.java
@@ -56,12 +56,15 @@ public class TaskGroupPredicate implements IPredicate {
private String name;
+ private Boolean excludeFinishedProject;
+
public TaskGroupPredicate(List filters, Date startDate,
- Date finishDate, String name) {
+ Date finishDate, String name, Boolean excludeFinishedProject) {
this.filters = filters;
this.startDate = startDate;
this.finishDate = finishDate;
this.name = name;
+ this.excludeFinishedProject = excludeFinishedProject;
}
@Override
@@ -166,6 +169,15 @@ public class TaskGroupPredicate implements IPredicate {
return false;
}
+ private boolean acceptFinishedProject(FilterPair filter, TaskGroup taskGroup) {
+ Label filterLabel = (Label) filter.getValue();
+ Order order = (Order) taskGroup.getOrderElement();
+ if (order.getState() != OrderStatusEnum.FINISHED) {
+ return true;
+ }
+ return false;
+ }
+
private boolean acceptExternalCompany(FilterPair filter, TaskGroup taskGroup) {
Order order = (Order) taskGroup.getOrderElement();
ExternalCompany filterCustomer = (ExternalCompany) filter.getValue();
@@ -300,4 +312,8 @@ public class TaskGroupPredicate implements IPredicate {
return false;
}
-}
\ No newline at end of file
+ public Boolean getExcludeFinishedProjects() {
+ return excludeFinishedProject;
+ }
+
+}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/chart/LoadChartFiller.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/chart/LoadChartFiller.java
index d00a16f55..ba236a7a9 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/chart/LoadChartFiller.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/chart/LoadChartFiller.java
@@ -38,7 +38,9 @@ public abstract class LoadChartFiller extends ChartFiller {
@Override
public void fillChart(Timeplot chart, Interval interval, Integer size) {
- chart.getChildren().clear();
+ if (chart.getChildren() != null) {
+ chart.getChildren().clear();
+ }
chart.invalidate();
if (getOptionalJavascriptCall() != null) {
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/company/CompanyPlanningController.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/company/CompanyPlanningController.java
index 1bbfd7342..828d82c50 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/company/CompanyPlanningController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/company/CompanyPlanningController.java
@@ -91,6 +91,8 @@ public class CompanyPlanningController implements Composer {
private Textbox filterProjectName;
+ private Checkbox filterExcludeFinishedProject;
+
private BandboxMultipleSearch bdFilters;
private ICommandOnTask doubleClickCommand;
@@ -135,6 +137,7 @@ public class CompanyPlanningController implements Composer {
filterStartDate = (Datebox) filterComponent.getFellow("filterStartDate");
filterFinishDate = (Datebox) filterComponent.getFellow("filterFinishDate");
filterProjectName = (Textbox) filterComponent.getFellow("filterProjectName");
+ filterExcludeFinishedProject = (Checkbox) filterComponent.getFellow("filterExcludeFinishedProject");
bdFilters = (BandboxMultipleSearch) filterComponent.getFellow("bdFilters");
bdFilters.setFinder("taskGroupsMultipleFiltersFinder");
@@ -179,6 +182,8 @@ public class CompanyPlanningController implements Composer {
.toDate());
}
filterProjectName.setValue(FilterUtils.readProjectsName());
+
+ filterExcludeFinishedProject.setChecked(user.isProjectsFilterFinishedOn());
}
}
@@ -311,6 +316,10 @@ public class CompanyPlanningController implements Composer {
filterStartDate.setValue(FilterUtils.readProjectsStartDate());
filterFinishDate.setValue(FilterUtils.readProjectsEndDate());
filterProjectName.setValue(FilterUtils.readProjectsName());
+ Boolean excludeFinishedProjects = FilterUtils.readExcludeFinishedProjects();
+ if ( excludeFinishedProjects != null ) {
+ filterExcludeFinishedProject.setChecked(excludeFinishedProjects);
+ }
loadPredefinedBandboxFilter();
}
@@ -319,7 +328,8 @@ public class CompanyPlanningController implements Composer {
filterStartDate.getValue(),
filterFinishDate.getValue(),
bdFilters.getSelectedElements(),
- filterProjectName.getValue());
+ filterProjectName.getValue(),
+ filterExcludeFinishedProject.isChecked());
FilterUtils.writeProjectPlanningFilterChanged(true);
filterByPredicate(createPredicate());
@@ -333,6 +343,7 @@ public class CompanyPlanningController implements Composer {
List listFilters = (List) bdFilters.getSelectedElements();
Date startDate = filterStartDate.getValue();
Date finishDate = filterFinishDate.getValue();
+ Boolean excludeFinishedProject = filterExcludeFinishedProject.isChecked();
String name = filterProjectName.getValue();
@@ -354,7 +365,7 @@ public class CompanyPlanningController implements Composer {
return predicate;
}
- return new TaskGroupPredicate(listFilters, startDate, finishDate, name);
+ return new TaskGroupPredicate(listFilters, startDate, finishDate, name, excludeFinishedProject);
}
private void filterByPredicate(TaskGroupPredicate predicate) {
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/company/CompanyPlanningModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/company/CompanyPlanningModel.java
index 780b01269..648189be3 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/company/CompanyPlanningModel.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/company/CompanyPlanningModel.java
@@ -164,6 +164,8 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
private LocalDate filterFinishDate;
+ private Boolean filterExcludeFinishedProject;
+
private static final class TaskElementNavigator implements IStructureNavigator {
@Override
@@ -204,6 +206,9 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
boolean expandPlanningViewChart = user.isExpandCompanyPlanningViewCharts();
configuration.setExpandPlanningViewCharts(expandPlanningViewChart);
+ boolean projectsFilterFinished = user.isProjectsFilterFinishedOn();
+ configuration.setFilterExcludeFinishedProject(projectsFilterFinished);
+
final Tabbox chartComponent = new Tabbox();
chartComponent.setOrient("vertical");
chartComponent.setHeight("200px");
@@ -218,6 +223,7 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
addAdditionalCommands(additional, configuration);
addPrintSupport(configuration);
disableSomeFeatures(configuration);
+ setDefaultButtonState(configuration,user);
planner.setInitialZoomLevel(getZoomLevel(configuration));
@@ -247,6 +253,23 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
}
}
+ private void setDefaultButtonState(PlannerConfiguration configuration, User user) {
+
+// set initial button show mode
+ if ( user.isShowAdvancesOn() ) {
+ configuration.setShowAdvancesOn(user.isShowAdvancesOn());
+ }
+
+ if ( user.isShowReportedHoursOn() ) {
+ configuration.setShowReportedHoursOn(user.isShowReportedHoursOn());
+ }
+
+ if ( user.isShowLabelsOn() ) {
+ configuration.setShowLabelsOn(user.isShowLabelsOn());
+ }
+
+}
+
private ZoomLevel getZoomLevel(PlannerConfiguration configuration) {
ZoomLevel sessionZoom = FilterUtils.readZoomLevelCompanyView();
@@ -692,6 +715,7 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
Date startDate = predicate.getStartDate();
Date endDate = predicate.getFinishDate();
+ Boolean excludeFinishedProject = predicate.getExcludeFinishedProjects();
List labels = new ArrayList<>();
List criteria = new ArrayList<>();
ExternalCompany customer = null;
@@ -732,7 +756,7 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
}
return orderDAO.getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
- username, currentScenario, startDate, endDate, labels, criteria, customer, state);
+ username, currentScenario, startDate, endDate, labels, criteria, customer, state, excludeFinishedProject);
}
@Override
@@ -742,6 +766,12 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
Date startDate = FilterUtils.readProjectsStartDate();
Date endDate = FilterUtils.readProjectsEndDate();
String name = FilterUtils.readProjectsName();
+ Boolean projectsFinished = FilterUtils.readExcludeFinishedProjects();
+
+ if ( projectsFinished == null ) {
+ User user = getUser();
+ projectsFinished = user.isProjectsFilterFinishedOn();
+ }
boolean calculateStartDate = startDate == null;
boolean calculateEndDate = endDate == null;
@@ -776,8 +806,9 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
}
filterStartDate = startDate != null ? LocalDate.fromDateFields(startDate) : null;
filterFinishDate = endDate != null ? LocalDate.fromDateFields(endDate) : null;
+ //filterExcludeFinishedProject = projectsFinished != null ? projectsFinished : false;
- return new TaskGroupPredicate(null, startDate, endDate, name);
+ return new TaskGroupPredicate(null, startDate, endDate, name, projectsFinished);
}
private static List notNull(T... values) {
@@ -886,4 +917,12 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
return user;
}
+ public Boolean getFilterExcludeFinishedProject() {
+ return filterExcludeFinishedProject;
+ }
+
+ public void setFilterExcludeFinishedProject(Boolean filterExcludeFinishedProject) {
+ this.filterExcludeFinishedProject = filterExcludeFinishedProject;
+ }
+
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/OrderPlanningModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/OrderPlanningModel.java
index 7d0de6561..df90a3607 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/OrderPlanningModel.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/OrderPlanningModel.java
@@ -354,6 +354,8 @@ public class OrderPlanningModel implements IOrderPlanningModel {
chartComponent.setHeight("200px");
appendTabs(chartComponent);
+ setDefaultButtonState(configuration,user);
+
configuration.setChartComponent(chartComponent);
configureModifiers(planningState.getOrder(), configuration);
long setConfigurationTime = System.currentTimeMillis();
@@ -395,6 +397,36 @@ public class OrderPlanningModel implements IOrderPlanningModel {
PROFILING_LOG.debug("overallProgressContent took: " + (System.currentTimeMillis() - overallProgressContentTime));
}
+ private void setDefaultButtonState(PlannerConfiguration configuration, User user) {
+
+ // set initial button show mode
+ if ( !planner.areShownAdvancesByDefault() && user.isShowAdvancesOn() ) {
+ configuration.setShowAdvancesOn(user.isShowAdvancesOn());
+ planner.setAreShownAdvancesByDefault(user.isShowAdvancesOn());
+ }
+
+ if ( !planner.areShownReportedHoursByDefault() && user.isShowReportedHoursOn() ) {
+ configuration.setShowReportedHoursOn(user.isShowReportedHoursOn());
+ planner.setAreShownReportedHoursByDefault(user.isShowReportedHoursOn());
+ }
+
+ if ( !planner.areShownMoneyCostBarByDefault() && user.isShowMoneyCostBarOn() ) {
+ configuration.setShowMoneyCostBarOn(user.isShowMoneyCostBarOn());
+ planner.setAreShownMoneyCostBarByDefault(user.isShowMoneyCostBarOn());
+ }
+
+ if ( !planner.areShownLabelsByDefault() && user.isShowLabelsOn() ) {
+ configuration.setShowLabelsOn(user.isShowLabelsOn());
+ planner.setAreShownLabelsByDefault(user.isShowLabelsOn());
+ }
+
+ if ( !planner.areShownResourcesByDefault() && user.isShowResourcesOn() ) {
+ configuration.setShowResourcesOn(user.isShowResourcesOn());
+ planner.setAreShownResourcesByDefault(user.isShowResourcesOn());
+ }
+
+ }
+
private ZoomLevel getZoomLevel(PlannerConfiguration configuration, Order order) {
ZoomLevel sessionZoom = FilterUtils.readZoomLevel(order);
if ( sessionZoom != null ) {
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/SaveCommandBuilder.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/SaveCommandBuilder.java
index 7f8f603be..3f5261e65 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/SaveCommandBuilder.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/SaveCommandBuilder.java
@@ -589,9 +589,19 @@ public class SaveCommandBuilder {
removeEmptyConsolidation(taskElement);
updateLimitingResourceQueueElementDates(taskElement);
- if (taskElement.getTaskSource() != null && taskElement.getTaskSource().isNewObject())
+ if (taskElement.getTaskSource() != null && taskElement.getTaskSource().isNewObject()) {
saveTaskSources(taskElement);
+ // hack to update taskPropertiesController reference to current currentTaskElement
+ if (SaveCommandBuilder.taskPropertiesController != null) {
+ TaskElement taskControllerTaskElement = SaveCommandBuilder.taskPropertiesController.getCurrentTaskElement();
+ if ( taskControllerTaskElement != null && taskControllerTaskElement.getOrderElement() == taskElement.getOrderElement() &&
+ taskControllerTaskElement.isNewObject()) {
+ SaveCommandBuilder.taskPropertiesController.setCurrentTaskElement(taskElement);
+ }
+ }
+ }
+
updateLimitingQueueDependencies(taskElement);
}
saveRootTask();
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/TaskPropertiesController.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/TaskPropertiesController.java
index ca54f7311..e67edf56e 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/TaskPropertiesController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/TaskPropertiesController.java
@@ -800,7 +800,7 @@ public class TaskPropertiesController extends GenericForwardComposer
emailNotificationModel.setTask(currentTaskElement.getTaskSource().getTask());
- emailNotificationModel.setProject(currentTaskElement.getParent().getTaskSource().getTask());
+ emailNotificationModel.setProject(currentTaskElement.getTopMost().getTaskSource().getTask());
emailNotificationModel.confirmSave();
} catch (DataIntegrityViolationException e) {
@@ -826,4 +826,12 @@ public class TaskPropertiesController extends GenericForwardComposer
return this;
}
+ public TaskElement getCurrentTaskElement() {
+ return currentTaskElement;
+ }
+
+ public void setCurrentTaskElement(TaskElement taskElement) {
+ currentTaskElement = taskElement;
+ }
+
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/tree/TreeController.java b/libreplan-webapp/src/main/java/org/libreplan/web/tree/TreeController.java
index 69ad4ebcc..7640a01e4 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/tree/TreeController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/tree/TreeController.java
@@ -609,7 +609,7 @@ public abstract class TreeController> extends GenericForw
int myPosition = parent.getIndex();
- if (myPosition < treeItems.size() - 1) {
+ if ((myPosition < treeItems.size() - 1) && myPosition > 0) {
// The current node is not the last one
Treerow downTreerow = treeItems.get(myPosition + 1).getTreerow();
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/users/dashboard/PersonalTimesheetDTO.java b/libreplan-webapp/src/main/java/org/libreplan/web/users/dashboard/PersonalTimesheetDTO.java
index db326f16d..ee3744d4a 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/users/dashboard/PersonalTimesheetDTO.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/users/dashboard/PersonalTimesheetDTO.java
@@ -35,8 +35,14 @@ import org.libreplan.business.workreports.entities.WorkReport;
*/
public class PersonalTimesheetDTO {
+ private static final String d_Y_PATTERN = "d Y";
+
+ private static final String MMMM_d_PATTERN = "MMMM d";
+
private static final String MMMM_Y_PATTERN = "MMMM y";
+ private static final String MMMM_d_Y_PATTERN = "MMMM d y";
+
private LocalDate date;
private WorkReport workReport;
@@ -108,20 +114,20 @@ public class PersonalTimesheetDTO {
String string = date.toString("w");
if (start.getMonthOfYear() == end.getMonthOfYear()) {
- string += " (" + date.toString(MMMM_Y_PATTERN) + ")";
+ string += " (" + start.toString(MMMM_d_PATTERN) + " - " + end.toString(d_Y_PATTERN) + ")";
} else {
if (start.getYear() == end.getYear()) {
- string += " (" + start.toString("MMMM") + " - " + end.toString(MMMM_Y_PATTERN) + ")";
+ string += " (" + start.toString(MMMM_d_PATTERN) + " - " + end.toString(MMMM_d_Y_PATTERN) + ")";
} else {
- string += " (" + start.toString(MMMM_Y_PATTERN) + " - " + end.toString(MMMM_Y_PATTERN) + ")";
+ string += " (" + start.toString(MMMM_d_Y_PATTERN) + " - " + end.toString(MMMM_d_Y_PATTERN) + ")";
}
}
return _("Week {0}", string);
case TWICE_MONTHLY:
return (date.getDayOfMonth() <= 15)
- ? _("{0} 1st fortnight", date.toString(MMMM_Y_PATTERN))
- : _("{0} 2nd fortnight", date.toString(MMMM_Y_PATTERN));
+ ? _("{0} 1st fortnight", date.toString(MMMM_d_Y_PATTERN))
+ : _("{0} 2nd fortnight", date.toString(MMMM_d_Y_PATTERN));
case MONTHLY:
default:
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/ISettingsModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/ISettingsModel.java
index 344c27eef..e112bd391 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/ISettingsModel.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/ISettingsModel.java
@@ -101,4 +101,27 @@ public interface ISettingsModel {
void setResourcesLoadFilterCriterion(Criterion criterion);
+ boolean isShowResourcesOn();
+
+ void setShowResourcesOn(boolean showResourcesOn);
+
+ boolean isShowAdvancesOn();
+
+ void setShowAdvancesOn(boolean showAdvancesOn);
+
+ boolean isShowReportedHoursOn();
+
+ void setShowReportedHoursOn(boolean showReportedHoursOn);
+
+ boolean isShowLabelsOn();
+
+ void setShowLabelsOn(boolean showLabelsOn);
+
+ boolean isShowMoneyCostBarOn();
+
+ void setShowMoneyCostBarOn(boolean showMoneyCostBarOn);
+
+ boolean isProjectsFilterFinishedOn();
+
+ void setProjectsFilterFinishedOn(boolean projectsFilterFinishedOn);
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/SettingsController.java b/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/SettingsController.java
index 9cb723956..1ba6be891 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/SettingsController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/SettingsController.java
@@ -314,4 +314,52 @@ public class SettingsController extends GenericForwardComposer {
settingsModel.setResourcesLoadFilterCriterion(criterion);
}
+ public boolean isShowResourcesOn() {
+ return settingsModel.isShowResourcesOn();
+ }
+
+ public void setShowResourcesOn(boolean showResourcesOn) {
+ settingsModel.setShowResourcesOn(showResourcesOn);
+ }
+
+ public boolean isShowAdvancesOn() {
+ return settingsModel.isShowAdvancesOn();
+ }
+
+ public void setShowAdvancesOn(boolean showAdvancesOn) {
+ settingsModel.setShowAdvancesOn(showAdvancesOn);
+ }
+
+ public boolean isShowReportedHoursOn() {
+ return settingsModel.isShowReportedHoursOn();
+ }
+
+ public void setShowReportedHoursOn(boolean showReportedHoursOn) {
+ settingsModel.setShowReportedHoursOn(showReportedHoursOn);
+ }
+
+ public boolean isShowLabelsOn() {
+ return settingsModel.isShowLabelsOn();
+ }
+
+ public void setShowLabelsOn(boolean showLabelsOn) {
+ settingsModel.setShowLabelsOn(showLabelsOn);
+ }
+
+ public boolean isShowMoneyCostBarOn() {
+ return settingsModel.isShowMoneyCostBarOn();
+ }
+
+ public void setShowMoneyCostBarOn(boolean showMoneyCostBarOn) {
+ settingsModel.setShowMoneyCostBarOn(showMoneyCostBarOn);
+ }
+
+ public boolean isProjectsFilterFinishedOn() {
+ return settingsModel.isProjectsFilterFinishedOn();
+ }
+
+ public void setProjectsFilterFinishedOn(boolean projectsFilterFinishedOn) {
+ settingsModel.setProjectsFilterFinishedOn(projectsFilterFinishedOn);
+ }
+
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/SettingsModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/SettingsModel.java
index ea9ba8acc..721f44c47 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/SettingsModel.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/users/settings/SettingsModel.java
@@ -311,4 +311,64 @@ public class SettingsModel implements ISettingsModel {
user.setResourcesLoadFilterCriterion(criterion);
}
+ @Override
+ public boolean isShowResourcesOn() {
+ return user.isShowResourcesOn();
+ }
+
+ @Override
+ public void setShowResourcesOn(boolean showResourcesOn) {
+ user.setShowResourcesOn(showResourcesOn);
+ }
+
+ @Override
+ public boolean isShowAdvancesOn() {
+ return user.isShowAdvancesOn();
+ }
+
+ @Override
+ public void setShowAdvancesOn(boolean showAdvancesOn) {
+ user.setShowAdvancesOn(showAdvancesOn);
+ }
+
+ @Override
+ public boolean isShowReportedHoursOn() {
+ return user.isShowReportedHoursOn();
+ }
+
+ @Override
+ public void setShowReportedHoursOn(boolean showReportedHoursOn) {
+ user.setShowReportedHoursOn(showReportedHoursOn);
+ }
+
+ @Override
+ public boolean isShowLabelsOn() {
+ return user.isShowLabelsOn();
+ }
+
+ @Override
+ public void setShowLabelsOn(boolean showLabelsOn) {
+ user.setShowLabelsOn(showLabelsOn);
+ }
+
+ @Override
+ public boolean isShowMoneyCostBarOn() {
+ return user.isShowMoneyCostBarOn();
+ }
+
+ @Override
+ public void setShowMoneyCostBarOn(boolean showMoneyCostBarOn) {
+ user.setShowMoneyCostBarOn(showMoneyCostBarOn);
+ }
+
+ @Override
+ public boolean isProjectsFilterFinishedOn() {
+ return user.isProjectsFilterFinishedOn();
+ }
+
+ @Override
+ public void setProjectsFilterFinishedOn(boolean projectsFilterFinishedOn) {
+ user.setProjectsFilterFinishedOn(projectsFilterFinishedOn);
+ }
+
}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/workreports/WorkReportCRUDController.java b/libreplan-webapp/src/main/java/org/libreplan/web/workreports/WorkReportCRUDController.java
index 8d3dc49b0..8c5b17000 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/workreports/WorkReportCRUDController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/workreports/WorkReportCRUDController.java
@@ -40,6 +40,8 @@ import org.libreplan.business.labels.entities.LabelType;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
+import org.libreplan.business.users.entities.User;
+import org.libreplan.business.users.entities.UserRole;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workreports.entities.HoursManagementEnum;
import org.libreplan.business.workreports.entities.WorkReport;
@@ -48,6 +50,7 @@ import org.libreplan.business.workreports.entities.WorkReportLine;
import org.libreplan.business.workreports.entities.WorkReportType;
import org.libreplan.business.workreports.valueobjects.DescriptionField;
import org.libreplan.business.workreports.valueobjects.DescriptionValue;
+import org.libreplan.web.UserUtil;
import org.libreplan.web.common.ConstraintChecker;
import org.libreplan.web.common.IMessagesForUser;
import org.libreplan.web.common.Level;
@@ -59,6 +62,7 @@ import org.libreplan.web.common.components.NewDataSortableColumn;
import org.libreplan.web.common.components.NewDataSortableGrid;
import org.libreplan.web.common.components.bandboxsearch.BandboxSearch;
import org.libreplan.web.common.entrypoints.IURLHandlerRegistry;
+import org.libreplan.web.security.SecurityUtils;
import org.libreplan.web.users.dashboard.IPersonalTimesheetController;
import org.zkoss.ganttz.IPredicate;
import org.zkoss.ganttz.util.ComponentsFinder;
@@ -689,16 +693,29 @@ public class WorkReportCRUDController
@Override
public void goToEditForm(WorkReport workReport) {
- if ( workReportModel.isPersonalTimesheet(workReport) ) {
- goToEditPersonalTimeSheet(workReport);
- } else {
+ if (SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_TIMESHEETS)) {
workReportModel.initEdit(workReport);
createWindow.setTitle(_("Edit Timesheet"));
loadComponents(createWindow);
prepareWorkReportList();
getVisibility().showOnly(createWindow);
Util.reloadBindings(createWindow);
+
+ } else if (SecurityUtils.isUserInRole(UserRole.ROLE_BOUND_USER) &&
+ workReportModel.isPersonalTimesheet(workReport) &&
+ belongsToCurrentUser(workReport)) {
+
+ goToEditPersonalTimeSheet(workReport);
+ } else {
+ messagesForUser.showMessage(Level.WARNING, _("You do not have permissions to edit this timesheet"));
}
+ }
+
+ private boolean belongsToCurrentUser(WorkReport workReport) {
+ User user = UserUtil.getUserFromSession();
+ assert user != null;
+
+ return workReport.getResource().getId().equals(user.getWorker().getId());
}
private void goToEditPersonalTimeSheet(WorkReport workReport) {
@@ -989,7 +1006,8 @@ public class WorkReportCRUDController
NewDataSortableGrid grid = (NewDataSortableGrid) row.getParent().getParent();
NewDataSortableColumn priorityColumn = (NewDataSortableColumn) grid.getChildren().get(1).getChildren().get(2);
- priorityColumn.setWidth("110px");
+ // DISCUSS: Are there any implications to not setting a width on this column??
+ //priorityColumn.setWidth("110px");
if (!getWorkReport().getWorkReportType().getHoursManagement().equals(HoursManagementEnum.NUMBER_OF_HOURS)) {
appendHoursStartAndFinish(row);
diff --git a/libreplan-webapp/src/main/resources/i18n/keys.pot b/libreplan-webapp/src/main/resources/i18n/keys.pot
index 6cc02d7d7..37caf4466 100644
--- a/libreplan-webapp/src/main/resources/i18n/keys.pot
+++ b/libreplan-webapp/src/main/resources/i18n/keys.pot
@@ -1674,7 +1674,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/templates/_editTemplate.zul:90
#: libreplan-webapp/src/main/webapp/common/configuration.zul:178
#: libreplan-webapp/src/main/webapp/orders/_edition.zul:140
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:76
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:82
msgid "Calendar"
msgstr ""
@@ -3532,7 +3532,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/costcategories/_editCostCategory.zul:98
#: libreplan-webapp/src/main/webapp/profiles/_editProfile.zul:74
#: libreplan-webapp/src/main/webapp/orders/components/_listOrderElementMaterials.zul:132
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:90
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:95
#: libreplan-webapp/src/main/webapp/unittypes/unitTypes.zul:43
#: libreplan-webapp/src/main/webapp/qualityforms/_editQualityForm.zul:137
#: libreplan-webapp/src/main/webapp/limitingresources/manualAllocation.zul:135
@@ -3725,7 +3725,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/workreports/workReport.zul:43
#: libreplan-webapp/src/main/webapp/workreports/workReport.zul:65
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:42
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:48
msgid "Template"
msgstr ""
@@ -4300,7 +4300,7 @@ msgstr ""
#: libreplan-webapp/src/main/java/org/libreplan/web/common/components/finders/TaskGroupFilterEnum.java:30
#: libreplan-webapp/src/main/webapp/subcontract/customerCommunications.zul:56
#: libreplan-webapp/src/main/webapp/orders/_edition.zul:227
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:69
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:75
#: libreplan-webapp/src/main/webapp/orders/_list.zul:32
msgid "Customer"
msgstr ""
@@ -4447,7 +4447,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/orders/_orderElementDetails.zul:35
#: libreplan-webapp/src/main/webapp/orders/_orderElementDetails.zul:41
#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:38
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:52
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:58
msgid "cannot be empty"
msgstr ""
@@ -7209,7 +7209,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/workreports/_editWorkReportType.zul:60
#: libreplan-webapp/src/main/webapp/costcategories/_editCostCategory.zul:45
#: libreplan-webapp/src/main/webapp/orders/_edition.zul:90
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:53
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:59
#: libreplan-webapp/src/main/webapp/unittypes/_editUnitType.zul:45
msgid "Generate code"
msgstr ""
@@ -7452,7 +7452,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/planner/editTask.zul:81
#: libreplan-webapp/src/main/webapp/planner/reassign.zul:48
#: libreplan-webapp/src/main/webapp/common/layout/template.zul:102
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:88
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:94
#: libreplan-webapp/src/main/webapp/limitingresources/manualAllocation.zul:133
msgid "Accept"
msgstr ""
@@ -7590,7 +7590,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/costcategories/_editCostCategory.zul:78
#: libreplan-webapp/src/main/webapp/orders/components/_listOrderElementMaterials.zul:109
#: libreplan-webapp/src/main/webapp/orders/_edition.zul:85
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:48
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:54
#: libreplan-webapp/src/main/webapp/orders/_assignmentsBox.zul:26
#: libreplan-webapp/src/main/webapp/orders/_list.zul:29
#: libreplan-webapp/src/main/webapp/unittypes/_editUnitType.zul:37
@@ -7767,6 +7767,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/scenarios/_edition.zul:43
#: libreplan-webapp/src/main/webapp/orders/_edition.zul:100
#: libreplan-webapp/src/main/webapp/orders/_orderElementDetails.zul:59
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:44
#: libreplan-webapp/src/main/webapp/qualityforms/_listQualityForm.zul:37
#: libreplan-webapp/src/main/webapp/qualityforms/_editQualityForm.zul:49
#: libreplan-webapp/src/main/webapp/email/email_templates.zul:83
@@ -7896,7 +7897,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/reports/schedulingProgressPerOrderReport.zul:53
#: libreplan-webapp/src/main/webapp/orders/_edition.zul:129
#: libreplan-webapp/src/main/webapp/orders/_orderElementDetails.zul:45
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:58
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:64
#: libreplan-webapp/src/main/webapp/orders/_list.zul:30
msgid "Starting date"
msgstr ""
@@ -8357,7 +8358,7 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/subcontract/customerCommunications.zul:54
#: libreplan-webapp/src/main/webapp/orders/_edition.zul:134
#: libreplan-webapp/src/main/webapp/orders/_orderElementDetails.zul:52
-#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:64
+#: libreplan-webapp/src/main/webapp/orders/_projectDetails.zul:70
#: libreplan-webapp/src/main/webapp/orders/_list.zul:31
msgid "Deadline"
msgstr ""
@@ -9291,6 +9292,10 @@ msgstr ""
msgid "Welcome page"
msgstr ""
+#: libreplan-webapp/src/main/webapp/email/email_templates.zul:124
+msgid "Project details page"
+msgstr ""
+
#: libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderStatusEnum.java:43
msgid "ARCHIVED"
msgstr ""
diff --git a/libreplan-webapp/src/main/resources/metainfo/tld/config.xml b/libreplan-webapp/src/main/resources/metainfo/tld/config.xml
index d38abf1cf..b098b2380 100644
--- a/libreplan-webapp/src/main/resources/metainfo/tld/config.xml
+++ b/libreplan-webapp/src/main/resources/metainfo/tld/config.xml
@@ -2,6 +2,6 @@
i18n
http://org.libreplan.web/i18n
- libreplan-webapp/WEB-INF/tld/i18n.tld
+ /metainfo/tld/i18n.tld
\ No newline at end of file
diff --git a/libreplan-webapp/src/main/resources/metainfo/tld/i18n.tld b/libreplan-webapp/src/main/resources/metainfo/tld/i18n.tld
new file mode 100644
index 000000000..8995a7ceb
--- /dev/null
+++ b/libreplan-webapp/src/main/resources/metainfo/tld/i18n.tld
@@ -0,0 +1,26 @@
+
+
+ http://org.libreplan.web/i18n
+
+
+
+ _
+ org.libreplan.web.I18nHelper
+
+ java.lang.String _(java.lang.String name)
+
+
+
+
+
+
+
+ __
+ org.libreplan.web.I18nHelper
+
+ java.lang.String _(java.lang.String name, java.lang.Object arg0)
+
+
+
+
+
diff --git a/libreplan-webapp/src/main/webapp/WEB-INF/lib/sapphire.jar b/libreplan-webapp/src/main/webapp/WEB-INF/lib/sapphire.jar
index f80e8d897..65c47fd50 100644
Binary files a/libreplan-webapp/src/main/webapp/WEB-INF/lib/sapphire.jar and b/libreplan-webapp/src/main/webapp/WEB-INF/lib/sapphire.jar differ
diff --git a/libreplan-webapp/src/main/webapp/WEB-INF/zk.xml b/libreplan-webapp/src/main/webapp/WEB-INF/zk.xml
index 37c3aa601..110583bb0 100644
--- a/libreplan-webapp/src/main/webapp/WEB-INF/zk.xml
+++ b/libreplan-webapp/src/main/webapp/WEB-INF/zk.xml
@@ -1,9 +1,5 @@
-
-
-
-
-
+