Merge pull request #141 from lmann99/master
Possible fixes for lazy initialization errors, email notifications, and other minor issues
This commit is contained in:
commit
d49cee584d
75 changed files with 1395 additions and 318 deletions
|
|
@ -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
|
||||
----
|
||||
|
|
|
|||
|
|
@ -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
|
||||
24
doc/src/user/en/17-2-pipeline-dashboard.rst
Normal file
24
doc/src/user/en/17-2-pipeline-dashboard.rst
Normal file
|
|
@ -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.
|
||||
19
doc/src/user/en/17-dashboards.rst
Normal file
19
doc/src/user/en/17-dashboards.rst
Normal file
|
|
@ -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
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="17-1-project-dashboard.html">Individual project dashboard</a>
|
||||
</li><li>
|
||||
<a href="17-2-pipeline-dashboard.html">All projects pipeline dashboard</a>
|
||||
</ul>
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -243,6 +243,8 @@ public class FunctionalityExposedForExtensions<T> implements IContext<T> {
|
|||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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() ) {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ public interface IDisabilityConfiguration {
|
|||
|
||||
public boolean isMoneyCostBarEnabled();
|
||||
|
||||
public boolean isLabelsEnabled();
|
||||
|
||||
public boolean isResourcesEnabled();
|
||||
|
||||
public boolean isExpandAllEnabled();
|
||||
|
||||
public boolean isFlattenTreeEnabled();
|
||||
|
|
|
|||
|
|
@ -157,6 +157,10 @@ public class PlannerConfiguration<T> 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<T> 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<T> 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<T> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<GanttDate> 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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ public class AdHocTransactionService implements IAdHocTransactionService {
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <T> T runOnTransaction(IOnTransaction<T> onTransaction) {
|
||||
return onTransaction.execute();
|
||||
|
|
|
|||
|
|
@ -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<EmailNotification> getAllByProject(TaskElement taskElement) {
|
||||
return getSession()
|
||||
.createCriteria(EmailNotification.class)
|
||||
.add(Restrictions.eq("project", taskElement))
|
||||
.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmailNotification> getAllByTask(TaskElement taskElement) {
|
||||
return getSession()
|
||||
.createCriteria(EmailNotification.class)
|
||||
.add(Restrictions.eq("task", taskElement))
|
||||
.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteAll() {
|
||||
List<EmailNotification> notifications = list(EmailNotification.class);
|
||||
|
|
@ -89,4 +109,26 @@ public class EmailNotificationDAO
|
|||
.uniqueResult() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteByProject(TaskElement taskElement) {
|
||||
List<EmailNotification> notifications = getAllByProject(taskElement);
|
||||
|
||||
for (Object item : notifications){
|
||||
getSession().delete(item);
|
||||
}
|
||||
|
||||
return getAllByProject(taskElement).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteByTask(TaskElement taskElement) {
|
||||
List<EmailNotification> notifications = getAllByTask(taskElement);
|
||||
|
||||
for (Object item : notifications){
|
||||
getSession().delete(item);
|
||||
}
|
||||
|
||||
return getAllByTask(taskElement).isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<EmailNotification, Lo
|
|||
|
||||
List<EmailNotification> getAllByType(EmailTemplateEnum enumeration);
|
||||
|
||||
List<EmailNotification> getAllByProject(TaskElement taskElement);
|
||||
|
||||
List<EmailNotification> getAllByTask(TaskElement taskElement);
|
||||
|
||||
boolean deleteAll();
|
||||
|
||||
boolean deleteAllByType(EmailTemplateEnum enumeration);
|
||||
|
||||
boolean deleteById(EmailNotification notification);
|
||||
|
||||
boolean deleteByProject(TaskElement taskElement);
|
||||
|
||||
boolean deleteByTask(TaskElement taskElement);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public interface IOrderDAO extends IIntegrationEntityDAO<Order> {
|
|||
List<Order> getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
|
||||
String username, Scenario scenario, Date startDate, Date endDate,
|
||||
List<Label> labels, List<Criterion> criteria,
|
||||
ExternalCompany customer, OrderStatusEnum state);
|
||||
ExternalCompany customer, OrderStatusEnum state, Boolean excludeFinishedProject);
|
||||
|
||||
/**
|
||||
* Returns the order filtered by the name.
|
||||
|
|
|
|||
|
|
@ -231,9 +231,10 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements IOrderDAO {
|
|||
List<Label> labels,
|
||||
List<Criterion> criteria,
|
||||
ExternalCompany customer,
|
||||
OrderStatusEnum state) {
|
||||
OrderStatusEnum state,
|
||||
Boolean excludeFinishedProject) {
|
||||
|
||||
List<Long> ordersIdsFiltered = getOrdersIdsFiltered(user, labels, criteria, customer, state);
|
||||
List<Long> 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<Order> implements IOrderDAO {
|
|||
List<Label> labels,
|
||||
List<Criterion> criteria,
|
||||
ExternalCompany customer,
|
||||
OrderStatusEnum state) {
|
||||
OrderStatusEnum state,
|
||||
Boolean excludeFinishedProject) {
|
||||
|
||||
List<Long> ordersIdsByReadAuthorization = getOrdersIdsByReadAuthorization(user);
|
||||
|
||||
|
|
@ -405,6 +407,15 @@ public class OrderDAO extends IntegrationEntityDAO<Order> 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<Order> implements IOrderDAO {
|
|||
List<Label> labels,
|
||||
List<Criterion> criteria,
|
||||
ExternalCompany customer,
|
||||
OrderStatusEnum state) {
|
||||
OrderStatusEnum state,
|
||||
Boolean excludeFinishedProject) {
|
||||
|
||||
User user;
|
||||
try {
|
||||
|
|
@ -559,7 +571,7 @@ public class OrderDAO extends IntegrationEntityDAO<Order> 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<Order> existsInScenario(List<Order> orders, Scenario scenario) {
|
||||
|
|
|
|||
|
|
@ -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<OrderElement> implemen
|
|||
@Autowired
|
||||
private ITaskSourceDAO taskSourceDAO;
|
||||
|
||||
@Autowired
|
||||
private IEmailNotificationDAO emailNotificationDAO;
|
||||
|
||||
@Override
|
||||
public List<OrderElement> findWithoutParent() {
|
||||
return getSession()
|
||||
|
|
@ -142,6 +147,9 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement> 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<OrderElement> implemen
|
|||
super.remove(id);
|
||||
}
|
||||
|
||||
public void removeNotifications(OrderElement orderElement) {
|
||||
|
||||
List<SchedulingDataForVersion> 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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -122,8 +122,11 @@ public interface IWorkerDAO extends IIntegrationEntityDAO<Worker> {
|
|||
public List<Worker> findByFirstNameSecondNameAnotherTransaction(
|
||||
String firstname, String secondname);
|
||||
|
||||
public Worker getCurrentWorker(Long resourceID);
|
||||
|
||||
/**
|
||||
* Return the list of {@link Worker Workers} bound to any {@link User}.
|
||||
*/
|
||||
List<Worker> getBound();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,4 +198,18 @@ public class WorkerDAO extends IntegrationEntityDAO<Worker>
|
|||
criteria.add(Restrictions.isNotNull("user"));
|
||||
return criteria.list();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Worker getCurrentWorker(Long resourceID) {
|
||||
List<Worker> workerList = getWorkers();
|
||||
|
||||
for (Worker worker : workerList) {
|
||||
if (worker.getId().equals(resourceID)) {
|
||||
return worker;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<OrderAuthorizatio
|
|||
public List<OrderAuthorization> listByUserAndItsProfiles(User user) {
|
||||
List<OrderAuthorization> list = new ArrayList<OrderAuthorization>();
|
||||
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<OrderAuthorizatio
|
|||
if (!listByUser(user).isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
Registry.getUserDAO().reattach(user);
|
||||
for (Profile profile : user.getProfiles()) {
|
||||
if (!listByProfile(profile).isEmpty()) {
|
||||
return true;
|
||||
|
|
@ -108,6 +111,7 @@ public class OrderAuthorizationDAO extends GenericDAOHibernate<OrderAuthorizatio
|
|||
public List<OrderAuthorization> listByOrderUserAndItsProfiles(Order order, User user) {
|
||||
List<OrderAuthorization> list = new ArrayList<OrderAuthorization>();
|
||||
list.addAll(listByOrderAndUser(order,user));
|
||||
Registry.getUserDAO().reattach(user);
|
||||
for(Profile profile : user.getProfiles()) {
|
||||
list.addAll(listByOrderAndProfile(order, profile));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
109
libreplan-business/src/main/resources/db.changelog-1.6.xml
Normal file
109
libreplan-business/src/main/resources/db.changelog-1.6.xml
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
|
||||
<changeSet id="add-new-column-show-reported-hours" author="lmann">
|
||||
<comment>Add columns to store user default setting of show/hide reported hours button</comment>
|
||||
<addColumn tableName="user_table">
|
||||
<column name="show_reported_hours_on" type="BOOLEAN" />
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="add-new-columns-show-resources" author="lmann">
|
||||
<comment>Add columns to store user default setting of show/hide resources button</comment>
|
||||
<addColumn tableName="user_table">
|
||||
<column name="show_resources_on" type="BOOLEAN" />
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="add-new-columns-show-advances" author="lmann">
|
||||
<comment>Add columns to store user default setting of show/hide advances button</comment>
|
||||
<addColumn tableName="user_table">
|
||||
<column name="show_advances_on" type="BOOLEAN" />
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="add-new-columns-show-labels" author="lmann">
|
||||
<comment>Add columns to store user default setting of show/hide labels button</comment>
|
||||
<addColumn tableName="user_table">
|
||||
<column name="show_labels_on" type="BOOLEAN" />
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="add-new-columns-show-moneycostbar" author="lmann">
|
||||
<comment>Add columns to store user default setting of show/hide moneycostbar button</comment>
|
||||
<addColumn tableName="user_table">
|
||||
<column name="show_money_cost_bar_on" type="BOOLEAN" />
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="add-new-columns-projects-filter-finished" author="lmann">
|
||||
<comment>Add columns to store user default setting of filter finished projects in views</comment>
|
||||
<addColumn tableName="user_table">
|
||||
<column name="projects_filter_finished_on" type="BOOLEAN" />
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="set-default-value-show-reported-hours" author="lmann">
|
||||
<addDefaultValue tableName="user_table"
|
||||
columnName="show_reported_hours_on"
|
||||
defaultValueBoolean="FALSE" />
|
||||
<addNotNullConstraint tableName="user_table"
|
||||
columnName="show_reported_hours_on"
|
||||
defaultNullValue="FALSE"
|
||||
columnDataType="BOOLEAN" />
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="set-default-value-show-resources" author="lmann">
|
||||
<addDefaultValue tableName="user_table"
|
||||
columnName="show_resources_on"
|
||||
defaultValueBoolean="FALSE" />
|
||||
<addNotNullConstraint tableName="user_table"
|
||||
columnName="show_resources_on"
|
||||
defaultNullValue="FALSE"
|
||||
columnDataType="BOOLEAN" />
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="set-default-value-show-advances" author="lmann">
|
||||
<addDefaultValue tableName="user_table"
|
||||
columnName="show_advances_on"
|
||||
defaultValueBoolean="FALSE" />
|
||||
<addNotNullConstraint tableName="user_table"
|
||||
columnName="show_advances_on"
|
||||
defaultNullValue="FALSE"
|
||||
columnDataType="BOOLEAN" />
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="set-default-value-show-labels" author="lmann">
|
||||
<addDefaultValue tableName="user_table"
|
||||
columnName="show_labels_on"
|
||||
defaultValueBoolean="FALSE" />
|
||||
<addNotNullConstraint tableName="user_table"
|
||||
columnName="show_labels_on"
|
||||
defaultNullValue="FALSE"
|
||||
columnDataType="BOOLEAN" />
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="set-default-value-show-money_cost_bar" author="lmann">
|
||||
<addDefaultValue tableName="user_table"
|
||||
columnName="show_money_cost_bar_on"
|
||||
defaultValueBoolean="FALSE" />
|
||||
<addNotNullConstraint tableName="user_table"
|
||||
columnName="show_money_cost_bar_on"
|
||||
defaultNullValue="FALSE"
|
||||
columnDataType="BOOLEAN" />
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="set-default-value-projects-filter-finished" author="lmann">
|
||||
<addDefaultValue tableName="user_table"
|
||||
columnName="projects_filter_finished_on"
|
||||
defaultValueBoolean="FALSE" />
|
||||
<addNotNullConstraint tableName="user_table"
|
||||
columnName="projects_filter_finished_on"
|
||||
defaultNullValue="FALSE"
|
||||
columnDataType="BOOLEAN" />
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
|
@ -12,4 +12,5 @@
|
|||
<include file="db.changelog-1.3.xml"/>
|
||||
<include file="db.changelog-1.4.xml"/>
|
||||
<include file="db.changelog-1.5.xml"/>
|
||||
<include file="db.changelog-1.6.xml"/>
|
||||
</databaseChangeLog>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
</set>
|
||||
|
||||
<!-- Indexed the other side -->
|
||||
<set name="criterionRequirements" access="field" cascade="all,delete-orphan" inverse="true" batch-size="10">
|
||||
<set name="criterionRequirements" access="field" cascade="all,delete-orphan" inverse="true" batch-size="10" lazy="false">
|
||||
<key column="order_element_id" not-null="false"/>
|
||||
<one-to-many class="org.libreplan.business.requirements.entities.CriterionRequirement"/>
|
||||
</set>
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
<key column="order_element_id"/>
|
||||
|
||||
<!-- Indexed the other side -->
|
||||
<list name="children" access="field" cascade="all">
|
||||
<list name="children" access="field" cascade="all" lazy="false">
|
||||
<key column="parent" not-null="false"/>
|
||||
<index column="position_in_container"/>
|
||||
<one-to-many class="OrderElement" />
|
||||
|
|
@ -216,7 +216,7 @@
|
|||
<property name="fixedPercentage" column="fixed_percentage" access="field" />
|
||||
|
||||
<!-- Indexed the other side -->
|
||||
<set name="criterionRequirements" access="field" cascade="save-update,delete-orphan" inverse="true" batch-size="10">
|
||||
<set name="criterionRequirements" access="field" cascade="save-update,delete-orphan" inverse="true" batch-size="10" lazy="false">
|
||||
<key column="hours_group_id" not-null="false"/>
|
||||
<one-to-many class="org.libreplan.business.requirements.entities.CriterionRequirement"/>
|
||||
</set>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
<!-- Inverse navigation from CriterionRequirement to Criterion -->
|
||||
<!-- Not indexed. Other side navigation not useful -->
|
||||
<many-to-one class="org.libreplan.business.resources.entities.Criterion" column="criterion_id"
|
||||
name="criterion"/>
|
||||
name="criterion" lazy="false"/>
|
||||
|
||||
<subclass discriminator-value="direct" name="DirectCriterionRequirement">
|
||||
<set access="field" name="children" cascade="delete-orphan" inverse="true" batch-size="10">
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
</set>
|
||||
|
||||
<!-- Index created in a database-object section -->
|
||||
<set name="profiles" table="user_profiles">
|
||||
<set name="profiles" table="user_profiles" lazy="false">
|
||||
<key column="user_id"/>
|
||||
<many-to-many column="profile_id" class="org.libreplan.business.users.entities.Profile"/>
|
||||
</set>
|
||||
|
|
@ -66,10 +66,22 @@
|
|||
|
||||
<property name="projectsFilterPeriodTo" column="projects_filter_period_to"/>
|
||||
|
||||
<property name="projectsFilterFinishedOn" column="projects_filter_finished_on"/>
|
||||
|
||||
<property name="resourcesLoadFilterPeriodSince" column="resources_load_filter_period_since"/>
|
||||
|
||||
<property name="resourcesLoadFilterPeriodTo" column="resources_load_filter_period_to"/>
|
||||
|
||||
<property name="showResourcesOn" column="show_resources_on"/>
|
||||
|
||||
<property name="showAdvancesOn" column="show_advances_on"/>
|
||||
|
||||
<property name="showReportedHoursOn" column="show_reported_hours_on"/>
|
||||
|
||||
<property name="showLabelsOn" column="show_labels_on"/>
|
||||
|
||||
<property name="showMoneyCostBarOn" column="show_money_cost_bar_on"/>
|
||||
|
||||
<many-to-one name="projectsFilterLabel" cascade="none" lazy="false" column="projects_filter_label_id" />
|
||||
|
||||
<many-to-one name="resourcesLoadFilterCriterion" cascade="none" lazy="false"
|
||||
|
|
@ -89,7 +101,7 @@
|
|||
<property name="profileName" not-null="true" unique="true" column="profile_name" />
|
||||
|
||||
<!-- Index created in a database-object section -->
|
||||
<set name="roles" table="profile_roles">
|
||||
<set name="roles" table="profile_roles" lazy="false">
|
||||
<key column="profile_id"/>
|
||||
<element column="role">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
|
|
|
|||
|
|
@ -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<TaskElement> 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() {
|
||||
|
|
|
|||
|
|
@ -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 <code>JobDetailFactoryBean</code> 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 {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <vova@libreplan-enterprise.com>
|
||||
*/
|
||||
|
||||
@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<EmailTemplate> emailTemplates;
|
||||
emailTemplates = emailTemplateModel.getAll();
|
||||
|
||||
private Worker getCurrentWorker(Long resourceID){
|
||||
List<Worker> 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<EmailTemplate> 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<String> getEndPoints() throws MalformedObjectNameException, NullPointerException, UnknownHostException,
|
||||
AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException {
|
||||
|
||||
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||
|
||||
Set<ObjectName> 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<String> endPoints = new ArrayList<String>();
|
||||
for (Iterator<ObjectName> 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<ConnectorProperty> 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<ConnectorProperty> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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<ResourceAllocation<?>> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<User> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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("");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<FilterPair> readProjectsParameters() {
|
||||
return (List<FilterPair>) 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<FilterPair> parameters) {
|
||||
Sessions.getCurrent().setAttribute("companyFilterLabel", parameters);
|
||||
}
|
||||
|
|
@ -83,12 +97,14 @@ public class FilterUtils {
|
|||
public static void writeProjectsFilter(Date startDate,
|
||||
Date endDate,
|
||||
List<FilterPair> 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<FilterPair> readOrderParameters(Order order) {
|
||||
return (List<FilterPair>) Sessions.getCurrent().getAttribute(order.getCode() + "-labelsandcriteriaFilter");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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<EmailNotification> getAllByProject(TaskElement taskElement) {
|
||||
return emailNotificationDAO.getAllByProject(taskElement);
|
||||
}
|
||||
@Override
|
||||
@Transactional
|
||||
public List<EmailNotification> 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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<EmailNotification> getAllByType(EmailTemplateEnum enumeration);
|
||||
|
||||
List<EmailNotification> getAllByProject(TaskElement taskElement);
|
||||
|
||||
List<EmailNotification> 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();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ public interface IOrderModel extends IIntegrationEntityModel {
|
|||
|
||||
List<Order> getOrders(Date startDate, Date endDate, List<Label> labels,
|
||||
List<Criterion> criteria, ExternalCompany customer,
|
||||
OrderStatusEnum state);
|
||||
OrderStatusEnum state, Boolean excludeFinishedProject);
|
||||
|
||||
void initEdit(Order order, Desktop desktop);
|
||||
|
||||
|
|
|
|||
|
|
@ -849,7 +849,6 @@ public class ManageOrderElementAdvancesController extends GenericForwardComposer
|
|||
this.manageOrderElementAdvancesModel.sortListAdvanceMeasurement();
|
||||
Util.reloadBindings(editAdvancesMeasurement);
|
||||
|
||||
this.setCurrentDate();
|
||||
this.setPercentage();
|
||||
this.setCurrentValue();
|
||||
Util.reloadBindings(chart);
|
||||
|
|
|
|||
|
|
@ -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<Criterion> criteria = new ArrayList<>();
|
||||
ExternalCompany customer = null;
|
||||
OrderStatusEnum state = null;
|
||||
//Boolean excludeFinishedProject = false;
|
||||
|
||||
for (FilterPair filterPair : (List<FilterPair>) 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<FilterPair> 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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Order> orderList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
|
|
@ -235,13 +241,13 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
|
|||
@Transactional(readOnly = true)
|
||||
public List<Order> getOrders(Date startDate, Date endDate,
|
||||
List<Label> labels, List<Criterion> criteria,
|
||||
ExternalCompany customer, OrderStatusEnum state) {
|
||||
ExternalCompany customer, OrderStatusEnum state, Boolean excludeFinishedProject) {
|
||||
getLabelsOnConversation().reattachLabels();
|
||||
List<Order> 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<Long, OrderVersion> versionsRemovedById = new HashMap<>();
|
||||
List<Scenario> currentAndDerived = currentAndDerivedScenarios();
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ public class ProjectDetailsController extends GenericForwardComposer<Component>
|
|||
|
||||
private Textbox txtName;
|
||||
|
||||
private Textbox txtDescription;
|
||||
|
||||
private Datebox deadline;
|
||||
|
||||
private Checkbox generateCode;
|
||||
|
|
|
|||
|
|
@ -56,12 +56,15 @@ public class TaskGroupPredicate implements IPredicate {
|
|||
|
||||
private String name;
|
||||
|
||||
private Boolean excludeFinishedProject;
|
||||
|
||||
public TaskGroupPredicate(List<FilterPair> 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;
|
||||
}
|
||||
|
||||
}
|
||||
public Boolean getExcludeFinishedProjects() {
|
||||
return excludeFinishedProject;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ public class CompanyPlanningController implements Composer {
|
|||
|
||||
private Textbox filterProjectName;
|
||||
|
||||
private Checkbox filterExcludeFinishedProject;
|
||||
|
||||
private BandboxMultipleSearch bdFilters;
|
||||
|
||||
private ICommandOnTask<TaskElement> 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<FilterPair> listFilters = (List<FilterPair>) 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) {
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
|
|||
|
||||
private LocalDate filterFinishDate;
|
||||
|
||||
private Boolean filterExcludeFinishedProject;
|
||||
|
||||
private static final class TaskElementNavigator implements IStructureNavigator<TaskElement> {
|
||||
|
||||
@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<TaskElement> 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<TaskElement> 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<org.libreplan.business.labels.entities.Label> labels = new ArrayList<>();
|
||||
List<Criterion> 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 <T> List<T> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<TaskElement> 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<TaskElement> configuration, Order order) {
|
||||
ZoomLevel sessionZoom = FilterUtils.readZoomLevel(order);
|
||||
if ( sessionZoom != null ) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -800,7 +800,7 @@ public class TaskPropertiesController extends GenericForwardComposer<Component>
|
|||
|
||||
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<Component>
|
|||
return this;
|
||||
}
|
||||
|
||||
public TaskElement getCurrentTaskElement() {
|
||||
return currentTaskElement;
|
||||
}
|
||||
|
||||
public void setCurrentTaskElement(TaskElement taskElement) {
|
||||
currentTaskElement = taskElement;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -609,7 +609,7 @@ public abstract class TreeController<T extends ITreeNode<T>> 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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
<config-name>i18n</config-name>
|
||||
<taglib>
|
||||
<taglib-uri>http://org.libreplan.web/i18n</taglib-uri>
|
||||
<taglib-location>libreplan-webapp/WEB-INF/tld/i18n.tld</taglib-location>
|
||||
<taglib-location>/metainfo/tld/i18n.tld</taglib-location>
|
||||
</taglib>
|
||||
</config>
|
||||
26
libreplan-webapp/src/main/resources/metainfo/tld/i18n.tld
Normal file
26
libreplan-webapp/src/main/resources/metainfo/tld/i18n.tld
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<taglib>
|
||||
<uri>http://org.libreplan.web/i18n</uri>
|
||||
<description>
|
||||
</description>
|
||||
<function>
|
||||
<name>_</name>
|
||||
<function-class>org.libreplan.web.I18nHelper</function-class>
|
||||
<function-signature>
|
||||
java.lang.String _(java.lang.String name)
|
||||
</function-signature>
|
||||
<description>
|
||||
</description>
|
||||
</function>
|
||||
|
||||
<!-- Pass one extra argument -->
|
||||
<function>
|
||||
<name>__</name>
|
||||
<function-class>org.libreplan.web.I18nHelper</function-class>
|
||||
<function-signature>
|
||||
java.lang.String _(java.lang.String name, java.lang.Object arg0)
|
||||
</function-signature>
|
||||
<description>
|
||||
</description>
|
||||
</function>
|
||||
</taglib>
|
||||
Binary file not shown.
|
|
@ -1,9 +1,5 @@
|
|||
<zk>
|
||||
<log>
|
||||
<log-base/>
|
||||
</log>
|
||||
|
||||
<desktop-config>
|
||||
<desktop-config>
|
||||
<!--
|
||||
Seconds it takes between requests for a desktop to be invalidated.
|
||||
A timer is introduced to avoid invalidation of pages still open.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<checkbox id="storedColumnVisible" label="${i18n:_('Show archived column data')}"
|
||||
checked="true" onCheck="dashboardControllerGlobal.showStoredColumn()"/>
|
||||
|
||||
<grid id="pipelineGrid" sclass="global-dashboard-grid">
|
||||
<grid id="pipelineGrid" sclass="global-dashboard-grid" height="500px">
|
||||
<columns>
|
||||
<column label="${i18n:_('PRE-SALES')}"/>
|
||||
<column label="${i18n:_('OFFERED')}"/>
|
||||
|
|
|
|||
|
|
@ -118,6 +118,11 @@
|
|||
<label value="{url}"/>
|
||||
<label value="${i18n:_('Welcome page')}"/>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<label value="{projecturl}"/>
|
||||
<label value="${i18n:_('Project details page')}"/>
|
||||
</row>
|
||||
</rows>
|
||||
|
||||
</grid>
|
||||
|
|
|
|||
|
|
@ -121,6 +121,35 @@
|
|||
</rows>
|
||||
</grid>
|
||||
</row>
|
||||
<row>
|
||||
<label value="${i18n:_('Planning view modes on')}" />
|
||||
<grid>
|
||||
<columns>
|
||||
<column />
|
||||
<column />
|
||||
<column />
|
||||
</columns>
|
||||
<rows>
|
||||
<row>
|
||||
<checkbox id="showResourcesOn"
|
||||
label="${i18n:_('Show resources')}"
|
||||
checked="@{settingsController.showResourcesOn}"/>
|
||||
<checkbox id="showAdvancesOn"
|
||||
label="${i18n:_('Show progress')}"
|
||||
checked="@{settingsController.showAdvancesOn}"/>
|
||||
<checkbox id="showReportedHoursOn"
|
||||
label="${i18n:_('Show reported hours')}"
|
||||
checked="@{settingsController.showReportedHoursOn}"/>
|
||||
<checkbox id="showLabelsOn"
|
||||
label="${i18n:_('Show labels')}"
|
||||
checked="@{settingsController.showLabelsOn}"/>
|
||||
<checkbox id="showMoneyCostBarOn"
|
||||
label="${i18n:_('Show money cost bar')}"
|
||||
checked="@{settingsController.showMoneyCostBarOn}"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</row>
|
||||
<row>
|
||||
<label value="${i18n:_('Projects view filtering')}" />
|
||||
<hbox>
|
||||
|
|
@ -143,6 +172,9 @@
|
|||
value="@{settingsController.projectsFilterPeriodTo}"
|
||||
width="50px"
|
||||
constraint="@{settingsController.checkMonthsMaxValue}"/>
|
||||
<checkbox id="projectsFilterFinishedOn"
|
||||
label="${i18n:_('Exclude finished projects')}"
|
||||
checked="@{settingsController.projectsFilterFinishedOn}"/>
|
||||
</hbox>
|
||||
</row>
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@
|
|||
sort="auto(initDate,deadline)" sortDirection="ascending" sclass="date" hflex="min"/>
|
||||
<column label="${i18n:_('Deadline')}" sort="auto(deadline,initDate)" align="center" sclass="date" hflex="min"/>
|
||||
<column label="${i18n:_('Customer')}" sort="auto(customerReference)" hflex="min"/>
|
||||
<column label="${i18n:_('Total Budget')}" sort="auto(totalBudget)" align="right" hflex="min"/>
|
||||
<column label="${i18n:_('Total Budget')}" sort="auto(totalManualBudget)" align="right" hflex="min"/>
|
||||
<column label="${i18n:_('Planned Budget')}" sort="auto(totalBudget)" align="right" hflex="min"/>
|
||||
<column label="${i18n:_('Hours')}" sort="auto(totalHours)" align="right" hflex="min"/>
|
||||
<column label="${i18n:_('State')}" sort="auto(totalBudget)" align="center" hflex="min"/>
|
||||
<column label="${i18n:_('State')}" sort="auto(lower(state))" align="center" hflex="min"/>
|
||||
<column label="${i18n:_('Operations')}" sclass="operations" width="120px"/>
|
||||
</columns>
|
||||
</grid>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
tooltiptext="${i18n:_('Select required criteria set and press filter button')}"/>
|
||||
|
||||
<textbox id="filterProjectName" width="100px"
|
||||
onChange="orderFilterController.onApplyFilter()" />
|
||||
onChange="orderFilterController.onApplyFilter()"
|
||||
onOK="orderFilterController.onApplyFilter()" />
|
||||
|
||||
<label value=" ${i18n:_('with')}" />
|
||||
|
||||
|
|
@ -41,6 +42,11 @@
|
|||
<datebox id="filterFinishDate" constraint = "@{orderFilterController.checkConstraintFinishDate}"
|
||||
onChange="orderFilterController.onApplyFilter()"/>
|
||||
|
||||
<label value=" ${i18n:_('Exclude finished projects')}" />
|
||||
|
||||
<checkbox id="filterExcludeFinishedProject"
|
||||
onChange="orderFilterController.onApplyFilter()"/>
|
||||
|
||||
<button mold="trendy" image="/common/img/ico_filter.png" style="margin-top: -4px"
|
||||
tooltiptext="${i18n:_('Apply filtering to tasks satisfying required criteria')}"
|
||||
onClick="orderFilterController.onApplyFilter()"/>
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@
|
|||
<textbox id="txtName" value="@{projectController.order.name}" width="500px"
|
||||
constraint="no empty:${i18n:_('cannot be empty')}"
|
||||
onOK="projectController.accept();"/>
|
||||
</row>
|
||||
<row>
|
||||
<label value="${i18n:_('Description')}" />
|
||||
<textbox id="txtDescription" value="@{projectController.order.description}" width="500px" rows="7"/>
|
||||
</row>
|
||||
<row>
|
||||
<label value="${i18n:_('Template')}" />
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package org.libreplan.web.test.ws.email;
|
|||
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.libreplan.business.common.Registry;
|
||||
|
|
@ -167,6 +169,20 @@ public class EmailTest {
|
|||
assertTrue(EmailConnectionValidator.exceptionType instanceof MessagingException);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testDDeleteEmailNotification() {
|
||||
EmailTemplate emailTemplate = createEmailTemplate();
|
||||
emailTemplateDAO.save(emailTemplate);
|
||||
|
||||
EmailNotification emailNotification = createEmailNotification();
|
||||
emailNotificationDAO.save(emailNotification);
|
||||
|
||||
emailTemplateDAO.delete(emailTemplate);
|
||||
boolean result = emailNotificationDAO.deleteByProject(emailNotification.getProject());
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
private EmailTemplate createEmailTemplate() {
|
||||
EmailTemplate emailTemplate = new EmailTemplate();
|
||||
emailTemplate.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START);
|
||||
|
|
|
|||
6
pom.xml
6
pom.xml
|
|
@ -866,6 +866,12 @@
|
|||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.21</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue