Merge branch 'master' into tim-connector

This commit is contained in:
Manuel Rego Casasnovas 2013-03-27 10:30:45 +01:00
commit 28e56f8ae1
77 changed files with 15930 additions and 4063 deletions

View file

@ -51,6 +51,7 @@ Translators
Helena Grosso <lenagrosso@gmail.com>,
Joaquim Rocha <jrocha@igalia.com>
* [ru] Pavel Rudensky <prudensky@gmail.com>
* [zh] Swanson Chan <lacidophilin@yahoo.com>
Contributors

View file

@ -86,6 +86,7 @@ Translators
Helena Grosso <lenagrosso@gmail.com>,
Joaquim Rocha <jrocha@igalia.com>
* [ru] Pavel Rudensky <prudensky@gmail.com>
* [zh] Swanson Chan <lacidophilin@yahoo.com>
Contributors
------------

View file

@ -86,6 +86,7 @@ Traductores
Helena Grosso <lenagrosso@gmail.com>,
Joaquim Rocha <jrocha@igalia.com>
* [ru] Pavel Rudensky <prudensky@gmail.com>
* [zh] Swanson Chan <lacidophilin@yahoo.com>
Contribuidores
--------------

View file

@ -86,6 +86,7 @@ Traductores
Helena Grosso <lenagrosso@gmail.com>,
Joaquim Rocha <jrocha@igalia.com>
* [ru] Pavel Rudensky <prudensky@gmail.com>
* [zh] Swanson Chan <lacidophilin@yahoo.com>
Contribuidores
--------------

View file

@ -144,8 +144,6 @@ public class Planner extends HtmlMacroComponent {
private GanttPanel ganttPanel;
private boolean fixedZoomByUser = false;
private List<? extends CommandContextualized<?>> contextualizedGlobalCommands;
private CommandContextualized<?> goingDownInLastArrowCommand;
@ -174,7 +172,7 @@ public class Planner extends HtmlMacroComponent {
private boolean isFlattenTree = false;
private ZoomLevel initialZoomLevel = null;
private ZoomLevel zoomLevel = null;
private Listbox listZoomLevels = null;
@ -276,8 +274,7 @@ public class Planner extends HtmlMacroComponent {
if (ganttPanel == null) {
return;
}
this.fixedZoomByUser = true;
initialZoomLevel = zoomLevel;
this.zoomLevel = zoomLevel;
ganttPanel.setZoomLevel(zoomLevel, scrollLeft);
}
@ -732,22 +729,14 @@ public class Planner extends HtmlMacroComponent {
public ZoomLevel getZoomLevel() {
if (ganttPanel == null) {
return initialZoomLevel != null ? initialZoomLevel
return zoomLevel != null ? zoomLevel
: ZoomLevel.DETAIL_ONE;
}
return ganttPanel.getTimeTracker().getDetailLevel();
}
public boolean isFixedZoomByUser() {
return this.fixedZoomByUser;
}
public void setInitialZoomLevel(final ZoomLevel zoomLevel) {
if (this.initialZoomLevel != null) {
// already initialized
return;
}
this.initialZoomLevel = zoomLevel;
this.zoomLevel = zoomLevel;
}
public boolean areContainersExpandedByDefault() {
@ -821,13 +810,12 @@ public class Planner extends HtmlMacroComponent {
}
public void updateSelectedZoomLevel() {
if (!isFixedZoomByUser()) {
ganttPanel.getTimeTracker().setZoomLevel(zoomLevel);
Listitem selectedItem = (Listitem) listZoomLevels.getItems().get(
initialZoomLevel.ordinal());
zoomLevel.ordinal());
listZoomLevels.setSelectedItem(selectedItem);
listZoomLevels.invalidate();
}
}
public IContext<?> getContext() {
return context;

View file

@ -0,0 +1,249 @@
# LibrePlan - GanttZK module.
# Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
# Desenvolvemento Tecnolóxico de Galicia
# Copyright (C) 2010-2012 Igalia, S.L.
# This file is distributed under the same license as the LibrePlan package.
#
# Translators:
# Swanson Chan <lacidophilin@yahoo.com>, 2013.
msgid ""
msgstr ""
"Project-Id-Version: libreplan-1.3.3\n"
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
"POT-Creation-Date: 2012-12-07 13:59+0100\n"
"PO-Revision-Date: 2013-03-09 07:49+0000\n"
"Last-Translator: Swanson Chan <lacidophilin@yahoo.com>\n"
"Language-Team: 中文\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
msgid "Erase"
msgstr "抹去"
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
msgid "Add Dependency"
msgstr "添加依赖关系"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
msgid "Worker"
msgstr "工人"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:689
msgid "Show money cost bar"
msgstr "显示资金成本栏"
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
msgid "Start"
msgstr "开始"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
msgid "Show reported hours"
msgstr "节目报道小时"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:85
msgid "Show/Hide reported hours"
msgstr "报告显示/隐藏小时"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:35
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:49
msgid "Zoom"
msgstr "放大"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:67
msgid "The specified dependency is not allowed"
msgstr "不允许指定的依赖"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:255
msgid "Set End-End"
msgstr "设置端到端"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:78
msgid "Show/Hide progress"
msgstr "显示/隐藏进度"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
msgid "Task"
msgstr "任务"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:199
msgid "available effort: {0}, assigned effort: {1}"
msgstr "可用的努力:{0},分配的努力:{1}"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:64
msgid "Criterion"
msgstr "标准"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:695
msgid "Hide money cost bar"
msgstr "隐藏资金成本吧"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
msgid "Print"
msgstr "打印"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:71
msgid "Week"
msgstr "周"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:501
msgid "filtering by name"
msgstr "过滤名称"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadLeftPane.java:111
msgid "See scheduling"
msgstr "见调度"
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:30
msgid "End"
msgstr "结束"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:89
msgid "Resources"
msgstr "资源"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/TimeTracker.java:243
msgid "changing zoom"
msgstr "改变变焦"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
msgid "Show/Hide money cost bar"
msgstr "显示/隐藏资金成本吧"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:47
msgid "Group by"
msgstr "集团通过"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:90
msgid "Generic allocation criteria"
msgstr "通用的分配标准"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
msgid "Quarter"
msgstr "季"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:43
msgid "Page"
msgstr "页"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
msgid "None"
msgstr "无"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:71
msgid "Flatten/Unflatten tree"
msgstr "拼合/ Unflatten树的"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
msgid "Project"
msgstr "项目"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:67
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:28
msgid "Name"
msgstr "名称"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:645
msgid "Show progress"
msgstr "显示进度"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:67
msgid "Expand/Collapse all"
msgstr "展开/收起所有"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:58
msgid "Show/Hide critical path"
msgstr "显示/隐藏关键路径"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "年"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
msgid "showing criteria"
msgstr "显示标准"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
msgid "Month"
msgstr "月"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:64
msgid "Show/Hide resources"
msgstr "显示/隐藏资源"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:247
msgid "Set End-Start"
msgstr "设置结束开始"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:309
msgid "decreasing zoom"
msgstr "减少变焦"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:625
msgid "Hide critical path"
msgstr "隐藏关键路径"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:84
msgid "Day"
msgstr "日"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:675
msgid "Hide reported hours"
msgstr "隐藏报道小时"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:193
msgid "Load: {0}%"
msgstr "负载:{0}"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:147
msgid "showing resources"
msgstr "显示资源"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:61
msgid "Show/Hide labels"
msgstr "显示/隐藏标签"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:97
msgid "Hour"
msgstr "小时"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
msgid "Graphics"
msgstr "图像"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:251
msgid "Set Start-Start"
msgstr "设置开始启动"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:152
msgid "See resource allocation"
msgstr "资源分配"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:292
msgid "increasing zoom"
msgstr "增加变焦"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:467
msgid "Show all elements"
msgstr "显示所有元素"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:466
msgid "All"
msgstr "所有"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:38
msgid "Refresh"
msgstr "刷新"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620
msgid "Show critical path"
msgstr "显示关键路径"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:653
msgid "Hide progress"
msgstr "隐藏进度"

View file

@ -132,4 +132,8 @@ public class Label extends IntegrationEntity implements Comparable<Label> {
return getTypeAndName().compareToIgnoreCase(o.getTypeAndName());
}
public String getFinderPattern() {
return String.format("%s ( %s )", name, type.getName());
}
}

View file

@ -26,8 +26,11 @@ import java.util.List;
import org.libreplan.business.common.daos.IIntegrationEntityDAO;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.reports.dtos.CostExpenseSheetDTO;
import org.libreplan.business.reports.dtos.OrderCostsPerResourceDTO;
@ -79,6 +82,11 @@ public interface IOrderDAO extends IIntegrationEntityDAO<Order> {
List<Order> getOrdersByReadAuthorizationByScenario(String username,
Scenario scenario);
List<Order> getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
String username, Scenario scenario, Date startDate, Date endDate,
List<Label> labels, List<Criterion> criteria,
ExternalCompany customer, OrderStatusEnum state);
/**
* Returns the order filtered by the name. If name is blank (whitespace,
* empty ("") or null, it throws <code>InstanceNotFoundException</code>.

View file

@ -38,9 +38,12 @@ import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.costcategories.daos.CostCategoryDAO;
import org.libreplan.business.costcategories.daos.ITypeOfWorkHoursDAO;
import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.orders.entities.SchedulingState;
import org.libreplan.business.planner.daos.ITaskSourceDAO;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.reports.dtos.CostExpenseSheetDTO;
@ -214,6 +217,242 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements
}
}
private List<Order> getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
User user, Date startDate, Date endDate, List<Label> labels,
List<Criterion> criteria, ExternalCompany customer,
OrderStatusEnum state) {
List<Long> ordersIdsFiltered = getOrdersIdsFiltered(user, labels,
criteria, customer, state);
if (ordersIdsFiltered != null && ordersIdsFiltered.isEmpty()) {
return Collections.emptyList();
}
List<Long> ordersIdsByDates = getOrdersIdsByDates(startDate, endDate);
if (ordersIdsByDates != null && ordersIdsByDates.isEmpty()) {
return Collections.emptyList();
}
List<Long> ordersIdsUnscheduled = getOrdersIdsUnscheduled(startDate,
endDate);
Criteria c = getSession().createCriteria(Order.class);
if (ordersIdsFiltered != null && ordersIdsByDates != null) {
org.hibernate.criterion.Criterion and = Restrictions.and(
Restrictions.in("id", ordersIdsFiltered),
Restrictions.in("id", ordersIdsByDates));
c.add(and);
} else {
if (ordersIdsFiltered != null) {
c.add(Restrictions.in("id", ordersIdsFiltered));
}
if (ordersIdsByDates != null) {
if (ordersIdsUnscheduled.isEmpty()) {
c.add(Restrictions.in("id", ordersIdsByDates));
} else {
c.add(Restrictions.or(
Restrictions.in("id", ordersIdsByDates),
Restrictions.in("id", ordersIdsUnscheduled)));
}
}
}
c.addOrder(org.hibernate.criterion.Order.desc("initDate"));
c.addOrder(org.hibernate.criterion.Order.asc("infoComponent.name"));
return c.list();
}
private List<Long> getOrdersIdsUnscheduled(Date startDate, Date endDate) {
String strQuery = "SELECT s.orderElement.id "
+ "FROM SchedulingDataForVersion s "
+ "WHERE s.schedulingStateType = :type";
Query query = getSession().createQuery(strQuery);
query.setParameter("type", SchedulingState.Type.NO_SCHEDULED);
List<Long> ordersIdsUnscheduled = query.list();
if (ordersIdsUnscheduled.isEmpty()) {
return Collections.emptyList();
}
String strQueryDates = "SELECT o.id "
+ "FROM Order o "
+ "WHERE o.id IN (:ids) ";
if (startDate != null) {
strQueryDates += "AND o.initDate >= :startDate ";
}
if (endDate != null) {
strQueryDates += "AND o.initDate <= :endDate ";
}
Query queryDates = getSession().createQuery(strQueryDates);
if (startDate != null) {
queryDates.setParameter("startDate", startDate);
}
if (endDate != null) {
queryDates.setParameter("endDate", endDate);
}
queryDates.setParameterList("ids", ordersIdsUnscheduled);
return queryDates.list();
}
/**
* If both params are <code>null</code> it returns <code>null</code>.
* Otherwise it filters the list of tasks to return the ones wihtout parent
* between the dates.
*/
private List<Long> getOrdersIdsByDates(Date startDate, Date endDate) {
if (startDate == null && endDate == null) {
return null;
}
String strQuery = "SELECT t.taskSource.schedulingData.orderElement.id "
+ "FROM TaskElement t "
+ "WHERE t.parent IS NULL ";
if (endDate != null) {
strQuery += "AND t.startDate.date <= :endDate ";
}
if (startDate != null) {
strQuery += "AND t.endDate.date >= :startDate ";
}
Query query = getSession().createQuery(strQuery);
if (startDate != null) {
query.setParameter("startDate", LocalDate.fromDateFields(startDate));
}
if (endDate != null) {
query.setParameter("endDate", LocalDate.fromDateFields(endDate));
}
return query.list();
}
/**
* If user has permissions over all orders and not filters are passed it
* returns <code>null</code>. Otherwise, it returns the list of orders
* identifiers for which the user has read permissions and the filters pass.
*/
private List<Long> getOrdersIdsFiltered(User user, List<Label> labels,
List<Criterion> criteria, ExternalCompany customer,
OrderStatusEnum state) {
List<Long> ordersIdsByReadAuthorization = getOrdersIdsByReadAuthorization(user);
String strQuery = "SELECT o.id ";
strQuery += "FROM Order o ";
String where = "";
String whereFinal = "";
if (labels != null && !labels.isEmpty()) {
for (int i = 0; i < labels.size(); i++) {
if (where.isEmpty()) {
where += "WHERE ";
} else {
where += "AND ";
}
where += ":label" + i + " IN elements(o.labels) ";
}
}
if (criteria != null && !criteria.isEmpty()) {
strQuery += "JOIN o.criterionRequirements cr ";
if (where.isEmpty()) {
where += "WHERE ";
} else {
where += "AND ";
}
where += "cr.criterion IN (:criteria) ";
where += "AND cr.class = DirectCriterionRequirement ";
whereFinal += "GROUP BY o.id ";
whereFinal += "HAVING count(o.id) = :criteriaSize ";
}
if (customer != null) {
if (where.isEmpty()) {
where += "WHERE ";
} else {
where += "AND ";
}
where += "o.customer = :customer ";
}
if (state != null) {
if (where.isEmpty()) {
where += "WHERE ";
} else {
where += "AND ";
}
where += "o.state = :state ";
}
// If not restrictions by labels, criteria, customer or state
if (where.isEmpty()) {
return ordersIdsByReadAuthorization;
}
if (ordersIdsByReadAuthorization != null
&& !ordersIdsByReadAuthorization.isEmpty()) {
if (where.isEmpty()) {
where += "WHERE ";
} else {
where += "AND ";
}
where += "o.id IN (:ids) ";
}
strQuery += where + whereFinal;
Query query = getSession().createQuery(strQuery);
if (labels != null && !labels.isEmpty()) {
int i = 0;
for (Label label : labels) {
query.setParameter("label" + i, label);
i++;
}
}
if (criteria != null && !criteria.isEmpty()) {
query.setParameterList("criteria", criteria);
query.setParameter("criteriaSize", (long) criteria.size());
}
if (customer != null) {
query.setParameter("customer", customer);
}
if (state != null) {
query.setParameter("state", state);
}
if (ordersIdsByReadAuthorization != null
&& !ordersIdsByReadAuthorization.isEmpty()) {
query.setParameterList("ids", ordersIdsByReadAuthorization);
}
return query.list();
}
/**
* If user has permissions over all orders it returns <code>null</code>.
* Otherwise, it returns the list of orders identifiers for which the user
* has read permissions.
*/
private List<Long> getOrdersIdsByReadAuthorization(User user) {
if (user.isInRole(UserRole.ROLE_SUPERUSER)
|| user.isInRole(UserRole.ROLE_READ_ALL_PROJECTS)
|| user.isInRole(UserRole.ROLE_EDIT_ALL_PROJECTS)) {
return null;
} else {
String strQuery = "SELECT oa.order.id "
+ "FROM OrderAuthorization oa "
+ "WHERE oa.user = :user "
+ "OR oa.profile IN (:profiles) ";
Query query = getSession().createQuery(strQuery);
query.setParameter("user", user);
query.setParameterList("profiles", user.getProfiles());
return query.list();
}
}
@Override
public List<Order> getOrdersByWriteAuthorization(User user) {
if (user.isInRole(UserRole.ROLE_SUPERUSER)
@ -278,6 +517,23 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements
return existsInScenario(getOrdersByReadAuthorization(user), scenario);
}
@Override
public List<Order> getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
String username, Scenario scenario, Date startDate, Date endDate,
List<Label> labels, List<Criterion> criteria,
ExternalCompany customer, OrderStatusEnum state) {
User user;
try {
user = userDAO.findByLoginName(username);
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
return existsInScenario(
getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
user, startDate, endDate, labels, criteria, customer,
state), scenario);
}
private List<Order> existsInScenario(List<Order> orders, Scenario scenario) {
List<Order> result = new ArrayList<Order>();
for (Order each : orders) {

View file

@ -1689,4 +1689,8 @@ public abstract class OrderElement extends IntegrationEntity implements
return code.startsWith(PredefinedConnectorProperties.JIRA_CODE_PREFIX);
}
public boolean isConvertedToContainer() {
return false;
}
}

View file

@ -88,6 +88,8 @@ public class OrderLine extends OrderElement {
private Integer lastHoursGroupSequenceCode = 0;
private boolean convertedToContainer = false;
@Override
public Integer getWorkHours() {
return hoursGroupOrderLineHandler.calculateTotalHours(hoursGroups);
@ -156,6 +158,7 @@ public class OrderLine extends OrderElement {
result.setName(getName());
setCode("");
setName("");
convertedToContainer = true;
return result;
}
@ -392,4 +395,9 @@ public class OrderLine extends OrderElement {
return budget;
}
@Override
public boolean isConvertedToContainer() {
return convertedToContainer;
}
}

View file

@ -23,6 +23,8 @@ package org.libreplan.business.orders.entities;
import static org.libreplan.business.i18n.I18nHelper._;
import java.util.EnumSet;
/**
* @author Susana Montes Pedreiera <smotnes@wirelessgalicia.com>
@ -53,4 +55,12 @@ public enum OrderStatusEnum {
public static OrderStatusEnum getDefault() {
return PRE_SALES;
}
public static EnumSet<OrderStatusEnum> getVisibleStatus() {
return EnumSet.of(OrderStatusEnum.PRE_SALES, OrderStatusEnum.OFFERED,
OrderStatusEnum.OUTSOURCED, OrderStatusEnum.ACCEPTED,
OrderStatusEnum.STARTED, OrderStatusEnum.ON_HOLD,
OrderStatusEnum.FINISHED);
}
}

View file

@ -46,6 +46,7 @@ import org.springframework.stereotype.Repository;
*
* @author Diego Pino García <dpino@igalia.com>
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*/
@Repository
@Scope(BeanDefinition.SCOPE_SINGLETON)
@ -63,30 +64,46 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
@Override
public List<DayAssignment> getAllFor(Scenario scenario) {
List<DayAssignment> result = new ArrayList<DayAssignment>();
result.addAll(getSpecific(scenario, null, null));
result.addAll(getGeneric(scenario, null, null));
result.addAll(getDerived(scenario, null, null));
result.addAll(getSpecific(scenario, null, null, null));
result.addAll(getGeneric(scenario, null, null, null));
result.addAll(getDerived(scenario, null, null, null));
return result;
}
@Override
public List<DayAssignment> getAllFor(Scenario scenario, LocalDate init,
LocalDate end) {
List<DayAssignment> result = new ArrayList<DayAssignment>();
result.addAll(getSpecific(scenario, init, end));
result.addAll(getGeneric(scenario, init, end));
result.addAll(getDerived(scenario, init, end));
result.addAll(getSpecific(scenario, init, end, null));
result.addAll(getGeneric(scenario, init, end, null));
result.addAll(getDerived(scenario, init, end, null));
return result;
}
@Override
public List<DayAssignment> getAllFor(Scenario scenario,
LocalDate startDateInclusive, LocalDate endDateInclusive,
Resource resource) {
List<DayAssignment> result = new ArrayList<DayAssignment>();
result.addAll(getSpecific(scenario, startDateInclusive,
endDateInclusive, resource));
result.addAll(getGeneric(scenario, startDateInclusive,
endDateInclusive, resource));
result.addAll(getDerived(scenario, startDateInclusive,
endDateInclusive, resource));
return result;
}
private List<DerivedDayAssignment> getDerived(Scenario scenario,
LocalDate initInclusive, LocalDate endInclusive) {
LocalDate initInclusive, LocalDate endInclusive, Resource resource) {
String queryString = "select d from DerivedDayAssignmentsContainer c "
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
+ addQueryConditionForInitAndEndDate(initInclusive,
endInclusive);
endInclusive) + addQueryConditionsForResource(resource);
Query query = getSession().createQuery(queryString);
query = query.setParameter("scenario", scenario);
addInitAndEndParameters(query, initInclusive, endInclusive);
addResourceParameter(query, resource);
return query.list();
}
@ -98,6 +115,10 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
return initCondition + endCondition;
}
private String addQueryConditionsForResource(Resource resource) {
return resource != null ? " and d.resource = :resource " : "";
}
private Query addInitAndEndParameters(Query query, LocalDate initInclusive,
LocalDate endInclusive) {
if (initInclusive != null) {
@ -109,30 +130,38 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
return query;
}
private Query addResourceParameter(Query query, Resource resource) {
return resource != null ? query.setParameter("resource", resource)
: query;
}
private List<GenericDayAssignment> getGeneric(Scenario scenario,
LocalDate initInclusive, LocalDate endInclusive) {
LocalDate initInclusive, LocalDate endInclusive, Resource resource) {
String queryString = "select d from GenericDayAssignmentsContainer c "
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
+ addQueryConditionForInitAndEndDate(initInclusive,
endInclusive);
endInclusive) + addQueryConditionsForResource(resource);
Query query = getSession().createQuery(queryString).setParameter(
"scenario", scenario);
query = addInitAndEndParameters(query, initInclusive, endInclusive);
addInitAndEndParameters(query, initInclusive, endInclusive);
addResourceParameter(query, resource);
return query.list();
}
private List<SpecificDayAssignment> getSpecific(Scenario scenario,
LocalDate initInclusive, LocalDate endInclusive) {
LocalDate initInclusive, LocalDate endInclusive, Resource resource) {
String queryString = "select d from SpecificDayAssignmentsContainer c "
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
+ addQueryConditionForInitAndEndDate(initInclusive,
endInclusive);
endInclusive) + addQueryConditionsForResource(resource);
Query query = getSession().createQuery(queryString).setParameter(
"scenario", scenario);
query = addInitAndEndParameters(query, initInclusive, endInclusive);
addInitAndEndParameters(query, initInclusive, endInclusive);
addResourceParameter(query, resource);
return query.list();
}
@Override
@SuppressWarnings("unchecked")
public List<DayAssignment> listFilteredByDate(LocalDate init, LocalDate end) {
Criteria criteria = getSession().createCriteria(DayAssignment.class);
@ -164,7 +193,7 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
}
Criteria criteria = getSession().createCriteria(DayAssignment.class)
.add(Restrictions.in("resource", resources));
return (List<DayAssignment>) criteria.list();
return criteria.list();
}
}

View file

@ -34,8 +34,9 @@ import org.libreplan.business.scenarios.entities.Scenario;
/**
* DAO interface for {@link DayAssignment}
*
* @author @author Diego Pino García <dpino@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*/
public interface IDayAssignmentDAO extends IGenericDAO<DayAssignment, Long> {
@ -47,6 +48,10 @@ public interface IDayAssignmentDAO extends IGenericDAO<DayAssignment, Long> {
public List<DayAssignment> getAllFor(Scenario scenario,
LocalDate initInclusive, LocalDate endInclusive);
public List<DayAssignment> getAllFor(Scenario scenario,
LocalDate startDateInclusive, LocalDate endDateInclusive,
Resource resource);
List<DayAssignment> listFilteredByDate(LocalDate init, LocalDate end);
public List<DayAssignment> findByResources(Scenario scenario, List<Resource> resources);

View file

@ -0,0 +1,80 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2012 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.business.resources.daos;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.workingday.EffortDuration;
/**
* Specifies the method to calculate the load ratios of a resource and the data
* type which represents the output
*
* @author Javier Moran Rua <jmoran@igalia.com>
*
*/
public interface IResourceLoadRatiosCalculator {
public interface ILoadRatiosDataType {
EffortDuration getLoad();
EffortDuration getOverload();
EffortDuration getCapacity();
/**
* Calculates the overtime ratio. The overtime ratio is defined as
* overload / (load+overload).
*
* @return the overtime ratio represented with a {@link BigDecimal} with
* scale of 2. If both load and overload are zero it is returned
* zero.
*/
BigDecimal getOvertimeRatio();
/**
* Calculates the availability ratio. The availability ratio is defined
* as 1 - (load/capacity)*100. It is a percentage.
*
* @return the availability ratio represented with a {@link BigDecimal}
* with a scale of 2. In the case that the capacity is zero, a
* 0% of availability is returned.
*/
BigDecimal getAvailiabilityRatio();
}
/**
* Calculates the load ratios of a resource between two dates in the
* escenario specified.
*
* @param resource
* @param startDate
* @param endDate
* @return the load ratios calculated.
*/
ILoadRatiosDataType calculateLoadRatios(Resource resource,
LocalDate startDate,
LocalDate endDate, Scenario scenario);
}

View file

@ -0,0 +1,218 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2012 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.business.resources.daos;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.joda.time.LocalDate;
import org.libreplan.business.common.IAdHocTransactionService;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.planner.daos.IDayAssignmentDAO;
import org.libreplan.business.planner.entities.DayAssignment;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate.PartialDay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
/**
* Class designed to be used as a singleton spring bean implementing the
* {@link IResourceLoadRatiosCalculator} interface.
*
* Spawns a new Hibernate transaction using {@link IAdHocTransactionService} to
* access the database.
*
* @author Javier Moran Rua <jmoran@igalia.com>
*
*/
@Service
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class ResourceLoadRatiosCalculator implements
IResourceLoadRatiosCalculator {
@Autowired
private IDayAssignmentDAO dayAssigmentDAO;
@Autowired
private IResourceDAO resourceDAO;
@Autowired
private IAdHocTransactionService adHocTransactionService;
private static class LoadRatiosDataType implements
IResourceLoadRatiosCalculator.ILoadRatiosDataType {
private EffortDuration load;
private EffortDuration overload;
private EffortDuration capacity;
public LoadRatiosDataType(EffortDuration load, EffortDuration overload,
EffortDuration capacity) {
this.load = load;
this.overload = overload;
this.capacity = capacity;
}
@Override
public EffortDuration getLoad() {
return this.load;
}
@Override
public EffortDuration getOverload() {
return this.overload;
}
@Override
public EffortDuration getCapacity() {
return this.capacity;
}
@Override
public BigDecimal getOvertimeRatio() {
BigDecimal result;
if (this.load.isZero() && this.overload.isZero()) {
result = BigDecimal.ZERO;
} else {
result = this.overload.dividedByAndResultAsBigDecimal(this.load
.plus(this.capacity));
}
return result.setScale(2, BigDecimal.ROUND_HALF_UP);
}
@Override
public BigDecimal getAvailiabilityRatio() {
BigDecimal result;
if (this.capacity.isZero()) {
result = BigDecimal.ZERO;
} else {
result = BigDecimal.ONE.subtract(this.load
.dividedByAndResultAsBigDecimal(this.capacity));
if (result.compareTo(BigDecimal.ZERO) < 0) {
result = BigDecimal.ZERO;
}
}
return result.setScale(2, BigDecimal.ROUND_HALF_UP);
}
}
@Override
public ILoadRatiosDataType calculateLoadRatios(final Resource resource,
final LocalDate startDate, final LocalDate endDate,
final Scenario scenario) {
return adHocTransactionService
.runOnReadOnlyTransaction(new IOnTransaction<LoadRatiosDataType>() {
@Override
@SuppressWarnings("unchecked")
public LoadRatiosDataType execute() {
resourceDAO.reattach(resource);
EffortDuration totalLoad = EffortDuration.zero(),
totalOverload = EffortDuration.zero(),
totalCapacity = EffortDuration.zero();
for (Map.Entry<LocalDate, EffortDuration> each :
getAllEffortPerDateFor(scenario,
startDate, endDate, resource)
.entrySet()) {
totalLoad = addLoad(totalLoad, each.getValue());
totalOverload = addOverload(totalOverload,
resource, each.getValue(), each.getKey());
}
totalCapacity = calculateTotalCapacity(resource,
startDate, endDate);
return new LoadRatiosDataType(totalLoad,
totalOverload, totalCapacity);
}
private Map<LocalDate,EffortDuration>
getAllEffortPerDateFor(Scenario scenario,LocalDate startDate,
LocalDate endDate, Resource resource) {
HashMap<LocalDate, EffortDuration> result =
new HashMap<LocalDate, EffortDuration>();
List<DayAssignment> l = dayAssigmentDAO.getAllFor(
scenario, startDate, endDate,
resource);
EffortDuration newValue = EffortDuration.zero();
for (DayAssignment each: l) {
if (result.containsKey(each.getDay())) {
newValue = result.get(each.getDay()).
plus(each.getDuration());
} else {
newValue = each.getDuration();
}
result.put(each.getDay(), newValue);
}
return result;
}
private EffortDuration addLoad(EffortDuration currentLoad,
EffortDuration load) {
return currentLoad.plus(load);
}
private EffortDuration calculateTotalCapacity(
Resource resource, LocalDate startDate,
LocalDate endDate) {
return resource.getCalendar().getWorkableDuration(
startDate, endDate);
}
private EffortDuration addOverload(
EffortDuration currentOverload, Resource resource,
EffortDuration loadAtDate, LocalDate date) {
EffortDuration result;
EffortDuration capacityAtDay = getCapacityAtDate(
resource, date);
if (capacityAtDay.compareTo(loadAtDate) < 0) {
result = currentOverload.plus(loadAtDate
.minus(capacityAtDay));
} else {
result = currentOverload;
}
return result;
}
private EffortDuration getCapacityAtDate(Resource resource,
LocalDate date) {
return resource.getCalendar().getCapacityOn(
PartialDay.wholeDay(date));
}
});
}
}

View file

@ -466,6 +466,10 @@ public class Criterion extends IntegrationEntity implements ICriterion,
return String.format("%s :: %s", type, name);
}
public String getFinderPattern() {
return String.format("%s ( %s )", name, type.getName());
}
@Override
public int compareTo(Criterion o) {
return toString().compareToIgnoreCase(o.toString());

View file

@ -49,8 +49,10 @@ import org.libreplan.business.calendars.entities.ResourceCalendar;
import org.libreplan.business.calendars.entities.SameWorkHoursEveryDay;
import org.libreplan.business.common.BaseEntity;
import org.libreplan.business.common.IHumanIdentifiable;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.common.IntegrationEntity;
import org.libreplan.business.common.Registry;
import org.libreplan.business.common.entities.Configuration;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.MultipleInstancesException;
import org.libreplan.business.common.exceptions.ValidationException;
@ -1188,16 +1190,32 @@ public abstract class Resource extends IntegrationEntity implements
@AssertTrue(message = "You have exceeded the maximum limit of resources")
public boolean checkMaxResources() {
Integer maxResources = Registry.getConfigurationDAO()
.getConfiguration().getMaxResources();
return Registry.getTransactionService()
.runOnAnotherReadOnlyTransaction(new IOnTransaction<Boolean>() {
@Override
public Boolean execute() {
Configuration configuration = Registry
.getConfigurationDAO().getConfiguration();
if (configuration == null) {
return true;
}
Integer maxResources = configuration.getMaxResources();
if (maxResources != null && maxResources > 0) {
List<Resource> resources = Registry.getResourceDAO().findAll();
if (resources.size() > maxResources) {
List<Resource> resources = Registry
.getResourceDAO().findAll();
int resourcesNumber = resources.size();
if (isNewObject()) {
resourcesNumber++;
}
if (resourcesNumber > maxResources) {
return false;
}
}
return true;
}
});
}
public boolean isActiveBetween(LocalDate startDate, LocalDate endDate) {
return calendar.isActiveBetween(startDate, endDate);

View file

@ -45,7 +45,8 @@ public enum Language {
POLISH_LANGUAGE("Polski", new Locale("pl")),
CZECH_LANGUAGE("Čeština", new Locale("cs")),
GERMAN_LANGUAGE("Deutsch", new Locale("de")),
CATALAN_LANGUAGE("Català", new Locale("ca"));
CATALAN_LANGUAGE("Català", new Locale("ca")),
CHINESE_LANGUAGE("中文", new Locale("zh"));
private final String displayName;

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2012 Igalia, S.L.
* Copyright (C) 2010-2013 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -31,8 +31,12 @@ import org.hibernate.validator.AssertTrue;
import org.hibernate.validator.NotEmpty;
import org.libreplan.business.common.BaseEntity;
import org.libreplan.business.common.IHumanIdentifiable;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.common.Registry;
import org.libreplan.business.common.entities.Configuration;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.settings.entities.Language;
@ -47,6 +51,7 @@ import org.libreplan.business.users.daos.IUserDAO;
* @author Ignacio Diaz Teijido <ignacio.diaz@comtecsf.es>
* @author Manuel Rego Casasnovas <rego@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
public class User extends BaseEntity implements IHumanIdentifiable{
@ -81,6 +86,18 @@ public class User extends BaseEntity implements IHumanIdentifiable{
private Worker worker;
private Label projectsFilterLabel = null;
private Integer projectsFilterPeriodSince;
private Integer projectsFilterPeriodTo;
private Criterion resourcesLoadFilterCriterion = null;
private Integer resourcesLoadFilterPeriodSince;
private Integer resourcesLoadFilterPeriodTo;
/**
* Necessary for Hibernate. Please, do not call it.
*/
@ -362,15 +379,77 @@ public class User extends BaseEntity implements IHumanIdentifiable{
@AssertTrue(message = "You have exceeded the maximum limit of users")
public boolean checkMaxUsers() {
Integer maxUsers = Registry.getConfigurationDAO().getConfiguration()
.getMaxUsers();
return Registry.getTransactionService()
.runOnAnotherReadOnlyTransaction(new IOnTransaction<Boolean>() {
@Override
public Boolean execute() {
Configuration configuration = Registry
.getConfigurationDAO().getConfiguration();
if (configuration == null) {
return true;
}
Integer maxUsers = configuration.getMaxUsers();
if (maxUsers != null && maxUsers > 0) {
List<User> users = Registry.getUserDAO().findAll();
if (users.size() > maxUsers) {
int usersNumber = users.size();
if (isNewObject()) {
usersNumber++;
}
if (usersNumber > maxUsers) {
return false;
}
}
return true;
}
});
}
public Label getProjectsFilterLabel() {
return projectsFilterLabel;
}
public void setProjectsFilterLabel(Label label) {
projectsFilterLabel = label;
}
public Criterion getResourcesLoadFilterCriterion() {
return resourcesLoadFilterCriterion;
}
public void setResourcesLoadFilterCriterion(Criterion criterion) {
resourcesLoadFilterCriterion = criterion;
}
public Integer getProjectsFilterPeriodSince() {
return projectsFilterPeriodSince;
}
public void setProjectsFilterPeriodSince(Integer period) {
projectsFilterPeriodSince = period;
}
public Integer getProjectsFilterPeriodTo() {
return projectsFilterPeriodTo;
}
public void setProjectsFilterPeriodTo(Integer period) {
projectsFilterPeriodTo = period;
}
public Integer getResourcesLoadFilterPeriodSince() {
return resourcesLoadFilterPeriodSince;
}
public void setResourcesLoadFilterPeriodSince(Integer period) {
resourcesLoadFilterPeriodSince = period;
}
public Integer getResourcesLoadFilterPeriodTo() {
return resourcesLoadFilterPeriodTo;
}
public void setResourcesLoadFilterPeriodTo(Integer period) {
resourcesLoadFilterPeriodTo = period;
}
}

View file

@ -303,4 +303,69 @@
<column name="schedule" type="BOOLEAN" />
</createTable>
</changeSet>
<changeSet id="add-projects_filter_period_since-column-to-user_table"
author="ltilve">
<comment>Add column to store project filtering interval 'range since' parameter</comment>
<addColumn tableName="user_table">
<column name="projects_filter_period_since" type="INTEGER" />
</addColumn>
</changeSet>
<changeSet id="add-projects_filter_period_to-column-to-user_table"
author="ltilve">
<comment>Add column to store project filtering interval 'range to' parameter</comment>
<addColumn tableName="user_table">
<column name="projects_filter_period_to" type="INTEGER" />
</addColumn>
</changeSet>
<changeSet id="add-resources_load_filter_period_since-column-to-user_table"
author="ltilve">
<comment>Add column to store resources load filtering interval 'range since' parameter</comment>
<addColumn tableName="user_table">
<column name="resources_load_filter_period_since" type="INTEGER" />
</addColumn>
</changeSet>
<changeSet id="add-resources_load_filter_period_to-column-to-user_table"
author="ltilve">
<comment>Add column to store resources load filtering interval 'range to' parameter</comment>
<addColumn tableName="user_table">
<column name="resources_load_filter_period_to" type="INTEGER" />
</addColumn>
</changeSet>
<changeSet id="add-projects_filter_label_id-column-to-user_table"
author="ltilve">
<comment>Add column to store label reference for default project filtering</comment>
<addColumn tableName="user_table">
<column name="projects_filter_label_id" type="BIGINT" />
</addColumn>
</changeSet>
<changeSet id="add-resources_load_filter_criterion_id-column-to-user_table"
author="ltilve">
<comment>Add column to store criterion reference for default resources load filtering</comment>
<addColumn tableName="user_table">
<column name="resources_load_filter_criterion_id" type="BIGINT" />
</addColumn>
</changeSet>
<changeSet id="add-projects_filter_label_id-fk-to-user_table" author="ltilve">
<comment>Add Foreign Key constraint on label reference</comment>
<addForeignKeyConstraint constraintName="user_label_fkey"
baseTableName="user_table" baseColumnNames="projects_filter_label_id"
referencedTableName="label" referencedColumnNames="id"
onDelete="SET NULL" />
</changeSet>
<changeSet id="add-resources_load_filter_fk_id-column-to-user_table" author="ltilve">
<comment>Add Foreign Key constraint on criterion reference</comment>
<addForeignKeyConstraint constraintName="user_criterion_fkey"
baseTableName="user_table" baseColumnNames="resources_load_filter_criterion_id"
referencedTableName="criterion" referencedColumnNames="id"
onDelete="SET NULL"/>
</changeSet>
</databaseChangeLog>

View file

@ -63,6 +63,20 @@
<one-to-one name="worker" property-ref="user"
class="org.libreplan.business.resources.entities.Worker" />
<property name="projectsFilterPeriodSince" column="projects_filter_period_since"/>
<property name="projectsFilterPeriodTo" column="projects_filter_period_to"/>
<property name="resourcesLoadFilterPeriodSince" column="resources_load_filter_period_since"/>
<property name="resourcesLoadFilterPeriodTo" column="resources_load_filter_period_to"/>
<many-to-one name="projectsFilterLabel" cascade="none" lazy="false"
column="projects_filter_label_id" />
<many-to-one name="resourcesLoadFilterCriterion" cascade="none"
lazy="false" column="resources_load_filter_criterion_id" />
</class>
<class name="Profile" table="profile_table">

View file

@ -143,6 +143,9 @@
<copy todir="src/main/webapp/help/ca" failonerror="false">
<fileset dir="../doc/src/user/es/html"/>
</copy>
<copy todir="src/main/webapp/help/zh" failonerror="false">
<fileset dir="../doc/src/user/en/html"/>
</copy>
</tasks>
</configuration>
</execution>

View file

@ -0,0 +1,14 @@
# Locale for completedEstimatedHours.jrxml
title = \ \u5c0f\u65f6\u5185\u62a5
subtitle = \u4f30\u8ba1\u4efb\u52a1/\u8ba1\u5212\u5c0f\u65f6\u6570
order = \u9879\u76ee\u540d\u79f0\uff1a
reference = \u53c2\u8003\u65e5\u671f\uff1a
criteria = \u6807\u51c6\uff1a
labels = \u6807\u7b7e\uff1a
name = \u540d\u79f0
total.hours = \u603b\u65f6\u6570
estimated = \u4f30\u8ba1
planned = \u8ba1\u5212
hours.up.to.date = \u5c0f\u65f6\u6700\u65b0
page = \u9875
of = \u7684

View file

@ -0,0 +1,11 @@
# Locale for hoursWorkedPerWorkerReportInAMonth.jrxml
title = \u5de5\u4f5c\u62a5\u544a
subtitle = \u5728\u4e00\u4e2a\u6708\u5185\u901a\u8fc7\u8d44\u6e90\u7684\u603b\u5de5\u4f5c\u5c0f\u65f6
parameters.year = \u5e74\u4efd\uff1a
parameters.month = \u6708\uff1a
name = \u540d\u79f0
hours = \u5c0f\u65f6
total.hours = \u603b\u65f6\u6570\uff1a
note1 = \u5728\u641c\u7d22\u8303\u56f4\u4e2d\u5bf9\u9009\u5b9a\u7684\u8d44\u6e90\u4e0d\u5b58\u5728\u7684\u5de5\u4f5c\u62a5\u544a\u3002
page = \u9875
of = \u7684

View file

@ -0,0 +1,18 @@
# Locale for hoursWorkedPerWorkerReport.jrxml
title = \u5de5\u4f5c\u62a5\u544a
subtitle = \u5de5\u4f5c\u65f6\u6570\u8d44\u6e90
date.start = \u5f00\u59cb\u65e5\u671f\uff1a
date.end = \u7ed3\u675f\u65e5\u671f\uff1a
criteria = \u6807\u51c6\uff1a
labels = \u6807\u7b7e
labels.colon = \u6807\u7b7e\uff1a
start = \u5f00\u59cb
end = \u7ed3\u675f
hours = \u5c0f\u65f6
task.code.name = \u4efb\u52a1\u4ee3\u7801/\u540d\u79f0
text.fields = \u6587\u672c\u5b57\u6bb5
total.day = \u6bcf\u5929\u7684\u603b\u65f6\u6570\uff1a
total.worker = \u6bcf\u540d\u5de5\u4eba\u7684\u603b\u65f6\u6570\uff1a
note1 = \u5728\u641c\u7d22\u8303\u56f4\u4e2d\u5bf9\u9009\u5b9a\u7684\u8d44\u6e90\u4e0d\u5b58\u5728\u7684\u5de5\u4f5c\u62a5\u544a\u3002
page = \u9875
of = \u7684

View file

@ -0,0 +1,28 @@
# Locale for ordersCostPerResourcesReport.jrxml
title = \u9879\u76ee\u62a5\u544a
subtitle = \u9879\u76ee\u6210\u672c
date.start = \u5f00\u59cb\u65e5\u671f\uff1a
date.end = \u7ed3\u675f\u65e5\u671f\uff1a
criteria = \u6807\u51c6\uff1a
labels = \u6807\u7b7e\uff1a
headers.column1 = \u7c7b\u578b\u5c0f\u65f6
headers.column2 = \u65e5\u671f
headers.column3 = \u85aa\u6c34
headers.column4 = \u5c0f\u65f6
headers.column5 = \u6210\u672c
total.task = \u6bcf\u5929\u7684\u603b\u8ba1\uff1a
total.worker = \u6bcf\u4e2a\u5de5\u4eba\u7684\u603b\u8ba1\uff1a
total = \u9879\u76ee\u603b\uff1a
page = \u9875
of = \u7684
expense.subtitle = \u8d39\u7528\u8868
headers.expense.column1 = \u65e5\u671f
headers.expense.column2 = \u6982\u5ff5
headers.expense.column3 = \u8d44\u6e90
headers.expense.column4 = \u503c
time.spend.subtitle = \u6267\u884c\u65f6\u95f4\uff1a
money.spend.subtitle = \u82b1\u7684\u94b1\uff1a
total.numhours = \u603b\u65f6\u6570\uff1a
total.time.money = \u5c0f\u65f6\u8d39\u7528\uff1a
total.expense.money = \u8d39\u7528\u6210\u672c\uff1a
total.money = \u5408\u8ba1\uff1a

View file

@ -0,0 +1,20 @@
# Locale for projectStatusReport.jrxml
title = 项目状态报告
project = 项目名称:
filter = 过滤器:
project_estimated_hours = 估计时间:
project_planned_hours = 计划时间:
project_imputed_hours = 的推算时间:
code =
name = 名称
estimated_hours = 估计
planned_hours = 计划
imputed_hours = 的推算
project_budget = 预算:
project_hours_cost = 小时费用:
project_expenses_cost = 费用成本:
project_total_cost = 总成本:
budget = 预算
hours_cost = 小时费用
expenses_cost = 费用成本
total_cost = 总成本

View file

@ -0,0 +1,24 @@
# Locale for schedulingProgressPerOrderReport.jrxml
title = \u8fdb\u5c55\u62a5\u544a
subtitle = \u6bcf\u4e2a\u9879\u76ee\u7684\u5de5\u4f5c\u53ca\u8fdb\u5c55\u60c5\u51b5
tipo = \u8fdb\u5c55\u7c7b\u578b\uff1a
order = \u9879\u76ee\uff1a
date.start = \u8d77\u59cb\u65e5\u671f\u3002
date.end = \u7ed3\u675f\u65e5\u671f\uff1a
date.reference = \u53c2\u8003\u65e5\u671f\uff1a
total.hours = \u603b\u65f6\u6570
estimated = \u4f30\u8ba1
planned = \u8ba1\u5212
progress = \u8fdb\u6b65
measured = \u6d4b\u91cf
imputed = \u7684\u63a8\u7b97
hours.up.to.date = \u5c0f\u65f6\u6700\u65b0
real = \u5b9e
difference = \u5dee\u5f02
cost = \u6210\u672c
cost.ratio = \u6210\u672c\u7387
planned.ratio = \u89c4\u5212\u6bd4\u7387
note1 = \u9009\u62e9\u7684\u8fdb\u5ea6\u7c7b\u578b\u662f\u4e0d\u9002\u7528\u4e8e\u8fd9\u4e00\u9879\u76ee\u3002
note2 = \u4f7f\u7528\u8513\u5ef6\u8fdb\u5c55\u7c7b\u578b\u3002
page = \u9875
of = \u7684

View file

@ -0,0 +1,17 @@
# Locale for timeLineRequiredMaterial.jrxml
title = \u7269\u6599
subtitle = \u7269\u6599\u9700\u6c42\u65e5\u671f
date.start = \u5f00\u59cb\u65e5\u671f\uff1a
date.end = \u7ed3\u675f\u65e5\u671f\uff1a
status = \u72b6\u6001\uff1a
headers.title = \u65e5
headers.column1 = \u6750\u6599
headers.column2 = \u9879\u76ee - \u4efb\u52a1
headers.column3 = \u53ef\u7528\u6027
headers.column4 = \u5355\u4f4d
headers.column5 = \u5355\u4ef7
headers.column6 = \u4ef7\u683c
headers.column7 = \u72b6\u6001
headers.total = \u6bcf\u5929\u7684\u603b\u4ef7\u683c\uff1a
page = \u9875
of = \u7684

View file

@ -0,0 +1,28 @@
# Locale for workingArrangementPerOrderReport.jrxml
title = \u9879\u76ee\u62a5\u544a
subtitle = \u5728\u9879\u76ee\u7684\u4efb\u52a1\u8c03\u5ea6\u72b6\u6001
order = \u9879\u76ee\u540d\u79f0\uff1a
status = \u72b6\u6001\uff1a
name = \u59d3\u540d\u3002
code = \u4ee3\u7801\uff1a
criteria = \u6807\u51c6\uff1a
labels = \u6807\u7b7e\uff1a
headers1.column1 = \u5f00\u59cb\u65e5\u671f
headers1.column1.column1 = \u4f30\u8ba1
headers1.column1.column2 = \u7b2c\u4e00\u6b21\u62a5\u544a
headers1.column2 = \u7ed3\u675f\u65e5\u671f
headers1.column2.column1 = \u4f30\u8ba1
headers1.column2.column2 = \u6700\u540e\u62a5\u544a
headers1.column2.column3 = \u671f\u9650
headers1.column3 = \u8fdb\u6b65
headers1.column4 = \u72b6\u6001
headers1.column5 = \u671f\u9650
headers2.title = \u4f9d\u5b58\u5173\u7cfb
headers2.column1 = \u540d\u79f0
headers2.column2 = \u7801
headers2.column3 = \u7c7b\u578b
headers2.column4 = \u8fdb\u6b65
overrun = \u6cdb\u6ee5
intime = \u53ca\u65f6
page = \u9875
of = \u7684

View file

@ -0,0 +1,24 @@
# Locale for workingProgressPerTaskReport.jrxml
title = \u8fdb\u5c55\u62a5\u544a
subtitle = \u6bcf\u4e2a\u4efb\u52a1\u7684\u5de5\u4f5c\u53ca\u8fdb\u5c55\u60c5\u51b5
order = \u9879\u76ee\u540d\u79f0\uff1a
reference = \u53c2\u8003\u65e5\u671f\uff1a
criteria = \u6807\u51c6\uff1a
labels = \u6807\u7b7e\uff1a
headers.column1 = \u603b\u65f6\u6570
headers.column1.column1 = \u4f30\u8ba1
headers.column1.column2 = \u8ba1\u5212
headers.column2 = \u8fdb\u6b65
headers.column2.column1 = \u6d4b\u91cf
headers.column2.column2 = \u7684\u63a8\u7b97
headers.column2.column3 = \u8ba1\u5212
headers.column3 = \u5c0f\u65f6\u6700\u65b0
headers.column3.column1 = \u8ba1\u5212
headers.column3.column2 = \u5b9e
headers.column4 = \u5dee\u5f02
headers.column4.column1 = \u6210\u672c
headers.column4.column2 = \u8ba1\u5212
headers.column4.column3 = \u6210\u672c\u7387
headers.column4.column4 = \u89c4\u5212\u6bd4\u7387
page = \u9875
of = \u7684

View file

@ -0,0 +1,270 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2013 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.web.common;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.joda.time.LocalDate;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.web.common.components.finders.FilterPair;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
import org.zkoss.zk.ui.Sessions;
/**
* Manages operations to read and write filter parameters from the session <br />
*
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
public class FilterUtils {
// Company view and Project list session variables
public static Date readProjectsStartDate() {
return (Date) Sessions.getCurrent().getAttribute(
"companyFilterStartDate");
}
public static Date readProjectsEndDate() {
return (Date) Sessions.getCurrent()
.getAttribute("companyFilterEndDate");
}
public static List<FilterPair> readProjectsParameters() {
return (List<FilterPair>) Sessions.getCurrent().getAttribute(
"companyFilterLabel");
}
public static void writeProjectsStartDate(Date date) {
Sessions.getCurrent().setAttribute("companyFilterStartDate", date);
Sessions.getCurrent().setAttribute("companyFilterStartDateChanged",
true);
}
public static boolean hasProjectsStartDateChanged() {
return Sessions.getCurrent().hasAttribute(
"companyFilterStartDateChanged");
}
public static void writeProjectsEndDate(Date date) {
Sessions.getCurrent().setAttribute("companyFilterEndDate", date);
Sessions.getCurrent().setAttribute("companyFilterEndDateChanged", true);
}
public static boolean hasProjectsEndDateChanged() {
return Sessions.getCurrent()
.hasAttribute("companyFilterEndDateChanged");
}
public static void writeProjectsParameters(List<FilterPair> parameters) {
Sessions.getCurrent().setAttribute("companyFilterLabel", parameters);
}
public static void writeProjectsFilter(Date startDate, Date endDate,
List<FilterPair> parameters) {
writeProjectsStartDate(startDate);
writeProjectsEndDate(endDate);
writeProjectsParameters(parameters);
}
public static void writeProjectFilterChanged(boolean changed) {
Sessions.getCurrent().setAttribute("companyFilterChanged", changed);
}
public static boolean hasProjectFilterChanged() {
return (Sessions.getCurrent().getAttribute("companyFilterChanged") != null)
&& ((Boolean) Sessions.getCurrent().getAttribute(
"companyFilterChanged"));
}
public static void writeProjectPlanningFilterChanged(boolean changed) {
Sessions.getCurrent().setAttribute("companyFilterPlanningChanged",
changed);
}
public static boolean hasProjectPlanningFilterChanged() {
return (Sessions.getCurrent().getAttribute(
"companyFilterPlanningChanged") != null)
&& ((Boolean) Sessions.getCurrent().getAttribute(
"companyFilterPlanningChanged"));
}
// Resources load filter
public static LocalDate readResourceLoadsStartDate() {
return (LocalDate) Sessions.getCurrent().getAttribute(
"resourceLoadStartDate");
}
public static LocalDate readResourceLoadsEndDate() {
return (LocalDate) Sessions.getCurrent().getAttribute(
"resourceLoadEndDate");
}
public static List<FilterPair> readResourceLoadsBandbox() {
return (List<FilterPair>) Sessions.getCurrent().getAttribute(
"resourceLoadFilterWorkerOrCriterion");
}
public static void writeResourceLoadsStartDate(LocalDate date) {
Sessions.getCurrent().setAttribute("resourceLoadStartDate", date);
Sessions.getCurrent()
.setAttribute("resourceLoadStartDateChanged", true);
}
public static boolean hasResourceLoadsStartDateChanged() {
return Sessions.getCurrent().hasAttribute(
"resourceLoadStartDateChanged");
}
public static void writeResourceLoadsEndDate(LocalDate date) {
Sessions.getCurrent().setAttribute("resourceLoadEndDate", date);
Sessions.getCurrent().setAttribute("resourceLoadEndDateChanged", true);
}
public static boolean hasResourceLoadsEndDateChanged() {
return Sessions.getCurrent().hasAttribute("resourceLoadEndDateChanged");
}
public static void writeResourceLoadsParameters(List<Object> parameters) {
Sessions.getCurrent().setAttribute(
"resourceLoadFilterWorkerOrCriterion", parameters);
}
// Project gantt and WBS filter parameters
public static Date readOrderStartDate(Order order) {
return (Date) Sessions.getCurrent().getAttribute(
order.getCode() + "-startDateFilter");
}
public static Date readOrderEndDate(Order order) {
return (Date) Sessions.getCurrent().getAttribute(
order.getCode() + "-endDateFilter");
}
public static String readOrderTaskName(Order order) {
return (String) Sessions.getCurrent().getAttribute(
order.getCode() + "-tasknameFilter");
}
public static List<FilterPair> readOrderParameters(Order order) {
return (List<FilterPair>) Sessions.getCurrent().getAttribute(
order.getCode() + "-labelsandcriteriaFilter");
}
public static Boolean readOrderInheritance(Order order) {
return (Boolean) Sessions.getCurrent().getAttribute(
order.getCode() + "-inheritanceFilter");
}
public static void writeOrderStartDate(Order order, Date date) {
Sessions.getCurrent().setAttribute(
order.getCode() + "-startDateFilter", date);
}
public static void writeOrderEndDate(Order order, Date date) {
Sessions.getCurrent().setAttribute(order.getCode() + "-endDateFilter",
date);
}
public static void writeOrderTaskName(Order order, String name) {
Sessions.getCurrent().setAttribute(order.getCode() + "-tasknameFilter",
name);
}
public static void writeOrderParameters(Order order,
List<FilterPair> parameters) {
Sessions.getCurrent().setAttribute(
order.getCode() + "-labelsandcriteriaFilter", parameters);
}
public static void writeOrderInheritance(Order order, boolean value) {
Sessions.getCurrent().setAttribute(
order.getCode() + "-inheritanceFilter", value);
}
public static void clearBandboxes() {
writeProjectsParameters(null);
writeResourceLoadsParameters(null);
}
public static void clearSessionDates() {
writeProjectsStartDate(null);
Sessions.getCurrent().setAttribute("companyFilterStartDateChanged",
null);
writeProjectsEndDate(null);
Sessions.getCurrent().setAttribute("companyFilterEndDateChanged", null);
writeResourceLoadsStartDate(null);
Sessions.getCurrent()
.setAttribute("resourceLoadStartDateChanged", null);
writeResourceLoadsEndDate(null);
Sessions.getCurrent().setAttribute("resourceLoadEndDateChanged", null);
}
public static ZoomLevel readZoomLevelCompanyView() {
return (ZoomLevel) Sessions.getCurrent().getAttribute(
"zoomLevelCompanyView");
}
public static void writeZoomLevelCompanyView(ZoomLevel zoomLevel) {
Sessions.getCurrent().setAttribute("zoomLevelCompanyView", zoomLevel);
}
public static ZoomLevel readZoomLevelResourcesLoad() {
return (ZoomLevel) Sessions.getCurrent().getAttribute(
"zoomLevelResourcesLoad");
}
public static void writeZoomLevelResourcesLoad(ZoomLevel zoomLevel) {
Sessions.getCurrent().setAttribute("zoomLevelResourcesLoad", zoomLevel);
}
public static ZoomLevel readZoomLevel(Order order) {
return (ZoomLevel) Sessions.getCurrent().getAttribute(
order.getCode() + "-zoomLevel");
}
public static void writeZoomLevel(Order order, ZoomLevel zoomLevel) {
Sessions.getCurrent().setAttribute(order.getCode() + "-zoomLevel",
zoomLevel);
}
public static boolean sessionExists() {
return Sessions.getCurrent() != null;
}
public static boolean hasOrderWBSFiltersChanged(Order order) {
return sessionExists()
&& (Sessions.getCurrent().getAttribute(
order.getCode() + "-orderWBSFilterChanged") != null)
&& ((Boolean) Sessions.getCurrent().getAttribute(
order.getCode() + "-orderWBSFilterChanged"));
}
public static void writeOrderWBSFiltersChanged(Order order, boolean changed) {
Sessions.getCurrent().setAttribute(
order.getCode() + "-orderWBSFilterChanged", changed);
}
}

View file

@ -25,11 +25,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.web.planner.allocation.AdvancedAllocationController;
import org.libreplan.web.planner.allocation.AllocationResult;
import org.libreplan.web.planner.allocation.AdvancedAllocationController.AllocationInput;
import org.libreplan.web.planner.allocation.AdvancedAllocationController.IAdvanceAllocationResultReceiver;
import org.libreplan.web.planner.allocation.AdvancedAllocationController.IBack;
import org.libreplan.web.planner.allocation.AllocationResult;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@ -54,20 +55,23 @@ public class ViewSwitcher implements Composer {
isInPlanningOrder = true;
}
public void goToAdvancedAllocation(AllocationResult allocationResult,
public void goToAdvancedAllocation(Order order,
AllocationResult allocationResult,
IAdvanceAllocationResultReceiver resultReceiver) {
planningOrder = ComponentsReplacer.replaceAllChildren(parent,
"advance_allocation.zul", createArgsForAdvancedAllocation(
allocationResult, resultReceiver));
planningOrder = ComponentsReplacer.replaceAllChildren(
parent,
"advance_allocation.zul",
createArgsForAdvancedAllocation(order, allocationResult,
resultReceiver));
isInPlanningOrder = false;
}
private Map<String, Object> createArgsForAdvancedAllocation(
private Map<String, Object> createArgsForAdvancedAllocation(Order order,
AllocationResult allocationResult,
IAdvanceAllocationResultReceiver resultReceiver) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("advancedAllocationController",
new AdvancedAllocationController(createBack(),
new AdvancedAllocationController(order, createBack(),
asAllocationInput(allocationResult, resultReceiver)));
return result;
}

View file

@ -21,6 +21,7 @@
package org.libreplan.web.common.components;
import java.util.Date;
import java.util.List;
import org.libreplan.business.resources.daos.IResourcesSearcher;
@ -36,6 +37,7 @@ import org.zkoss.zul.Radiogroup;
/**
* @author Diego Pino García <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*
* ZK macro component for searching {@link Worker} entities
*
@ -43,6 +45,8 @@ import org.zkoss.zul.Radiogroup;
@SuppressWarnings("serial")
public class NewAllocationSelector extends AllocationSelector {
public static final int DAYS_LEAD_LAG_TO_TASK_LIMITS_DATES_FILTERING_INITIALIZATION = 30;
private NewAllocationSelectorController selectorController;
private ResourceAllocationBehaviour behaviour;
@ -148,6 +152,7 @@ public class NewAllocationSelector extends AllocationSelector {
} // AllocationType
@Override
public NewAllocationSelectorController getController() {
if (selectorController == null) {
selectorController = new NewAllocationSelectorController(behaviour);
@ -164,4 +169,12 @@ public class NewAllocationSelector extends AllocationSelector {
this.behaviour = ResourceAllocationBehaviour.valueOf(behaviour);
}
public void setEndFilteringDate(Date d) {
getController().setEndFilteringDate(d);
}
public void setStartFilteringDate(Date d) {
getController().setStartFilteringDate(d);
}
}

View file

@ -131,6 +131,8 @@ public class BandboxMultipleSearch extends HtmlMacroComponent {
final String inputText = ((InputEvent) event).getValue();
if ((inputText == null) || (inputText.isEmpty())) {
clear();
listbox.setSelectedIndex(0);
Events.postEvent(Events.ON_CHANGE, listbox, null);
} else {
searchMultipleFilters(inputText);
}
@ -231,6 +233,7 @@ public class BandboxMultipleSearch extends HtmlMacroComponent {
}
public List getSelectedElements() {
updateBandboxValue();
if (this.multipleFiltersFinder != null) {
if (!multipleFiltersFinder.isValidFormatText(selectedFilters,
bandbox.getValue())) {
@ -387,4 +390,13 @@ public class BandboxMultipleSearch extends HtmlMacroComponent {
return heightBbox;
}
public void addSelectedElements(List<FilterPair> sessionFilterPairs) {
selectedFilters.clear();
for (FilterPair filterPair : sessionFilterPairs) {
addFilter(filterPair);
}
updateselectedFiltersText();
updateBandboxValue();
}
}

View file

@ -193,9 +193,9 @@ public class OrderElementsMultipleFiltersFinder extends MultipleFiltersFinder {
}
private void addLabel(LabelType type, Label label) {
String pattern = label.getName() + " ( " + type.getName() + " )";
getListMatching().add(
new FilterPair(OrderElementFilterEnum.Label, pattern, label));
new FilterPair(OrderElementFilterEnum.Label, label
.getFinderPattern(), label));
}
}

View file

@ -302,9 +302,9 @@ public class OrdersMultipleFiltersFinder extends MultipleFiltersFinder {
}
private void addLabel(LabelType type, Label label) {
String pattern = label.getName() + " ( " + type.getName() + " )";
getListMatching().add(
new FilterPair(OrderFilterEnum.Label, pattern, label));
new FilterPair(OrderFilterEnum.Label, label.getFinderPattern(),
label));
}
private void addExternalCompany(ExternalCompany externalCompany) {

View file

@ -196,9 +196,9 @@ public class TaskElementsMultipleFiltersFinder extends MultipleFiltersFinder {
}
private void addLabel(LabelType type, Label label) {
String pattern = label.getName() + " ( " + type.getName() + " )";
getListMatching().add(
new FilterPair(TaskElementFilterEnum.Label, pattern, label));
new FilterPair(TaskElementFilterEnum.Label, label
.getFinderPattern(), label));
}
private List<FilterPair> fillWithFirstTenFiltersResources() {

View file

@ -307,9 +307,9 @@ public class TaskGroupsMultipleFiltersFinder extends MultipleFiltersFinder {
}
private void addLabel(LabelType type, Label label) {
String pattern = label.getName() + " ( " + type.getName() + " )";
getListMatching().add(
new FilterPair(TaskGroupFilterEnum.Label, pattern, label));
new FilterPair(TaskGroupFilterEnum.Label, label
.getFinderPattern(), label));
}
private void addExternalCompany(ExternalCompany externalCompany) {

View file

@ -33,12 +33,14 @@ import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.orders.entities.Order;
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.qualityforms.entities.QualityForm;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.CriterionType;
import org.libreplan.business.templates.entities.OrderElementTemplate;
import org.libreplan.business.templates.entities.OrderTemplate;
import org.libreplan.business.users.entities.User;
import org.libreplan.web.common.IIntegrationEntityModel;
import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState;
import org.zkoss.ganttz.IPredicate;
@ -87,6 +89,10 @@ public interface IOrderModel extends IIntegrationEntityModel {
List<Order> getOrders();
List<Order> getOrders(Date startDate, Date endDate, List<Label> labels,
List<Criterion> criteria, ExternalCompany customer,
OrderStatusEnum state);
void initEdit(Order order, Desktop desktop);
void prepareForCreate(Desktop desktop);
@ -148,4 +154,6 @@ public interface IOrderModel extends IIntegrationEntityModel {
boolean isOnlyChildAndParentAlreadyInUseByHoursOrExpenses(
OrderElement orderElement);
User getUser();
}

View file

@ -23,6 +23,8 @@ package org.libreplan.web.orders;
import static org.libreplan.web.I18nHelper._;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.HashMap;
@ -36,6 +38,7 @@ import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.LogFactory;
import org.joda.time.LocalDate;
import org.libreplan.business.calendars.entities.BaseCalendar;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.externalcompanies.entities.DeadlineCommunication;
@ -48,9 +51,12 @@ import org.libreplan.business.orders.entities.Order.SchedulingMode;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.planner.entities.PositionConstraintType;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.templates.entities.OrderTemplate;
import org.libreplan.business.users.entities.User;
import org.libreplan.business.users.entities.UserRole;
import org.libreplan.web.common.ConfirmCloseUtil;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.IMessagesForUser;
import org.libreplan.web.common.Level;
import org.libreplan.web.common.MessagesForUser;
@ -60,6 +66,8 @@ import org.libreplan.web.common.Util.ReloadStrategy;
import org.libreplan.web.common.components.bandboxsearch.BandboxMultipleSearch;
import org.libreplan.web.common.components.bandboxsearch.BandboxSearch;
import org.libreplan.web.common.components.finders.FilterPair;
import org.libreplan.web.common.components.finders.OrderFilterEnum;
import org.libreplan.web.common.components.finders.TaskGroupFilterEnum;
import org.libreplan.web.orders.criterionrequirements.AssignedCriterionRequirementToOrderElementController;
import org.libreplan.web.orders.labels.AssignedLabelsToOrderElementController;
import org.libreplan.web.orders.labels.LabelsAssignmentToOrderElementComponent;
@ -214,9 +222,91 @@ public class OrderCRUDController extends GenericForwardComposer {
.getFellow("bdFilters");
checkIncludeOrderElements = (Checkbox) filterComponent
.getFellow("checkIncludeOrderElements");
checkCreationPermissions();
setupGlobalButtons();
initializeFilter();
}
private void initializeFilter() {
Date startDate = (Date) FilterUtils.readProjectsStartDate();
Date endDate = FilterUtils.readProjectsEndDate();
boolean calculateStartDate = (startDate == null);
boolean calculateEndDate = (endDate == null);
// Filter predicate needs to be calculated based on the projects dates
if ((calculateStartDate) || (calculateEndDate)) {
User user = orderModel.getUser();
// Calculate filter based on user preferences
if (user != null) {
if ((startDate == null)
&& !FilterUtils.hasProjectsStartDateChanged()
&& (user.getProjectsFilterPeriodSince() != null)) {
startDate = new LocalDate()
.minusMonths(user.getProjectsFilterPeriodSince())
.toDateTimeAtStartOfDay().toDate();
}
if ((endDate == null)
&& !FilterUtils.hasProjectsEndDateChanged()
&& (user.getProjectsFilterPeriodTo() != null)) {
endDate = new LocalDate()
.plusMonths(user.getProjectsFilterPeriodTo())
.toDateMidnight().toDate();
}
}
}
filterStartDate.setValue(startDate);
filterFinishDate.setValue(endDate);
loadLabels();
FilterUtils.writeProjectPlanningFilterChanged(false);
}
private void loadLabels() {
List<FilterPair> sessionFilters = FilterUtils
.readProjectsParameters();
// Allow labels when list is empty
if (sessionFilters != null) {
bdFilters.addSelectedElements(toOrderFilterEnum(sessionFilters));
return;
}
User user = orderModel.getUser();
// Calculate filter based on user preferences
if ((user != null) && (user.getProjectsFilterLabel() != null)) {
bdFilters.addSelectedElement(new FilterPair(OrderFilterEnum.Label,
user.getProjectsFilterLabel().getFinderPattern(), user
.getProjectsFilterLabel()));
}
}
private List<FilterPair> toOrderFilterEnum(List<FilterPair> filterPairs) {
List<FilterPair> result = new ArrayList<FilterPair>();
for (FilterPair filterPair : filterPairs) {
TaskGroupFilterEnum type = (TaskGroupFilterEnum) filterPair
.getType();
switch (type) {
case Label:
result.add(new FilterPair(OrderFilterEnum.Label, filterPair
.getPattern(), filterPair.getValue()));
break;
case Criterion:
result.add(new FilterPair(OrderFilterEnum.Criterion, filterPair
.getPattern(), filterPair.getValue()));
break;
case ExternalCompany:
result.add(new FilterPair(OrderFilterEnum.ExternalCompany,
filterPair.getPattern(), filterPair.getValue()));
break;
case State:
result.add(new FilterPair(OrderFilterEnum.State, filterPair
.getPattern(), filterPair.getValue()));
break;
default:
}
}
return result;
}
private void setupGlobalButtons() {
@ -456,7 +546,7 @@ public class OrderCRUDController extends GenericForwardComposer {
private void reloadTree(TreeComponent orderElementsTree) {
final Tree tree = (Tree) orderElementsTree.getFellowIfAny("tree");
tree.setModel(orderElementTreeController.getTreeModel());
tree.setModel(orderElementTreeController.getFilteredTreeModel());
tree.addEventListener(Events.ON_SELECT, new EventListener() {
@Override
public void onEvent(Event event) {
@ -653,9 +743,53 @@ public class OrderCRUDController extends GenericForwardComposer {
}
public List<Order> getOrders() {
if (checkIncludeOrderElements.isChecked()) {
return orderModel.getOrders();
}
return getOrdersFiltered();
}
private List<Order> getOrdersFiltered() {
List<org.libreplan.business.labels.entities.Label> labels = new ArrayList<org.libreplan.business.labels.entities.Label>();
List<Criterion> criteria = new ArrayList<Criterion>();
ExternalCompany customer = null;
OrderStatusEnum state = null;
for (FilterPair filterPair : (List<FilterPair>) bdFilters
.getSelectedElements()) {
OrderFilterEnum type = (OrderFilterEnum) filterPair.getType();
switch (type) {
case Label:
labels.add((org.libreplan.business.labels.entities.Label) filterPair
.getValue());
break;
case Criterion:
criteria.add((Criterion) filterPair.getValue());
break;
case ExternalCompany:
if (customer != null) {
// It's impossible to have an Order associated to more than
// 1 customer
return Collections.emptyList();
}
customer = (ExternalCompany) filterPair.getValue();
break;
case State:
if (state != null) {
// It's impossible to have an Order associated with more
// than 1 state
return Collections.emptyList();
}
state = (OrderStatusEnum) filterPair.getValue();
break;
}
}
return orderModel.getOrders(filterStartDate.getValue(),
filterFinishDate.getValue(), labels, criteria, customer, state);
}
private OnlyOneVisible getVisibility() {
if (cachedOnlyOneVisible == null) {
cachedOnlyOneVisible = new OnlyOneVisible(listWindow);
@ -801,7 +935,6 @@ public class OrderCRUDController extends GenericForwardComposer {
listing = (Grid) listWindow.getFellow("listing");
showOrderFilter();
showCreateButtons(true);
clearFilterDates();
}
private void showWindow(Window window) {
@ -1319,9 +1452,9 @@ public class OrderCRUDController extends GenericForwardComposer {
throws WrongValueException {
Date finishDate = (Date) value;
if ((finishDate != null)
&& (filterStartDate.getValue() != null)
&& (finishDate.compareTo(filterStartDate.getValue()) < 0)) {
filterFinishDate.setValue(null);
&& (filterStartDate.getRawValue() != null)
&& (finishDate.compareTo((Date) filterStartDate
.getRawValue()) < 0)) {
throw new WrongValueException(comp,
_("must be after start date"));
}
@ -1336,9 +1469,10 @@ public class OrderCRUDController extends GenericForwardComposer {
throws WrongValueException {
Date startDate = (Date) value;
if ((startDate != null)
&& (filterFinishDate.getValue() != null)
&& (startDate.compareTo(filterFinishDate.getValue()) > 0)) {
filterStartDate.setValue(null);
&& (filterFinishDate.getRawValue() != null)
&& (startDate.compareTo((Date) filterFinishDate
.getRawValue()) > 0)) {
// filterStartDate.setValue(null);
throw new WrongValueException(comp,
_("must be lower than end date"));
}
@ -1348,13 +1482,55 @@ public class OrderCRUDController extends GenericForwardComposer {
public void onApplyFilter() {
OrderPredicate predicate = createPredicate();
if (predicate != null) {
storeSessionVariables();
FilterUtils.writeProjectFilterChanged(true);
if (predicate != null && checkIncludeOrderElements.isChecked()) {
// Force reload conversation state in oderModel
getOrders();
filterByPredicate(predicate);
} else {
showAllOrders();
}
}
private void storeSessionVariables() {
FilterUtils.writeProjectsFilter(filterStartDate.getValue(),
filterFinishDate.getValue(),
getSelectedBandboxAsTaskGroupFilters());
}
private List<FilterPair> getSelectedBandboxAsTaskGroupFilters() {
List<FilterPair> result = new ArrayList<FilterPair>();
for (FilterPair filterPair : (List<FilterPair>) bdFilters
.getSelectedElements()) {
OrderFilterEnum type = (OrderFilterEnum) filterPair
.getType();
switch (type) {
case Label:
result.add(new FilterPair(TaskGroupFilterEnum.Label, filterPair
.getPattern(), filterPair.getValue()));
break;
case Criterion:
result.add(new FilterPair(TaskGroupFilterEnum.Criterion,
filterPair.getPattern(), filterPair.getValue()));
break;
case ExternalCompany:
result.add(new FilterPair(TaskGroupFilterEnum.ExternalCompany,
filterPair.getPattern(), filterPair.getValue()));
break;
case State:
result.add(new FilterPair(TaskGroupFilterEnum.State, filterPair
.getPattern(), filterPair.getValue()));
break;
default:
result.add(new FilterPair(OrderFilterEnum.Label, filterPair
.getPattern(), filterPair.getValue()));
break;
}
}
return result;
}
private OrderPredicate createPredicate() {
List<FilterPair> listFilters = (List<FilterPair>) bdFilters
.getSelectedElements();
@ -1375,13 +1551,8 @@ public class OrderCRUDController extends GenericForwardComposer {
listing.invalidate();
}
private void clearFilterDates() {
filterStartDate.setValue(null);
filterFinishDate.setValue(null);
}
public void showAllOrders() {
listing.setModel(new SimpleListModel(orderModel.getOrders().toArray()));
private void showAllOrders() {
listing.setModel(new SimpleListModel(getOrders().toArray()));
listing.invalidate();
}
@ -1685,6 +1856,12 @@ public class OrderCRUDController extends GenericForwardComposer {
return Util.getCurrencySymbol();
}
public void readSessionFilterDates() {
filterStartDate.setValue(FilterUtils.readProjectsStartDate());
filterFinishDate.setValue(FilterUtils.readProjectsEndDate());
loadLabels();
}
/**
* Setup the connector, JiraSynchronization controller
*/

View file

@ -67,10 +67,18 @@ public class OrderElementPredicate implements IPredicate {
return accepts(orderElement) || accepts(orderElement.getAllChildren());
}
public boolean isEmpty() {
return (filters.isEmpty() && startDate == null && finishDate == null && name
.isEmpty());
}
private boolean accepts(OrderElement orderElement) {
if (orderElement == null) {
return false;
}
if (orderElement.isNewObject() || orderElement.isConvertedToContainer()) {
return true;
}
if (acceptFilters(orderElement) && acceptFiltersDates(orderElement)
&& acceptFilterName(orderElement)) {
return true;

View file

@ -32,6 +32,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Filter;
import javax.annotation.Resource;
@ -49,12 +50,15 @@ import org.libreplan.business.orders.entities.SchedulingState;
import org.libreplan.business.requirements.entities.CriterionRequirement;
import org.libreplan.business.templates.entities.OrderElementTemplate;
import org.libreplan.business.users.entities.UserRole;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.IMessagesForUser;
import org.libreplan.web.common.Level;
import org.libreplan.web.common.Util;
import org.libreplan.web.common.components.bandboxsearch.BandboxMultipleSearch;
import org.libreplan.web.common.components.bandboxsearch.BandboxSearch;
import org.libreplan.web.common.components.finders.FilterPair;
import org.libreplan.web.common.components.finders.OrderElementFilterEnum;
import org.libreplan.web.common.components.finders.TaskElementFilterEnum;
import org.libreplan.web.orders.assigntemplates.TemplateFinderPopup;
import org.libreplan.web.orders.assigntemplates.TemplateFinderPopup.IOnResult;
import org.libreplan.web.security.SecurityUtils;
@ -76,6 +80,7 @@ import org.zkoss.zul.Datebox;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.Vbox;
@ -285,9 +290,47 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
operationsForOrderElement.tree(tree)
.orderTemplates(this.orderTemplates);
importOrderFiltersFromSession();
disableCreateTemplateButtonIfNeeded(comp);
}
private void importOrderFiltersFromSession() {
Order order = orderModel.getOrder();
filterNameOrderElement.setValue(FilterUtils
.readOrderTaskName(order));
filterStartDateOrderElement.setValue(FilterUtils
.readOrderStartDate(order));
filterFinishDateOrderElement.setValue(FilterUtils
.readOrderEndDate(order));
if (FilterUtils.readOrderParameters(order) != null) {
for (FilterPair each : (List<FilterPair>) FilterUtils
.readOrderParameters(order)) {
if (toOrderFilterEnum(each) != null) {
bdFiltersOrderElement
.addSelectedElement(toOrderFilterEnum(each));
}
}
}
if (FilterUtils.readOrderInheritance(order) != null) {
labelsWithoutInheritance.setChecked(FilterUtils
.readOrderInheritance(order));
}
}
private FilterPair toOrderFilterEnum(FilterPair each) {
switch ((TaskElementFilterEnum) each.getType()) {
case Label:
return new FilterPair(OrderElementFilterEnum.Label,
each.getPattern(), each.getValue());
case Criterion:
return new FilterPair(OrderElementFilterEnum.Criterion,
each.getPattern(), each.getValue());
case Resource:
// Resources are discarded on WBS filter
}
return null;
}
private void disableCreateTemplateButtonIfNeeded(Component comp) {
Button createTemplateButton = (Button) comp
.getFellowIfAny("createTemplateButton");
@ -569,13 +612,15 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
@Override
protected boolean isPredicateApplied() {
return predicate != null;
return (predicate != null)
&& !((OrderElementPredicate) predicate).isEmpty();
}
/**
* Apply filter to order elements in current order
*/
public void onApplyFilter() {
writeFilterParameters();
OrderElementPredicate predicate = createPredicate();
this.predicate = predicate;
@ -586,6 +631,38 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
}
}
private void writeFilterParameters() {
Order order = orderModel.getOrder();
FilterUtils.writeOrderStartDate(order,
filterStartDateOrderElement.getValue());
FilterUtils.writeOrderEndDate(order,
filterFinishDateOrderElement.getValue());
FilterUtils
.writeOrderTaskName(order,
filterNameOrderElement.getValue());
FilterUtils.writeOrderInheritance(order,
labelsWithoutInheritance.isChecked());
List<FilterPair> result = new ArrayList<FilterPair>();
for (FilterPair filterPair : (List<FilterPair>) bdFiltersOrderElement
.getSelectedElements()) {
result.add(toTasKElementFilterEnum(filterPair));
}
FilterUtils.writeOrderParameters(order, result);
FilterUtils.writeOrderWBSFiltersChanged(order, true);
}
private FilterPair toTasKElementFilterEnum(FilterPair each) {
switch ((OrderElementFilterEnum) each.getType()) {
case Label:
return new FilterPair(TaskElementFilterEnum.Label,
each.getPattern(), each.getValue());
case Criterion:
return new FilterPair(TaskElementFilterEnum.Criterion,
each.getPattern(), each.getValue());
}
return null;
}
private OrderElementPredicate createPredicate() {
List<FilterPair> listFilters = (List<FilterPair>) bdFiltersOrderElement
.getSelectedElements();
@ -603,6 +680,29 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
name, ignoreLabelsInheritance);
}
public TreeModel getFilteredTreeModel() {
OrderElementTreeModel filteredModel = getFilteredModel();
if (filteredModel == null) {
return null;
}
return filteredModel.asTree();
}
public OrderElementTreeModel getFilteredModel() {
if (orderModel == null) {
return null;
}
OrderElementPredicate predicate = createPredicate();
this.predicate = predicate;
if (predicate != null) {
return orderModel.getOrderElementsFilteredByPredicate(predicate);
} else {
return orderModel.getOrderElementTreeModel();
}
}
private void filterByPredicate(OrderElementPredicate predicate) {
OrderElementTreeModel orderElementTreeModel = orderModel
.getOrderElementsFilteredByPredicate(predicate);
@ -618,10 +718,7 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
@Override
protected boolean isNewButtonDisabled() {
if(readOnly) {
return true;
}
return isPredicateApplied();
return readOnly;
}
/**

View file

@ -58,6 +58,7 @@ import org.libreplan.business.orders.entities.HoursGroup;
import org.libreplan.business.orders.entities.Order;
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.IMoneyCostCalculator;
import org.libreplan.business.planner.entities.PositionConstraintType;
import org.libreplan.business.qualityforms.daos.IQualityFormDAO;
@ -222,6 +223,22 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
return orders;
}
@Override
@Transactional(readOnly = true)
public List<Order> getOrders(Date startDate, Date endDate,
List<Label> labels, List<Criterion> criteria,
ExternalCompany customer, OrderStatusEnum state) {
getLabelsOnConversation().reattachLabels();
List<Order> orders = orderDAO
.getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
SecurityUtils.getSessionUserLoginName(),
scenarioManager.getCurrent(), startDate, endDate,
labels, criteria, customer, state);
initializeOrders(orders);
return orders;
}
private void initializeOrders(List<Order> list) {
for (Order order : list) {
orderDAO.reattachUnmodifiedEntity(order);
@ -928,4 +945,21 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
}
}
@Override
@Transactional(readOnly = true)
public User getUser() {
User user;
try {
user = this.userDAO.findByLoginName(SecurityUtils
.getSessionUserLoginName());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
// Attach filter bandbox elements
if (user.getProjectsFilterLabel() != null) {
user.getProjectsFilterLabel().getFinderPattern();
}
return user;
}
}

View file

@ -18,6 +18,7 @@
*/
package org.libreplan.web.planner;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
@ -282,4 +283,27 @@ public class TaskGroupPredicate implements IPredicate {
return false;
}
public boolean isIncludeChildren() {
return includeChildren;
}
public List<FilterPair> getFilters() {
if (filters == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(filters);
}
public Date getStartDate() {
return startDate;
}
public Date getFinishDate() {
return finishDate;
}
public void setFilters(List<FilterPair> listFilters) {
filters = listFilters;
}
}

View file

@ -41,6 +41,7 @@ import org.apache.commons.lang.Validate;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.planner.entities.AggregateOfResourceAllocations;
import org.libreplan.business.planner.entities.AssignmentFunction;
import org.libreplan.business.planner.entities.AssignmentFunction.AssignmentFunctionName;
@ -56,6 +57,7 @@ import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.web.common.EffortDurationBox;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.IMessagesForUser;
import org.libreplan.web.common.MessagesForUser;
import org.libreplan.web.common.OnlyOneVisible;
@ -377,24 +379,29 @@ public class AdvancedAllocationController extends GenericForwardComposer {
private Listbox advancedAllocationHorizontalPagination;
private Listbox advancedAllocationVerticalPagination;
private boolean fixedZoomByUser = false;
private ZoomLevel zoomLevel;
public AdvancedAllocationController(IBack back,
private Order order;
public AdvancedAllocationController(Order order, IBack back,
List<AllocationInput> allocationInputs) {
setInputData(back, allocationInputs);
setInputData(order, back, allocationInputs);
}
private void setInputData(IBack back, List<AllocationInput> allocationInputs) {
private void setInputData(Order order, IBack back,
List<AllocationInput> allocationInputs) {
Validate.notNull(order);
Validate.notNull(back);
Validate.noNullElements(allocationInputs);
this.order = order;
this.back = back;
this.allocationInputs = allocationInputs;
}
public void reset(IBack back, List<AllocationInput> allocationInputs) {
public void reset(Order order, IBack back,
List<AllocationInput> allocationInputs) {
rowsCached = null;
setInputData(back, allocationInputs);
setInputData(order, back, allocationInputs);
loadAndInitializeComponents();
}
@ -576,7 +583,8 @@ public class AdvancedAllocationController extends GenericForwardComposer {
private void createComponents() {
timeTracker = new TimeTracker(addMarginTointerval(), self);
paginatorFilter = new PaginatorFilter();
if (fixedZoomByUser && (zoomLevel != null)) {
zoomLevel = FilterUtils.readZoomLevel(order);
if (zoomLevel != null) {
timeTracker.setZoomLevel(zoomLevel);
}
paginatorFilter.setZoomLevel(timeTracker.getDetailLevel());
@ -588,7 +596,7 @@ public class AdvancedAllocationController extends GenericForwardComposer {
timeTracker.addZoomListener(new IZoomLevelChangedListener() {
@Override
public void zoomLevelChanged(ZoomLevel detailLevel) {
fixedZoomByUser = true;
FilterUtils.writeZoomLevel(order, detailLevel);
zoomLevel = detailLevel;
paginatorFilter.setZoomLevel(detailLevel);

View file

@ -38,6 +38,7 @@ import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*/
public interface IResourceAllocationModel extends INewAllocationsAdder {
@ -84,4 +85,6 @@ public interface IResourceAllocationModel extends INewAllocationsAdder {
Date getTaskEnd();
Date getTaskStart();
}

View file

@ -31,6 +31,7 @@ import java.util.List;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.LocalDate;
import org.libreplan.business.orders.entities.AggregatedHoursGroup;
import org.libreplan.business.planner.entities.CalculatedValue;
import org.libreplan.business.planner.entities.DerivedAllocation;
@ -82,8 +83,10 @@ import org.zkoss.zul.Window;
/**
* Controller for {@link ResourceAllocation} view.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino Garcia <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*/
@org.springframework.stereotype.Component("resourceAllocationController")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -162,6 +165,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
assignedEffortComponent.setWidth("80px");
}
@Override
public ResourceAllocationController getController() {
return this;
}
@ -228,12 +232,14 @@ public class ResourceAllocationController extends GenericForwardComposer {
return allocationConfiguration.getTaskWorkableDays();
}
private Label getTaskStart() {
return allocationConfiguration.getTaskStart();
public Label getTaskStart() {
return (allocationConfiguration != null) ? allocationConfiguration
.getTaskStart() : null;
}
private Label getTaskEnd() {
return allocationConfiguration.getTaskEnd();
public Label getTaskEnd() {
return (allocationConfiguration != null) ? allocationConfiguration
.getTaskEnd() : null;
}
private Radiogroup getCalculationTypeSelector() {
@ -317,8 +323,23 @@ public class ResourceAllocationController extends GenericForwardComposer {
}
public void goToAdvancedSearch() {
newAllocationSelector
.setStartFilteringDate(LocalDate
.fromDateFields(resourceAllocationModel.getTaskStart())
.minusDays(
NewAllocationSelector.DAYS_LEAD_LAG_TO_TASK_LIMITS_DATES_FILTERING_INITIALIZATION)
.toDateTimeAtStartOfDay().toDate());
newAllocationSelector
.setEndFilteringDate(LocalDate
.fromDateFields(resourceAllocationModel.getTaskEnd())
.plusDays(
NewAllocationSelector.DAYS_LEAD_LAG_TO_TASK_LIMITS_DATES_FILTERING_INITIALIZATION)
.toDateTimeAtStartOfDay().toDate());
applyButton.setVisible(false);
workerSearchTab.setSelected(true);
// The initial search and ratio load calculations is raised
// on going to advanced search
newAllocationSelector.clearAll();
}
/**

View file

@ -54,13 +54,14 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.ganttz.data.GanttDate;
import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
/**
* Model for UI operations related to {@link Task}
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*/
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -325,4 +326,17 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
return task.getEndDate();
}
@Override
public Date getTaskStart() {
Date result;
if (task == null) {
result = null;
} else {
result = task.getStartDate();
}
return result;
}
}

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
* Copyright (C) 2010-2013 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -30,18 +30,21 @@ import java.util.List;
import java.util.Map;
import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate;
import org.libreplan.business.common.entities.ProgressType;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.users.entities.User;
import org.libreplan.business.users.entities.UserRole;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.components.bandboxsearch.BandboxMultipleSearch;
import org.libreplan.web.common.components.finders.FilterPair;
import org.libreplan.web.common.components.finders.TaskGroupFilterEnum;
import org.libreplan.web.planner.TaskGroupPredicate;
import org.libreplan.web.planner.tabs.MultipleTabsPlannerController;
import org.libreplan.web.security.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.zkoss.ganttz.IPredicate;
import org.zkoss.ganttz.Planner;
import org.zkoss.ganttz.extensions.ICommandOnTask;
import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
@ -67,6 +70,7 @@ import org.zkoss.zul.Vbox;
* planner.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
@org.springframework.stereotype.Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -135,14 +139,49 @@ public class CompanyPlanningController implements Composer {
bdFilters = (BandboxMultipleSearch) filterComponent
.getFellow("bdFilters");
bdFilters.setFinder("taskGroupsMultipleFiltersFinder");
loadPredefinedBandboxFilter();
checkIncludeOrderElements = (Checkbox) filterComponent
.getFellow("checkIncludeOrderElements");
filterComponent.setVisible(true);
checkCreationPermissions();
}
private void loadPredefinedBandboxFilter() {
User user = model.getUser();
List<FilterPair> sessionFilterPairs = FilterUtils
.readProjectsParameters();
if (sessionFilterPairs != null) {
bdFilters.addSelectedElements(sessionFilterPairs);
} else if ((user != null) && (user.getProjectsFilterLabel() != null)) {
bdFilters.clear();
bdFilters.addSelectedElement(new FilterPair(
TaskGroupFilterEnum.Label, user.getProjectsFilterLabel()
.getFinderPattern(), user
.getProjectsFilterLabel()));
}
// Calculate filter based on user preferences
if (user != null) {
if ((filterStartDate.getValue() == null)
&& !FilterUtils.hasProjectsStartDateChanged()
&& (user.getProjectsFilterPeriodSince() != null)) {
filterStartDate.setValue(new LocalDate()
.minusMonths(user.getProjectsFilterPeriodSince())
.toDateTimeAtStartOfDay().toDate());
}
if (filterFinishDate.getValue() == null
&& !FilterUtils.hasProjectsEndDateChanged()
&& (user.getProjectsFilterPeriodTo() != null)) {
filterFinishDate.setValue(new LocalDate()
.plusMonths(user.getProjectsFilterPeriodTo())
.toDateMidnight().toDate());
}
}
}
/**
* Checks the creation permissions of the current user and enables/disables
* the create buttons accordingly.
@ -278,35 +317,50 @@ public class CompanyPlanningController implements Composer {
};
}
public void readSessionVariablesIntoComponents() {
filterStartDate.setValue(FilterUtils.readProjectsStartDate());
filterFinishDate.setValue(FilterUtils.readProjectsEndDate());
loadPredefinedBandboxFilter();
}
public void onApplyFilter() {
FilterUtils.writeProjectsFilter(filterStartDate.getValue(),
filterFinishDate.getValue(), bdFilters.getSelectedElements());
FilterUtils.writeProjectPlanningFilterChanged(true);
filterByPredicate(createPredicate());
}
private IPredicate createPredicate() {
public void loadSessionFiltersIntoBandbox() {
bdFilters.addSelectedElements(FilterUtils.readProjectsParameters());
}
private TaskGroupPredicate createPredicate() {
List<FilterPair> listFilters = (List<FilterPair>) bdFilters
.getSelectedElements();
Date startDate = filterStartDate.getValue();
Date finishDate = filterFinishDate.getValue();
Boolean includeOrderElements = checkIncludeOrderElements.isChecked();
if (listFilters.isEmpty() && startDate == null && finishDate == null) {
IPredicate predicate = model.getDefaultPredicate(includeOrderElements);
if (startDate == null && finishDate == null) {
TaskGroupPredicate predicate = model
.getDefaultPredicate(includeOrderElements);
//show filter dates calculated by default on screen
if(model.getFilterStartDate() != null) {
filterStartDate.setValue(model.getFilterStartDate().
toDateMidnight().toDate());
if (model.getFilterStartDate() != null
&& !FilterUtils.hasProjectsStartDateChanged()) {
filterStartDate.setValue(model.getFilterStartDate());
}
if(model.getFilterFinishDate() != null) {
filterFinishDate.setValue(model.getFilterFinishDate().
toDateMidnight().toDate());
if (model.getFilterFinishDate() != null
&& !FilterUtils.hasProjectsEndDateChanged()) {
filterFinishDate.setValue(model.getFilterFinishDate());
}
predicate.setFilters(listFilters);
return predicate;
}
return new TaskGroupPredicate(listFilters, startDate, finishDate,
includeOrderElements);
}
private void filterByPredicate(IPredicate predicate) {
private void filterByPredicate(TaskGroupPredicate predicate) {
// Recalculate predicate
model.setConfigurationToPlanner(planner, additional,
doubleClickCommand, predicate);
@ -314,6 +368,11 @@ public class CompanyPlanningController implements Composer {
planner.invalidate();
}
public void setPredicate() {
model.setConfigurationToPlanner(planner, additional,
doubleClickCommand, createPredicate());
}
public void setTabsController(MultipleTabsPlannerController tabsController) {
this.tabsController = tabsController;
}

View file

@ -47,6 +47,7 @@ import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.common.daos.IConfigurationDAO;
import org.libreplan.business.common.entities.ProgressType;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
import org.libreplan.business.hibernate.notification.PredefinedDatabaseSnapshots;
import org.libreplan.business.orders.daos.IOrderDAO;
import org.libreplan.business.orders.entities.Order;
@ -57,10 +58,14 @@ import org.libreplan.business.planner.entities.ICompanyEarnedValueCalculator;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.planner.entities.TaskGroup;
import org.libreplan.business.planner.entities.TaskMilestone;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.scenarios.IScenarioManager;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.entities.User;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.components.finders.FilterPair;
import org.libreplan.web.common.components.finders.TaskGroupFilterEnum;
import org.libreplan.web.planner.TaskElementAdapter;
import org.libreplan.web.planner.TaskGroupPredicate;
import org.libreplan.web.planner.chart.Chart;
@ -81,7 +86,6 @@ import org.springframework.transaction.annotation.Transactional;
import org.zkforge.timeplot.Plotinfo;
import org.zkforge.timeplot.Timeplot;
import org.zkoss.ganttz.IChartVisibilityChangedListener;
import org.zkoss.ganttz.IPredicate;
import org.zkoss.ganttz.Planner;
import org.zkoss.ganttz.adapters.IStructureNavigator;
import org.zkoss.ganttz.adapters.PlannerConfiguration;
@ -159,11 +163,8 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
private LocalDate filterFinishDate;
// All the status but CANCELLED and STORED
private static final EnumSet<OrderStatusEnum> STATUS_VISUALIZED = EnumSet
.of(OrderStatusEnum.PRE_SALES, OrderStatusEnum.OFFERED,
OrderStatusEnum.OUTSOURCED, OrderStatusEnum.ACCEPTED,
OrderStatusEnum.STARTED, OrderStatusEnum.ON_HOLD,
OrderStatusEnum.FINISHED);
private static final EnumSet<OrderStatusEnum> STATUS_VISUALIZED = OrderStatusEnum
.getVisibleStatus();
public void setPlanningControllerEntryPoints(
MultipleTabsPlannerController entryPoints) {
@ -202,7 +203,7 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
public void setConfigurationToPlanner(final Planner planner,
Collection<ICommandOnTask<TaskElement>> additional,
ICommandOnTask<TaskElement> doubleClickCommand,
IPredicate predicate) {
TaskGroupPredicate predicate) {
currentScenario = scenarioManager.getCurrent();
final PlannerConfiguration<TaskElement> configuration = createConfiguration(predicate);
@ -232,14 +233,13 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
addPrintSupport(configuration);
disableSomeFeatures(configuration);
ZoomLevel defaultZoomLevel = OrderPlanningModel
.calculateDefaultLevel(configuration);
OrderPlanningModel.configureInitialZoomLevelFor(planner,
defaultZoomLevel);
planner.setInitialZoomLevel(getZoomLevel(configuration));
configuration.setSecondLevelModificators(BankHolidaysMarker.create(getDefaultCalendar()));
planner.setConfiguration(configuration);
setupZoomLevelListener(planner);
if(expandPlanningViewChart) {
//if the chart is expanded, we load the data now
setupChartAndItsContent(planner, chartComponent);
@ -266,6 +266,32 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
}
}
private ZoomLevel getZoomLevel(
PlannerConfiguration<TaskElement> configuration) {
ZoomLevel sessionZoom = FilterUtils.readZoomLevelCompanyView();
if (sessionZoom != null) {
return sessionZoom;
}
return OrderPlanningModel.calculateDefaultLevel(configuration);
}
private void setupZoomLevelListener(Planner planner) {
planner.getTimeTracker().addZoomListener(getSessionZoomLevelListener());
}
private IZoomLevelChangedListener getSessionZoomLevelListener() {
IZoomLevelChangedListener zoomListener = new IZoomLevelChangedListener() {
@Override
public void zoomLevelChanged(ZoomLevel detailLevel) {
FilterUtils.writeZoomLevelCompanyView(detailLevel);
}
};
keepAliveZoomListeners.add(zoomListener);
return zoomListener;
}
private BaseCalendar getDefaultCalendar() {
return configurationDAO.getConfiguration().getDefaultCalendar();
}
@ -682,24 +708,36 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
}
private PlannerConfiguration<TaskElement> createConfiguration(
IPredicate predicate) {
TaskGroupPredicate predicate) {
return new PlannerConfiguration<TaskElement>(
taskElementAdapterCreator.createForCompany(currentScenario),
new TaskElementNavigator(), retainOnlyTopLevel(predicate));
}
private List<TaskElement> retainOnlyTopLevel(IPredicate predicate) {
private List<TaskElement> retainOnlyTopLevel(TaskGroupPredicate predicate) {
List<TaskElement> result = new ArrayList<TaskElement>();
List<Order> list = orderDAO.getOrdersByReadAuthorizationByScenario(
SecurityUtils.getSessionUserLoginName(), currentScenario);
List<Order> list = getOrders(predicate);
for (Order order : list) {
order.useSchedulingDataFor(currentScenario, false);
TaskGroup associatedTaskElement = order.getAssociatedTaskElement();
if (associatedTaskElement != null
&& (predicate == null || predicate
.accepts(associatedTaskElement))) {
if (associatedTaskElement != null) {
if (predicate != null) {
// If predicate includeChildren then we check if it accepts
// the element
if (predicate.isIncludeChildren()
&& !predicate.accepts(associatedTaskElement)) {
// If it doesn't accept the element we move on to the
// next order
continue;
}
}
// If predicate doesn't includeChildren then the orders where
// already filtered in the DB query.
// Otherwise they've been filtered with the predicate above, and
// if they didn't pass the filter the execution doesn't reach
// this point.
associatedTaskElement.setSimplifiedAssignedStatusCalculationEnabled(true);
result.add(associatedTaskElement);
}
@ -713,28 +751,92 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
return result;
}
private List<Order> getOrders(TaskGroupPredicate predicate) {
String username = SecurityUtils.getSessionUserLoginName();
if (predicate.isIncludeChildren()) {
return orderDAO.getOrdersByReadAuthorizationByScenario(username,
currentScenario);
}
Date startDate = predicate.getStartDate();
Date endDate = predicate.getFinishDate();
List<org.libreplan.business.labels.entities.Label> labels = new ArrayList<org.libreplan.business.labels.entities.Label>();
List<Criterion> criteria = new ArrayList<Criterion>();
ExternalCompany customer = null;
OrderStatusEnum state = null;
for (FilterPair filterPair : (List<FilterPair>) predicate.getFilters()) {
TaskGroupFilterEnum type = (TaskGroupFilterEnum) filterPair
.getType();
switch (type) {
case Label:
labels.add((org.libreplan.business.labels.entities.Label) filterPair
.getValue());
break;
case Criterion:
criteria.add((Criterion) filterPair.getValue());
break;
case ExternalCompany:
if (customer != null) {
// It's impossible to have an Order associated to more than
// 1 customer
return Collections.emptyList();
}
customer = (ExternalCompany) filterPair.getValue();
break;
case State:
if (state != null) {
// It's impossible to have an Order associated with more
// than 1 state
return Collections.emptyList();
}
state = (OrderStatusEnum) filterPair.getValue();
break;
}
}
return orderDAO
.getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
username, currentScenario, startDate, endDate, labels,
criteria, customer, state);
}
@Override
@Transactional(readOnly = true)
public IPredicate getDefaultPredicate(Boolean includeOrderElements) {
public TaskGroupPredicate getDefaultPredicate(Boolean includeOrderElements) {
Date startDate = FilterUtils.readProjectsStartDate();
Date endDate = FilterUtils.readProjectsEndDate();
boolean calculateStartDate = (startDate == null);
boolean calculateEndDate = (endDate == null);
// Filter predicate needs to be calculated based on the projects dates
if ((calculateStartDate) || (calculateEndDate)) {
if (currentScenario == null) {
currentScenario = scenarioManager.getCurrent();
}
List<Order> list = orderDAO.getOrdersByReadAuthorizationByScenario(
SecurityUtils.getSessionUserLoginName(), currentScenario);
Date startDate = null;
Date endDate = null;
for (Order each : list) {
each.useSchedulingDataFor(currentScenario, false);
TaskGroup associatedTaskElement = each.getAssociatedTaskElement();
TaskGroup associatedTaskElement = each
.getAssociatedTaskElement();
if (associatedTaskElement != null
&& STATUS_VISUALIZED.contains(each.getState())) {
startDate = Collections.min(notNull(startDate, each.getInitDate(),
if (calculateStartDate) {
startDate = Collections.min(notNull(startDate,
each.getInitDate(),
associatedTaskElement.getStartDate()));
endDate = Collections.max(notNull(endDate, each.getDeadline(),
}
if (calculateEndDate) {
endDate = Collections.max(notNull(endDate,
each.getDeadline(),
associatedTaskElement.getEndDate()));
}
}
}
}
filterStartDate = startDate != null ? LocalDate
.fromDateFields(startDate) : null;
filterFinishDate = endDate != null ? LocalDate.fromDateFields(endDate)
@ -754,18 +856,19 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
}
@Override
public LocalDate getFilterStartDate() {
return filterStartDate;
public Date getFilterStartDate() {
return ((filterStartDate == null) ? null : filterStartDate
.toDateTimeAtStartOfDay().toDate());
}
@Override
public LocalDate getFilterFinishDate() {
return filterFinishDate;
public Date getFilterFinishDate() {
return ((filterStartDate == null) ? null : filterFinishDate
.toDateMidnight().toDate());
}
private AvailabilityTimeLine.Interval getFilterInterval() {
return AvailabilityTimeLine.Interval.create(getFilterStartDate(),
getFilterFinishDate());
return AvailabilityTimeLine.Interval.create(filterStartDate,
filterFinishDate);
}
private class CompanyLoadChartFiller extends StandardLoadChartFiller {
@ -834,4 +937,21 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
return configurationDAO.getConfiguration().getProgressType();
}
@Override
@Transactional(readOnly = true)
public User getUser() {
User user;
try {
user = this.userDAO.findByLoginName(SecurityUtils
.getSessionUserLoginName());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
// Attach filter bandbox elements
if (user.getProjectsFilterLabel() != null) {
user.getProjectsFilterLabel().getFinderPattern();
}
return user;
}
}

View file

@ -22,13 +22,14 @@
package org.libreplan.web.planner.company;
import java.util.Collection;
import java.util.Date;
import org.joda.time.LocalDate;
import org.libreplan.business.common.entities.ProgressType;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.templates.entities.OrderTemplate;
import org.libreplan.business.users.entities.User;
import org.libreplan.web.planner.TaskGroupPredicate;
import org.libreplan.web.planner.tabs.MultipleTabsPlannerController;
import org.zkoss.ganttz.IPredicate;
import org.zkoss.ganttz.Planner;
import org.zkoss.ganttz.extensions.ICommandOnTask;
@ -41,16 +42,18 @@ public interface ICompanyPlanningModel {
public void setConfigurationToPlanner(Planner planner,
Collection<ICommandOnTask<TaskElement>> additional,
ICommandOnTask<TaskElement> doubleClickCommand, IPredicate predicate);
ICommandOnTask<TaskElement> doubleClickCommand,
TaskGroupPredicate predicate);
public void setTabsController(MultipleTabsPlannerController tabsController);
LocalDate getFilterStartDate();
Date getFilterStartDate();
LocalDate getFilterFinishDate();
Date getFilterFinishDate();
ProgressType getProgressTypeFromConfiguration();
public IPredicate getDefaultPredicate(Boolean includeOrderElements);
public TaskGroupPredicate getDefaultPredicate(Boolean includeOrderElements);
User getUser();
}

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
* Copyright (C) 2010-2013 Igalia, S.L.
* Copyright (C) 2010-2011 WirelessGalicia S.L.
*
* This program is free software: you can redistribute it and/or modify
@ -36,6 +36,7 @@ import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.ViewSwitcher;
import org.libreplan.web.common.components.bandboxsearch.BandboxMultipleSearch;
import org.libreplan.web.common.components.finders.FilterPair;
@ -75,6 +76,7 @@ import org.zkoss.zul.Vbox;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -144,6 +146,7 @@ public class OrderPlanningController implements Composer {
if (planner != null) {
ensureIsInPlanningOrderView();
updateConfiguration();
planner.setTaskListPredicate(getFilterAndParentExpanedPredicates(createPredicate()));
}
}
@ -211,6 +214,8 @@ public class OrderPlanningController implements Composer {
private void updateConfiguration() {
if (order != null) {
importOrderFiltersFromSession();
long time = System.currentTimeMillis();
model.setConfigurationToPlanner(planner, order, viewSwitcher,
editTaskController, advancedAllocationTaskController,
@ -225,6 +230,28 @@ public class OrderPlanningController implements Composer {
}
}
public void importOrderFiltersFromSession() {
importOrderFiltersFromSession(false);
}
public void importOrderFiltersFromSession(boolean forceReload) {
filterNameOrderElement.setValue(FilterUtils.readOrderTaskName(order));
filterStartDateOrderElement.setValue(FilterUtils
.readOrderStartDate(order));
filterFinishDateOrderElement.setValue(FilterUtils
.readOrderEndDate(order));
List<FilterPair> sessionFilterPairs = FilterUtils
.readOrderParameters(order);
if ((sessionFilterPairs != null)
&& (bdFiltersOrderElement.getSelectedElements().isEmpty() || forceReload)) {
bdFiltersOrderElement.addSelectedElements(sessionFilterPairs);
}
if (FilterUtils.readOrderInheritance(order) != null) {
labelsWithoutInheritance.setChecked(FilterUtils
.readOrderInheritance(order));
}
}
public EditTaskController getEditTaskController() {
return editTaskController;
}
@ -247,9 +274,18 @@ public class OrderPlanningController implements Composer {
public void onApplyFilter() {
filterByPredicate(createPredicate());
List<FilterPair> listFilters = (List<FilterPair>) bdFiltersOrderElement
.getSelectedElements();
FilterUtils.writeOrderParameters(order, listFilters);
}
private TaskElementPredicate createPredicate() {
if (FilterUtils.hasOrderWBSFiltersChanged(order)) {
importOrderFiltersFromSession(true);
FilterUtils.writeOrderWBSFiltersChanged(order, false);
}
List<FilterPair> listFilters = (List<FilterPair>) bdFiltersOrderElement
.getSelectedElements();
Date startDate = filterStartDateOrderElement.getValue();
@ -261,7 +297,10 @@ public class OrderPlanningController implements Composer {
&& name == null) {
return null;
}
FilterUtils.writeOrderTaskName(order, name);
FilterUtils.writeOrderStartDate(order, startDate);
FilterUtils.writeOrderEndDate(order, finishDate);
FilterUtils.writeOrderInheritance(order, ignoreLabelsInheritance);
return new TaskElementPredicate(listFilters, startDate, finishDate,
name, ignoreLabelsInheritance);
}
@ -281,25 +320,7 @@ public class OrderPlanningController implements Composer {
public void doAction() {
// FIXME remove or change
model.forceLoadLabelsAndCriterionRequirements();
final IContext<?> context = planner.getContext();
FilterAndParentExpandedPredicates newPredicate = new FilterAndParentExpandedPredicates(
context) {
@Override
public boolean accpetsFilterPredicate(Task task) {
if (predicate == null) {
return true;
}
TaskElement taskElement = (TaskElement) context
.getMapper()
.findAssociatedDomainObject(task);
return predicate.accepts(taskElement);
}
};
newPredicate.setFilterContainers(planner.getPredicate()
.isFilterContainers());
planner.setTaskListPredicate(newPredicate);
planner.setTaskListPredicate(getFilterAndParentExpanedPredicates(predicate));
}
@Override
@ -310,6 +331,27 @@ public class OrderPlanningController implements Composer {
});
}
private FilterAndParentExpandedPredicates getFilterAndParentExpanedPredicates(
final TaskElementPredicate predicate) {
final IContext<?> context = planner.getContext();
FilterAndParentExpandedPredicates newPredicate = new FilterAndParentExpandedPredicates(
context) {
@Override
public boolean accpetsFilterPredicate(Task task) {
if (predicate == null) {
return true;
}
TaskElement taskElement = (TaskElement) context.getMapper()
.findAssociatedDomainObject(task);
return predicate.accepts(taskElement);
}
};
newPredicate.setFilterContainers(planner.getPredicate()
.isFilterContainers());
return newPredicate;
}
public Constraint checkConstraintFinishDate() {
return new Constraint() {
@Override
@ -320,7 +362,7 @@ public class OrderPlanningController implements Composer {
&& (filterStartDateOrderElement.getValue() != null)
&& (finishDate.compareTo(filterStartDateOrderElement
.getValue()) < 0)) {
filterFinishDateOrderElement.setValue(null);
filterFinishDateOrderElement.setRawValue(null);
throw new WrongValueException(comp,
_("must be after start date"));
}
@ -339,7 +381,7 @@ public class OrderPlanningController implements Composer {
&& (filterFinishDateOrderElement.getValue() != null)
&& (startDate.compareTo(filterFinishDateOrderElement
.getValue()) > 0)) {
filterStartDateOrderElement.setValue(null);
filterStartDateOrderElement.setRawValue(null);
throw new WrongValueException(comp,
_("must be lower than end date"));
}

View file

@ -71,6 +71,7 @@ import org.libreplan.business.users.entities.UserRole;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.web.calendars.BaseCalendarModel;
import org.libreplan.web.common.ConfirmCloseUtil;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.ViewSwitcher;
import org.libreplan.web.planner.adaptplanning.IAdaptPlanningCommand;
import org.libreplan.web.planner.advances.AdvanceAssignmentPlanningController;
@ -181,13 +182,6 @@ public class OrderPlanningModel implements IOrderPlanningModel {
}
}
public static void configureInitialZoomLevelFor(Planner planner,
ZoomLevel defaultZoomLevel) {
if (!planner.isFixedZoomByUser()) {
planner.setInitialZoomLevel(defaultZoomLevel);
}
}
public static ZoomLevel calculateDefaultLevel(
PlannerConfiguration<TaskElement> configuration) {
if (configuration.getData().isEmpty()) {
@ -326,9 +320,7 @@ public class OrderPlanningModel implements IOrderPlanningModel {
.isExpandOrderPlanningViewCharts());
addAdditional(additional, configuration);
ZoomLevel defaultZoomLevel = OrderPlanningModel
.calculateDefaultLevel(configuration);
configureInitialZoomLevelFor(planner, defaultZoomLevel);
planner.setInitialZoomLevel(getZoomLevel(configuration, order));
final boolean writingAllowed = isWritingAllowedOnOrder();
ISaveCommand saveCommand = setupSaveCommand(configuration,
@ -377,6 +369,9 @@ public class OrderPlanningModel implements IOrderPlanningModel {
PROFILING_LOG.debug("setConfiguration on planner took: "
+ (System.currentTimeMillis() - setConfigurationTime) + " ms");
long preparingChartsAndMisc = System.currentTimeMillis();
setupZoomLevelListener(planner, order);
// Prepare tabpanels
Tabpanels chartTabpanels = new Tabpanels();
@ -409,6 +404,34 @@ public class OrderPlanningModel implements IOrderPlanningModel {
+ (System.currentTimeMillis() - overalProgressContentTime));
}
private ZoomLevel getZoomLevel(
PlannerConfiguration<TaskElement> configuration, Order order) {
ZoomLevel sessionZoom = FilterUtils.readZoomLevel(order);
if (sessionZoom != null) {
return sessionZoom;
}
return OrderPlanningModel.calculateDefaultLevel(configuration);
}
private void setupZoomLevelListener(Planner planner, Order order) {
planner.getTimeTracker().addZoomListener(
getSessionZoomLevelListener(order));
}
private IZoomLevelChangedListener getSessionZoomLevelListener(
final Order order) {
IZoomLevelChangedListener zoomListener = new IZoomLevelChangedListener() {
@Override
public void zoomLevelChanged(ZoomLevel detailLevel) {
FilterUtils.writeZoomLevel(order, detailLevel);
}
};
keepAliveZoomListeners.add(zoomListener);
return zoomListener;
}
private OrderEarnedValueChartFiller earnedValueChartFiller;
private void setupAdvanceAssignmentPlanningController(final Planner planner,

View file

@ -909,9 +909,11 @@ public class PlanningStateCreator {
private void reattachCriterions(Set<Criterion> criterions) {
for (Criterion each : criterions) {
if (!Hibernate.isInitialized(each)) {
criterionDAO.reattachUnmodifiedEntity(each);
}
}
}
private void addingNewlyCreated(IResourceDAO resourceDAO) {
Set<Resource> newResources = getNewResources(resourceDAO);

View file

@ -337,7 +337,7 @@ public class SaveCommandBuilder {
message += validationException.getMessage();
}
LOG.warn(validationException.getMessage());
LOG.warn("Error saving the project", validationException);
Messagebox.show(
_("Error saving the project\n{0}", message),
_("Error"), Messagebox.OK, Messagebox.ERROR);

View file

@ -264,7 +264,8 @@ public class AdvancedAllocationTabCreator {
private Map<String, Object> argsWithController(PlanningState planningState) {
Map<String, Object> result = new HashMap<String, Object>();
advancedAllocationController = new AdvancedAllocationController(onBack,
advancedAllocationController = new AdvancedAllocationController(
planningState.getOrder(), onBack,
createAllocationInputsFor(planningState));
result.put("advancedAllocationController", advancedAllocationController);
return result;
@ -297,7 +298,7 @@ public class AdvancedAllocationTabCreator {
}
private void resetController(PlanningState planningState) {
advancedAllocationController.reset(onBack,
advancedAllocationController.reset(planningState.getOrder(), onBack,
createAllocationInputsFor(planningState));
}

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
* Copyright (C) 2010-2013 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -27,6 +27,7 @@ import static org.libreplan.web.planner.tabs.MultipleTabsPlannerController.getSc
import java.util.HashMap;
import java.util.Map;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.Util;
import org.libreplan.web.common.Util.ReloadStrategy;
import org.libreplan.web.orders.OrderCRUDController;
@ -41,6 +42,7 @@ import org.zkoss.zul.Label;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*
*/
public class OrdersTabCreator {
@ -111,9 +113,23 @@ public class OrdersTabCreator {
}
}
private boolean checkFiltersChanged() {
return (FilterUtils.sessionExists() && FilterUtils
.hasProjectPlanningFilterChanged());
}
private void setFiltersUnchanged() {
FilterUtils.writeProjectFilterChanged(false);
}
@Override
protected void afterShowAction() {
if (checkFiltersChanged()) {
orderCRUDController.readSessionFilterDates();
setFiltersUnchanged();
}
orderCRUDController.goToList();
if (breadcrumbs.getChildren() != null) {
breadcrumbs.getChildren().clear();
}

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
* Copyright (C) 2010-2013 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -34,6 +34,7 @@ import org.libreplan.business.orders.daos.IOrderDAO;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.Util;
import org.libreplan.web.planner.company.CompanyPlanningController;
import org.libreplan.web.planner.order.OrderPlanningController;
@ -49,6 +50,7 @@ import org.zkoss.zul.Label;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*
*/
public class PlanningTabCreator {
@ -205,8 +207,23 @@ public class PlanningTabCreator {
}
}
private boolean checkFiltersChanged() {
return (FilterUtils.sessionExists() && FilterUtils
.hasProjectFilterChanged());
}
private void setFiltersUnchanged() {
FilterUtils.writeProjectPlanningFilterChanged(false);
}
@Override
protected void afterShowAction() {
if (checkFiltersChanged()) {
companyPlanningController
.readSessionVariablesIntoComponents();
setFiltersUnchanged();
}
companyPlanningController.setConfigurationForPlanner();
breadcrumbs.getChildren().clear();
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));

View file

@ -78,8 +78,8 @@ public class AdvancedAllocationTaskController extends GenericForwardComposer {
return;
}
getSwitcher().goToAdvancedAllocation(allocationResult,
createResultReceiver(allocationResult));
getSwitcher().goToAdvancedAllocation(planningState.getOrder(),
allocationResult, createResultReceiver(allocationResult));
}

View file

@ -23,6 +23,7 @@ package org.libreplan.web.resourceload;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.users.entities.User;
public interface IResourceLoadModel {
@ -35,4 +36,6 @@ public interface IResourceLoadModel {
boolean isExpandResourceLoadViewCharts();
User getUser();
}

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2012 Igalia, S.L.
* Copyright (C) 2010-2013 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -46,8 +46,11 @@ import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.daos.IResourcesSearcher;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.users.entities.User;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.components.bandboxsearch.BandboxMultipleSearch;
import org.libreplan.web.common.components.finders.FilterPair;
import org.libreplan.web.common.components.finders.ResourceAllocationFilterEnum;
import org.libreplan.web.planner.chart.Chart;
import org.libreplan.web.planner.chart.StandardLoadChartFiller;
import org.libreplan.web.planner.company.CompanyPlanningModel;
@ -98,6 +101,7 @@ import org.zkoss.zul.api.Combobox;
*
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -141,6 +145,7 @@ public class ResourceLoadController implements Composer {
this.parent = comp;
}
public void reload() {
reloader.resetToInitialState();
reloadWithoutReset();
@ -164,6 +169,8 @@ public class ResourceLoadController implements Composer {
private TimeTracker timeTracker;
private IZoomLevelChangedListener zoomLevelListener;
public Reloader() {
}
@ -247,14 +254,53 @@ public class ResourceLoadController implements Composer {
}
private TimeTracker buildTimeTracker(ResourceLoadDisplayData dataToShow) {
ZoomLevel zoomLevel = dataToShow.getInitialZoomLevel();
ZoomLevel zoomLevel = getZoomLevel(dataToShow);
TimeTracker result = new TimeTracker(dataToShow.getViewInterval(),
zoomLevel, SeveralModificators.create(),
SeveralModificators.create(createBankHolidaysMarker()),
parent);
setupZoomLevelListener(result);
return result;
}
private ZoomLevel getZoomLevel(ResourceLoadDisplayData dataToShow) {
if (filterBy != null) {
Order order = filterBy.getOrder();
ZoomLevel sessionZoom = FilterUtils.readZoomLevel(order);
if (sessionZoom != null) {
return sessionZoom;
}
}
ZoomLevel sessionZoom = FilterUtils.readZoomLevelResourcesLoad();
if (sessionZoom != null) {
return sessionZoom;
}
return dataToShow.getInitialZoomLevel();
}
private void setupZoomLevelListener(TimeTracker timeTracker) {
zoomLevelListener = getSessionZoomLevelListener();
timeTracker.addZoomListener(zoomLevelListener);
}
private IZoomLevelChangedListener getSessionZoomLevelListener() {
IZoomLevelChangedListener zoomListener = new IZoomLevelChangedListener() {
@Override
public void zoomLevelChanged(ZoomLevel detailLevel) {
if (filterBy != null) {
Order order = filterBy.getOrder();
FilterUtils.writeZoomLevel(order, detailLevel);
} else {
FilterUtils.writeZoomLevelResourcesLoad(detailLevel);
}
}
};
return zoomListener;
}
private ResourcesLoadPanel buildPanel(ResourceLoadDisplayData dataToShow) {
return new ResourcesLoadPanel(dataToShow.getLoadTimeLines(),
timeTracker, parent,
@ -268,12 +314,55 @@ public class ResourceLoadController implements Composer {
FilterTypeChanger filterTypeChanger = new FilterTypeChanger(onChange,
filterBy);
result.add(filterTypeChanger);
result.add(new ByDatesFilter(onChange, filterBy));
// Only by dates and bandbox filter on global resources load
if (filterBy == null) {
LocalDate startDate = FilterUtils.readResourceLoadsStartDate();
LocalDate endDate = FilterUtils.readResourceLoadsEndDate();
User user = resourceLoadModel.getUser();
// Calculate filter based on user preferences
if (user != null) {
if (startDate == null
&& !FilterUtils.hasResourceLoadsStartDateChanged()) {
if (user.getResourcesLoadFilterPeriodSince() != null) {
startDate = new LocalDate().minusMonths(user
.getResourcesLoadFilterPeriodSince());
} else {
// Default filter start
startDate = new LocalDate().minusDays(1);
}
}
if ((endDate == null)
&& !FilterUtils.hasResourceLoadsEndDateChanged()
&& (user.getResourcesLoadFilterPeriodTo() != null)) {
endDate = new LocalDate().plusMonths(user
.getResourcesLoadFilterPeriodTo());
}
}
result.add(new ByDatesFilter(onChange, filterBy, startDate, endDate));
List<FilterPair> filterPairs = (List<FilterPair>) FilterUtils
.readResourceLoadsBandbox();
if ((filterPairs == null || filterPairs.isEmpty())
&& user.getResourcesLoadFilterCriterion() != null) {
filterPairs = new ArrayList<FilterPair>();
filterPairs.add(new FilterPair(
ResourceAllocationFilterEnum.Criterion, user
.getResourcesLoadFilterCriterion()
.getFinderPattern(), user
.getResourcesLoadFilterCriterion()));
}
WorkersOrCriteriaBandbox bandbox = new WorkersOrCriteriaBandbox(
onChange, filterBy, filterTypeChanger, resourcesSearcher);
onChange, filterBy, filterTypeChanger, resourcesSearcher, filterPairs);
result.add(bandbox);
result.add(new ByNamePaginator(onChange, filterBy, filterTypeChanger,
bandbox));
}
result.add(new LoadChart(onChange, filterBy));
return result;
}
@ -412,10 +501,14 @@ public class ResourceLoadController implements Composer {
private final Datebox endBox = new Datebox();
private ByDatesFilter(Runnable onChange, PlanningState filterBy) {
private ByDatesFilter(Runnable onChange, PlanningState filterBy,
LocalDate startDate, LocalDate endDate) {
super(onChange, filterBy);
startDateValue = isAppliedToOrder() ? null : new LocalDate()
.minusDays(1);
startDateValue = (isAppliedToOrder() || (startDate == null)) ? null
: startDate
.toDateTimeAtStartOfDay().toLocalDate();
endDateValue = (endDate == null) ? null : endDate
.toDateMidnight().toLocalDate();
}
@Override
@ -435,10 +528,12 @@ public class ResourceLoadController implements Composer {
LocalDate newStart = toLocal(startBox.getValue());
if (!ObjectUtils.equals(startDateValue, newStart)) {
startDateValue = newStart;
FilterUtils.writeResourceLoadsStartDate(startDateValue);
notifyChange();
}
}
});
endBox.setValue(asDate(endDateValue));
endBox.setWidth("100px");
endBox.addEventListener(Events.ON_CHANGE, new EventListener() {
@ -447,10 +542,12 @@ public class ResourceLoadController implements Composer {
LocalDate newEnd = toLocal(endBox.getValue());
if (!ObjectUtils.equals(endBox, newEnd)) {
endDateValue = newEnd;
FilterUtils.writeResourceLoadsEndDate(endDateValue);
notifyChange();
}
}
});
Hbox hbox = new Hbox();
hbox.appendChild(new Label(_("From") + ":"));
hbox.appendChild(startBox);
@ -510,9 +607,19 @@ public class ResourceLoadController implements Composer {
private WorkersOrCriteriaBandbox(Runnable onChange,
PlanningState filterBy, FilterTypeChanger filterType,
IResourcesSearcher resourcesSearcher) {
IResourcesSearcher resourcesSearcher,
List<FilterPair> selectedFilters) {
super(onChange, filterBy, filterType);
this.resourcesSearcher = resourcesSearcher;
initBandbox();
if ((selectedFilters != null) && !selectedFilters.isEmpty()) {
for (FilterPair filterPair : selectedFilters) {
bandBox.addSelectedElement(filterPair);
}
entitiesSelected = getSelected();
}
}
@Override
@ -523,7 +630,7 @@ public class ResourceLoadController implements Composer {
panel.setSecondOptionalFilter(buildBandboxFilterer());
}
private Hbox buildBandboxFilterer() {
private void initBandbox() {
bandBox.setId("workerBandboxMultipleSearch");
bandBox.setWidthBandbox("185px");
bandBox.setWidthListbox("450px");
@ -534,10 +641,14 @@ public class ResourceLoadController implements Composer {
@Override
public void onEvent(Event event) throws Exception {
entitiesSelected = getSelected();
FilterUtils.writeResourceLoadsParameters(bandBox
.getSelectedElements());
notifyChange();
}
});
}
private Hbox buildBandboxFilterer() {
Hbox hbox = new Hbox();
hbox.appendChild(getLabel());
hbox.appendChild(bandBox);

View file

@ -1065,6 +1065,23 @@ public class ResourceLoadModel implements IResourceLoadModel {
return user.isExpandResourceLoadViewCharts();
}
@Override
@Transactional(readOnly = true)
public User getUser() {
User user;
try {
user = this.userDAO.findByLoginName(SecurityUtils
.getSessionUserLoginName());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
// Attach filter bandbox elements
if (user.getResourcesLoadFilterCriterion() != null) {
user.getResourcesLoadFilterCriterion().getFinderPattern();
}
return user;
}
}
class PeriodBuilderFactory {

View file

@ -23,9 +23,11 @@ package org.libreplan.web.resources.search;
import java.util.List;
import org.libreplan.business.resources.daos.IResourceLoadRatiosCalculator;
import org.libreplan.business.resources.daos.IResourcesSearcher;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.scenarios.IScenarioManager;
import org.libreplan.web.common.components.ResourceAllocationBehaviour;
import org.libreplan.web.planner.allocation.INewAllocationsAdder;
import org.zkoss.zk.ui.util.GenericForwardComposer;
@ -40,9 +42,15 @@ public abstract class AllocationSelectorController extends
// injected by name
protected IResourcesSearcher resourcesSearcher;
// injected by name
protected IResourceLoadRatiosCalculator resourceLoadRatiosCalculator;
// injected by name
protected ResourceAllocationBehaviour behaviour;
// injected by name
protected IScenarioManager scenarioManager;
public AllocationSelectorController() {
}

View file

@ -21,10 +21,14 @@
package org.libreplan.web.resources.search;
import static org.libreplan.web.I18nHelper._;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
@ -32,6 +36,9 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate;
import org.libreplan.business.resources.daos.IResourceLoadRatiosCalculator.ILoadRatiosDataType;
import org.libreplan.business.resources.daos.IResourcesSearcher.IResourcesQuery;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.CriterionType;
@ -43,10 +50,15 @@ import org.libreplan.web.common.components.ResourceAllocationBehaviour;
import org.libreplan.web.planner.allocation.INewAllocationsAdder;
import org.zkoss.lang.Objects;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.InputEvent;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Div;
import org.zkoss.zul.Image;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
@ -63,15 +75,23 @@ import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.api.Listheader;
/**
* @author Diego Pino Garcia <dpino@igalia.com>
* Controller for searching for {@link Resource}.
*
* @author Diego Pino Garcia <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
*
* Controller for searching for {@link Resource}
*/
public class NewAllocationSelectorController extends
AllocationSelectorController {
private static final BigDecimal AVALIABILITY_GOOD_VALUE = new BigDecimal(
0.50);
private static final BigDecimal AVALIABILITY_INTERMEDIUM_VALUE = new BigDecimal(
0.25);
private ResourceListRenderer resourceListRenderer = new ResourceListRenderer();
private Radiogroup allocationTypeSelector;
@ -82,6 +102,8 @@ public class NewAllocationSelectorController extends
private Label allocationSelectedItems;
private Datebox startDateLoadRatiosDatebox, endDateLoadRatiosDatebox;
private CriterionRenderer criterionRenderer = new CriterionRenderer();
private AllocationType currentAllocationType;
@ -103,6 +125,23 @@ public class NewAllocationSelectorController extends
initializeCriteriaTree();
initializeListboxResources();
initializeAllocationTypeSelector();
initializeFilteringDates();
}
private void initializeFilteringDates() {
// Start and end filtering dates are initialized here because
// they cannot be empty and must have always a value. The
// task start date and task end date are not available at the first
// rendering. Thus, the current date and current date + 1 day are used
// as the value to initialize the components although will
// never be visible by the user.
Date initDate = new Date();
setStartFilteringDate(initDate);
setEndFilteringDate(LocalDate.fromDateFields(initDate).plusDays(1)
.toDateTimeAtStartOfDay().toDate());
startDateLoadRatiosDatebox
.setConstraint(checkConstraintFilteringDate());
endDateLoadRatiosDatebox.setConstraint(checkConstraintFilteringDate());
}
private void initializeCriteriaTree() {
@ -197,8 +236,41 @@ public class NewAllocationSelectorController extends
}
}
private List<? extends Resource> getAllResources() {
return query().byResourceType(getType()).execute();
private List<ResourceWithItsLoadRatios> getAllResources() {
List<ResourceWithItsLoadRatios> result = new ArrayList<ResourceWithItsLoadRatios>();
// The search is only done in case that the endFilteringDate and
// startFilteringDate are initialized. This happens when the
// user does the advanced search visible by clicking on the
// AdvancedSearch button
if ((startDateLoadRatiosDatebox.getValue() != null)
&& (endDateLoadRatiosDatebox.getValue() != null)) {
List<? extends Resource> listResources = query().byResourceType(
getType()).execute();
result = addLoadRatiosCalculations(listResources);
}
return result;
}
private List<ResourceWithItsLoadRatios> addLoadRatiosCalculations(
List<? extends Resource> listResources) {
List<ResourceWithItsLoadRatios> result = new ArrayList<ResourceWithItsLoadRatios>();
for (Resource each : listResources) {
ILoadRatiosDataType t = resourceLoadRatiosCalculator
.calculateLoadRatios(each, LocalDate
.fromDateFields(startDateLoadRatiosDatebox
.getValue()),
LocalDate.fromDateFields(endDateLoadRatiosDatebox
.getValue()), scenarioManager.getCurrent());
result.add(new ResourceWithItsLoadRatios(each, t));
}
return result;
}
private ResourceType getType() {
@ -213,16 +285,28 @@ public class NewAllocationSelectorController extends
refreshListBoxResources(getAllResources());
}
private void refreshListBoxResources(List<? extends Resource> resources) {
private void refreshListBoxResources(
List<ResourceWithItsLoadRatios> resources) {
listBoxResources.setModel(new SimpleListModel(resources));
triggerSortListBoxResources();
}
private void triggerSortListBoxResources() {
for (Object child : listBoxResources.getListhead().getChildren()) {
final Listheader hd = (Listheader) child;
if (!"natural".equals(hd.getSortDirection())) {
hd.sort("ascending".equals(hd.getSortDirection()), true);
}
}
}
private void returnToSpecificDueToResourceSelection() {
currentAllocationType = AllocationType.SPECIFIC;
List<Criterion> criteria = getSelectedCriterions();
List<Resource> selectedWorkers = getSelectedWorkers();
refreshListBoxResources(query().byCriteria(criteria)
.byResourceType(getType()).execute());
refreshListBoxResources(addLoadRatiosCalculations(query()
.byCriteria(criteria).byResourceType(getType()).execute()));
listBoxResources.renderAll(); // force render so list items has the
// value property so the resources can be
// selected
@ -244,7 +328,8 @@ public class NewAllocationSelectorController extends
@SuppressWarnings("unchecked")
Collection<Listitem> items = listBoxResources.getItems();
for (Listitem item : items) {
Resource itemResource = (Resource) item.getValue();
Resource itemResource = ((ResourceWithItsLoadRatios) item
.getValue()).getResource();
if (itemResource != null
&& itemResource.getId().equals(resource.getId())) {
return item;
@ -262,8 +347,8 @@ public class NewAllocationSelectorController extends
@SuppressWarnings("unchecked")
private void clearSelection(Listbox listBox) {
Set<Listitem> selectedItems = new HashSet<Listitem>(listBox
.getSelectedItems());
Set<Listitem> selectedItems = new HashSet<Listitem>(
listBox.getSelectedItems());
for (Listitem each : selectedItems) {
listBox.removeItemFromSelection(each);
}
@ -271,7 +356,8 @@ public class NewAllocationSelectorController extends
@SuppressWarnings("unchecked")
private void clearSelection(Tree tree) {
Set<Treeitem> selectedItems = new HashSet<Treeitem>(tree.getSelectedItems());
Set<Treeitem> selectedItems = new HashSet<Treeitem>(
tree.getSelectedItems());
for (Treeitem each : selectedItems) {
tree.removeItemFromSelection(each);
}
@ -294,10 +380,8 @@ public class NewAllocationSelectorController extends
*/
private void searchResources(String name, List<Criterion> criterions) {
final List<? extends Resource> resources = query().byName(name)
.byCriteria(criterions)
.byResourceType(getType())
.execute();
refreshListBoxResources(resources);
.byCriteria(criterions).byResourceType(getType()).execute();
refreshListBoxResources(addLoadRatiosCalculations(resources));
}
/**
@ -306,6 +390,7 @@ public class NewAllocationSelectorController extends
*
* @return
*/
@Override
public List<Criterion> getSelectedCriterions() {
List<Criterion> result = new ArrayList<Criterion>();
@ -324,10 +409,12 @@ public class NewAllocationSelectorController extends
return resourceListRenderer;
}
@Override
public void onClose() {
clearAll();
}
@Override
public void clearAll() {
refreshListBoxResources();
criterionsTree.setModel(getCriterions());
@ -349,7 +436,8 @@ public class NewAllocationSelectorController extends
List<Resource> result = new ArrayList<Resource>();
List<Listitem> selectedItems = listBoxResources.getItems();
for (Listitem item : selectedItems) {
result.add((Resource) item.getValue());
result.add(((ResourceWithItsLoadRatios) item.getValue())
.getResource());
}
return result;
}
@ -359,7 +447,9 @@ public class NewAllocationSelectorController extends
List<Resource> result = new ArrayList<Resource>();
Set<Listitem> selectedItems = listBoxResources.getSelectedItems();
for (Listitem item : selectedItems) {
result.add((Resource) item.getValue());
result.add(((ResourceWithItsLoadRatios) item.getValue())
.getResource());
}
return result;
}
@ -466,6 +556,34 @@ public class NewAllocationSelectorController extends
toNodeList(criterion.getChildren()));
}
private static class ResourceWithItsLoadRatios implements
Comparable<ResourceWithItsLoadRatios> {
private Resource resource;
private ILoadRatiosDataType ratios;
public ResourceWithItsLoadRatios(Resource resource,
ILoadRatiosDataType ratios) {
Validate.notNull(resource);
Validate.notNull(ratios);
this.resource = resource;
this.ratios = ratios;
}
public Resource getResource() {
return this.resource;
}
public ILoadRatiosDataType getRatios() {
return this.ratios;
}
@Override
public int compareTo(ResourceWithItsLoadRatios o) {
return this.resource.compareTo(o.getResource());
}
}
/**
* @author Diego Pino García <dpino@igalia.com>
*
@ -475,17 +593,62 @@ public class NewAllocationSelectorController extends
@Override
public void render(Listitem item, Object data) {
item.setValue((Resource) data);
item.setValue(data);
appendLabelResource(item);
}
private void appendLabelResource(Listitem item) {
Resource resource = (Resource) item.getValue();
ResourceWithItsLoadRatios dataToRender = (ResourceWithItsLoadRatios) item
.getValue();
Listcell cell = new Listcell();
cell.appendChild(new Label(resource.getShortDescription()));
item.appendChild(cell);
Listcell cellName = new Listcell();
Resource resource = dataToRender.getResource();
cellName.appendChild(new Label(resource.getShortDescription()));
item.appendChild(cellName);
Listcell cellAvailability = new Listcell();
BigDecimal availability = dataToRender.getRatios()
.getAvailiabilityRatio();
Div totalDiv = new Div();
totalDiv.setStyle("width:50px;height:12px;border: solid 1px black");
Div containedDiv = new Div();
String styleValue = "width:" + availability.movePointRight(2)
+ "%;height:12px;background-color:"
+ calculateRgba(availability) + ";float:left;left:0";
containedDiv.setStyle(styleValue);
Label l = new Label(availability.movePointRight(2).toString() + "%");
l.setStyle("width:50px;margin-left: 12px");
containedDiv.appendChild(l);
totalDiv.appendChild(containedDiv);
cellAvailability.appendChild(totalDiv);
item.appendChild(cellAvailability);
Listcell cellOvertime = new Listcell();
BigDecimal overtime = dataToRender.getRatios().getOvertimeRatio();
Label overtimeLabel = new Label(overtime.toString());
cellOvertime.appendChild(overtimeLabel);
if (!overtime.equals(BigDecimal.ZERO.setScale(2))) {
overtimeLabel.setStyle("position: relative; top: -12px");
Image img = new Image(
"/dashboard/img/value-meaning-negative.png");
img.setStyle("width: 25px; position: relative; top: -5px");
cellOvertime.appendChild(img);
}
item.appendChild(cellOvertime);
}
private String calculateRgba(BigDecimal avaliability) {
String result;
if (avaliability.compareTo(AVALIABILITY_INTERMEDIUM_VALUE) < 0) {
result = "rgba(150,0,0,0.3)";
} else if (avaliability.compareTo(AVALIABILITY_GOOD_VALUE) < 0) {
result = "rgba(255,255,0,0.5)";
} else {
result = "rgba(102,204,0,0.3)";
}
return result;
}
}
@ -534,6 +697,7 @@ public class NewAllocationSelectorController extends
}
@Override
public void addTo(INewAllocationsAdder allocationsAdder) {
currentAllocationType.addTo(this, allocationsAdder);
}
@ -546,4 +710,54 @@ public class NewAllocationSelectorController extends
return listBoxResources.isMultiple();
}
public void setEndFilteringDate(Date d) {
endDateLoadRatiosDatebox.setValue(d);
}
public void setStartFilteringDate(Date d) {
startDateLoadRatiosDatebox.setValue(d);
}
public void updateLoadRatios() {
searchResources("", getSelectedCriterions());
}
public Constraint checkConstraintFilteringDate() {
return new Constraint() {
@Override
public void validate(Component comp, Object value) throws WrongValueException {
if (value == null) {
if (comp.getId().equals("startDateLoadRatiosDatebox")) {
throw new WrongValueException(comp,
_("Start filtering date cannot be empty"));
} else if (comp.getId().equals("endDateLoadRatiosDatebox")) {
throw new WrongValueException(comp,
_("End filtering date cannot be empty"));
}
}
Date startDate = null;
if (comp.getId().equals("startDateLoadRatiosDatebox")) {
startDate = (Date) value;
} else {
startDate = (Date) startDateLoadRatiosDatebox.getRawValue();
}
Date endDate = null;
if (comp.getId().equals("endDateLoadRatiosDatebox")) {
endDate = (Date) value;
} else {
endDate = (Date) endDateLoadRatiosDatebox.getRawValue();
}
if ((startDate != null) && (endDate != null)) {
if ((startDate.after(endDate))
|| (startDate.equals(endDate))) {
throw new WrongValueException(comp,_("Start filtering date must be before than end filtering date"));
}
}
}
};
}
}

View file

@ -250,6 +250,10 @@ public abstract class TreeController<T extends ITreeNode<T>> extends
getRenderer().refreshHoursValueForThisNodeAndParents(newNode);
getRenderer().refreshBudgetValueForThisNodeAndParents(newNode);
// Moved here in order to have items already renderer in order
// to select the proper element to focus
filterByPredicateIfAny();
if (node.isLeaf() && !node.isEmptyLeaf()) {
// Then a new container will be created
nameTextbox = getRenderer().getNameTextbox(node);
@ -260,8 +264,11 @@ public abstract class TreeController<T extends ITreeNode<T>> extends
}
} else {
getModel().addElement(name.getValue(), hours.getValue());
}
// This is needed in both parts of the if, but it's repeated in
// order to simplify the code
filterByPredicateIfAny();
}
} catch (IllegalStateException e) {
LOG.warn("exception ocurred adding element", e);
messagesForUser.showMessage(Level.ERROR, e.getMessage());

View file

@ -2,6 +2,7 @@
* This file is part of LibrePlan
*
* Copyright (C) 2011 ComtecSF, S.L.
* Copyright (C) 2013 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -18,7 +19,11 @@
*/
package org.libreplan.web.users.settings;
import java.util.List;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.settings.entities.Language;
@ -27,6 +32,7 @@ import org.libreplan.business.settings.entities.Language;
*
* @author Cristina Alvarino Perez <cristina.alvarino@comtecsf.es>
* @author Ignacio Diaz Teijido <ignacio.diaz@comtecsf.es>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
public interface ISettingsModel {
@ -67,4 +73,32 @@ public interface ISettingsModel {
boolean isBound();
Integer getProjectsFilterPeriodSince();
void setProjectsFilterPeriodSince(Integer period);
Integer getProjectsFilterPeriodTo();
void setProjectsFilterPeriodTo(Integer period);
Integer getResourcesLoadFilterPeriodSince();
void setResourcesLoadFilterPeriodSince(Integer period);
Integer getResourcesLoadFilterPeriodTo();
void setResourcesLoadFilterPeriodTo(Integer period);
Label getProjectsFilterLabel();
List<Label> getAllLabels();
void setProjectsFilterLabel(Label label);
List<Criterion> getAllCriteria();
Criterion getResourcesLoadFilterCriterion();
void setResourcesLoadFilterCriterion(Criterion criterion);
}

View file

@ -2,6 +2,7 @@
* This file is part of LibrePlan
*
* Copyright (C) 2011 ComtecSF, S.L.
* Copyright (C) 2013 Igalia.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -25,14 +26,26 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Filter;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.settings.entities.Language;
import org.libreplan.web.common.FilterUtils;
import org.libreplan.web.common.IMessagesForUser;
import org.libreplan.web.common.Level;
import org.libreplan.web.common.MessagesForUser;
import org.libreplan.web.common.components.bandboxsearch.BandboxSearch;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Textbox;
@ -41,6 +54,7 @@ import org.zkoss.zul.Textbox;
*
* @author Cristina Alvarino Perez <cristina.alvarino@comtecsf.es>
* @author Ignacio Diaz Teijido <ignacio.diaz@comtecsf.es>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
public class SettingsController extends GenericForwardComposer {
@ -52,6 +66,10 @@ public class SettingsController extends GenericForwardComposer {
private Textbox password;
private BandboxSearch projectsFilterLabelBandboxSearch;
private BandboxSearch resourcesLoadFilterCriterionBandboxSearch;
public static ListitemRenderer languagesRenderer = new ListitemRenderer() {
@Override
public void render(org.zkoss.zul.Listitem item, Object data)
@ -71,6 +89,25 @@ public class SettingsController extends GenericForwardComposer {
comp.setVariable("settingsController", this, true);
messages = new MessagesForUser(messagesContainer);
settingsModel.initEditLoggedUser();
projectsFilterLabelBandboxSearch.setListboxEventListener(
Events.ON_SELECT, new EventListener() {
@Override
public void onEvent(Event event) {
Listitem selectedItem = (Listitem) ((SelectEvent) event)
.getSelectedItems().iterator().next();
setProjectsFilterLabel((Label) selectedItem.getValue());
}
});
resourcesLoadFilterCriterionBandboxSearch.setListboxEventListener(
Events.ON_SELECT, new EventListener() {
@Override
public void onEvent(Event event) {
Listitem selectedItem = (Listitem) ((SelectEvent) event)
.getSelectedItems().iterator().next();
setResourcesLoadFilterCriterion((Criterion) selectedItem
.getValue());
}
});
}
public List<Language> getLanguages() {
@ -92,6 +129,8 @@ public class SettingsController extends GenericForwardComposer {
public boolean save() {
try {
checkEmptyBandboxes();
clearSessionVariables();
settingsModel.confirmSave();
messages.showMessage(Level.INFO, _("Settings saved"));
return true;
@ -101,6 +140,20 @@ public class SettingsController extends GenericForwardComposer {
return false;
}
private void clearSessionVariables() {
FilterUtils.clearBandboxes();
FilterUtils.clearSessionDates();
}
private void checkEmptyBandboxes() {
if (projectsFilterLabelBandboxSearch.getSelectedElement() == null) {
settingsModel.setProjectsFilterLabel(null);
}
if (resourcesLoadFilterCriterionBandboxSearch.getSelectedElement() == null) {
settingsModel.setResourcesLoadFilterCriterion(null);
}
}
public void setSelectedLanguage(Language language) {
settingsModel.setApplicationLanguage(language);
}
@ -176,4 +229,60 @@ public class SettingsController extends GenericForwardComposer {
return settingsModel.isBound();
}
public Integer getProjectsFilterPeriodSince() {
return settingsModel.getProjectsFilterPeriodSince();
}
public void setProjectsFilterPeriodSince(Integer period) {
settingsModel.setProjectsFilterPeriodSince(period);
}
public Integer getProjectsFilterPeriodTo() {
return settingsModel.getProjectsFilterPeriodTo();
}
public void setProjectsFilterPeriodTo(Integer period) {
settingsModel.setProjectsFilterPeriodTo(period);
}
public Integer getResourcesLoadFilterPeriodSince() {
return settingsModel.getResourcesLoadFilterPeriodSince();
}
public void setResourcesLoadFilterPeriodSince(Integer period) {
settingsModel.setResourcesLoadFilterPeriodSince(period);
}
public Integer getResourcesLoadFilterPeriodTo() {
return settingsModel.getResourcesLoadFilterPeriodTo();
}
public void setResourcesLoadFilterPeriodTo(Integer period) {
settingsModel.setResourcesLoadFilterPeriodTo(period);
}
public List<Label> getAllLabels() {
return settingsModel.getAllLabels();
}
public Label getProjectsFilterLabel() {
return settingsModel.getProjectsFilterLabel();
}
public void setProjectsFilterLabel(Label label) {
settingsModel.setProjectsFilterLabel(label);
}
public List<Criterion> getAllCriteria() {
return settingsModel.getAllCriteria();
}
public Criterion getResourcesLoadFilterCriterion() {
return settingsModel.getResourcesLoadFilterCriterion();
}
public void setResourcesLoadFilterCriterion(Criterion criterion) {
settingsModel.setResourcesLoadFilterCriterion(criterion);
}
}

View file

@ -19,9 +19,16 @@
package org.libreplan.web.users.settings;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.labels.daos.ILabelDAO;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.resources.daos.ICriterionDAO;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.settings.entities.Language;
import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.entities.Profile;
@ -49,8 +56,18 @@ public class SettingsModel implements ISettingsModel {
@Autowired
private IUserDAO userDAO;
@Autowired
private ILabelDAO labelsDAO;
@Autowired
private ICriterionDAO criterionDAO;
private User user;
private List<Label> allLabels;
private List<Criterion> allCriteria;
@Override
public Language getApplicationLanguage() {
return user.getApplicationLanguage();
@ -74,6 +91,26 @@ public class SettingsModel implements ISettingsModel {
public void initEditLoggedUser() {
User user = findByLoginUser(SecurityUtils.getSessionUserLoginName());
this.user = getFromDB(user);
loadAllLabels();
loadAllCriteria();
}
@Transactional(readOnly = true)
private void loadAllLabels() {
allLabels = labelsDAO.getAll();
// initialize the labels
for (Label label : allLabels) {
label.getType().getName();
}
}
@Transactional(readOnly = true)
private void loadAllCriteria() {
allCriteria = criterionDAO.getAll();
// initialize the criteria
for (Criterion criterion : allCriteria) {
criterion.getType().getName();
}
}
@Transactional(readOnly = true)
@ -202,4 +239,76 @@ public class SettingsModel implements ISettingsModel {
return false;
}
@Override
public Integer getProjectsFilterPeriodSince() {
return user.getProjectsFilterPeriodSince();
}
@Override
public void setProjectsFilterPeriodSince(Integer period) {
user.setProjectsFilterPeriodSince(period);
}
@Override
public Integer getProjectsFilterPeriodTo() {
return user.getProjectsFilterPeriodTo();
}
@Override
public void setProjectsFilterPeriodTo(Integer period) {
user.setProjectsFilterPeriodTo(period);
}
@Override
public Integer getResourcesLoadFilterPeriodSince() {
return user.getResourcesLoadFilterPeriodSince();
}
@Override
public void setResourcesLoadFilterPeriodSince(Integer period) {
user.setResourcesLoadFilterPeriodSince(period);
}
@Override
public Integer getResourcesLoadFilterPeriodTo() {
return user.getResourcesLoadFilterPeriodTo();
}
@Override
public void setResourcesLoadFilterPeriodTo(Integer period) {
user.setResourcesLoadFilterPeriodTo(period);
}
@Override
@Transactional(readOnly = true)
public List<Label> getAllLabels() {
return allLabels;
}
@Override
public Label getProjectsFilterLabel() {
return user.getProjectsFilterLabel();
}
@Override
public void setProjectsFilterLabel(Label label) {
user.setProjectsFilterLabel(label);
}
@Override
@Transactional(readOnly = true)
public List<Criterion> getAllCriteria() {
return allCriteria;
}
@Override
public Criterion getResourcesLoadFilterCriterion() {
return user.getResourcesLoadFilterCriterion();
}
@Override
public void setResourcesLoadFilterCriterion(Criterion criterion) {
user.setResourcesLoadFilterCriterion(criterion);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
This file is part of LibrePlan
Copyright (C) 2011 ComtecSF, S.L.
Copyright (C) 2013 Igalia, S.L.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -117,6 +118,40 @@
</rows>
</grid>
</row>
<row>
<label
value="${i18n:_('Projects view filtering')}" />
<hbox>
<label value="${i18n:_('Label filter')}" />
<bandboxSearch
id="projectsFilterLabelBandboxSearch"
finder="LabelBandboxFinder"
model="@{settingsController.allLabels}"
selectedElement="@{settingsController.projectsFilterLabel}"
widthListbox="450px" widthBandbox="200px"/>
<label value="${i18n:_('Projects since')}" />
<intbox id="projectsFilterPeriodSince" value="@{settingsController.projectsFilterPeriodSince}" width="50px"/>
<label value="${i18n:_('months to')}" />
<intbox id="projectsFilterPeriodTo" value="@{settingsController.projectsFilterPeriodTo}" width="50px"/>
</hbox>
</row>
<row>
<label
value="${i18n:_('Resources load filtering')}" />
<hbox>
<label value="${i18n:_('Criterion filter')}" />
<bandboxSearch
id="resourcesLoadFilterCriterionBandboxSearch"
finder="CriterionBandboxFinder"
model="@{settingsController.allCriteria}"
selectedElement="@{settingsController.resourcesLoadFilterCriterion}"
widthListbox="450px" widthBandbox="200px"/>
<label value="${i18n:_('Resources load since')}" />
<intbox id="resourcesLoadFilterPeriodSince" value="@{settingsController.resourcesLoadFilterPeriodSince}" width="50px"/>
<label value="${i18n:_('months to')}" />
<intbox id="resourcesLoadFilterPeriodTo" value="@{settingsController.resourcesLoadFilterPeriodTo}" width="50px"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>

View file

@ -23,10 +23,10 @@
<label value="${i18n:_('Task')}"
tooltiptext="${i18n:_('Select required criteria set and press filter button')}"/>
<textbox id="filterNameOrderElement" width="100px"
onOK="treeController.onApplyFilter()" />
onChange="treeController.onApplyFilter()" />
<label value="${i18n:_('with')}"/>
<bandboxMultipleSearch id="bdFiltersOrderElement" widthBandbox="260px" widthListbox="550px"
finder="orderElementsMultipleFiltersFinder" />
finder="orderElementsMultipleFiltersFinder" onChange="treeController.onApplyFilter()" />
<button id="optionsButton" label="${i18n:_('options')}" dir="reverse"
image="/common/img/ico_dropdown.png" style="margin-top: -2px"
tooltiptext="${i18n:_('Set Filter Options')}"
@ -38,12 +38,12 @@
<popup id="filterOptionsPopup" sclass="filter-options-popup">
<hbox align="pack">
<label value="${i18n:_('from')}"/>
<datebox id="filterStartDateOrderElement" constraint = "@{treeController.checkConstraintStartDate}" />
<datebox id="filterStartDateOrderElement" constraint = "@{treeController.checkConstraintStartDate}" onChange="treeController.onApplyFilter()" />
<label value="${i18n:_('to')}"/>
<datebox id="filterFinishDateOrderElement" constraint = "@{treeController.checkConstraintFinishDate}" />
<datebox id="filterFinishDateOrderElement" constraint = "@{treeController.checkConstraintFinishDate}" onChange="treeController.onApplyFilter()" />
</hbox>
<hbox align="pack">
<checkbox id="labelsWithoutInheritance" checked="false" label="${i18n:_('Labels without inheritance')}"/>
<checkbox id="labelsWithoutInheritance" checked="false" label="${i18n:_('Labels without inheritance')}" onChange="treeController.onApplyFilter()" />
</hbox>
</popup>
</hbox>

View file

@ -23,11 +23,13 @@
<label value=" ${i18n:_('Filter')}"
tooltiptext="${i18n:_('Select required criteria set and press filter button')}"/>
<bandboxMultipleSearch id="bdFilters" widthBandbox="260px" widthListbox="550px"
finder="ordersMultipleFiltersFinder"/>
finder="ordersMultipleFiltersFinder" onChange="orderFilterController.onApplyFilter()" />
<label value="${i18n:_('from')}"/>
<datebox id="filterStartDate" constraint = "@{orderFilterController.checkConstraintStartDate}"/>
<datebox id="filterStartDate" constraint = "@{orderFilterController.checkConstraintStartDate}"
onChange="orderFilterController.onApplyFilter()"/>
<label value="${i18n:_('to')}"/>
<datebox id="filterFinishDate" constraint = "@{orderFilterController.checkConstraintFinishDate}"/>
<datebox id="filterFinishDate" constraint = "@{orderFilterController.checkConstraintFinishDate}"
onChange="orderFilterController.onApplyFilter()"/>
<label value="${i18n:_('subelements')}"/>
<checkbox id="checkIncludeOrderElements"
tooltiptext="${i18n:_('Apply filtering to tasks satisfying required criteria')}" />

View file

@ -32,7 +32,7 @@
<vbox sclass="allocation-criterion-selector">
<tree id="criterionsTree" width="420px"
height="340px" vflex="true" multiple="true"
height="412px" vflex="true" multiple="true"
model="@{selectorController.criterions}"
zclass="z-dottree" style="margin-top:5px;margin-bottom:5px;">
<treecols>
@ -44,13 +44,43 @@
<!--Matchings -->
<vbox>
<label value="${i18n:_('Load ratios calculated between')}:"/>
<separator/>
<grid fixedLayout="true">
<columns>
<column/>
<column/>
</columns>
<rows>
<row>
<label value="${i18n:_('Start date')}:"/>
<datebox id="startDateLoadRatiosDatebox"
onChange="selectorController.updateLoadRatios()"/>
</row>
<row>
<label value="${i18n:_('End date')}:"/>
<datebox id="endDateLoadRatiosDatebox"
onChange="selectorController.updateLoadRatios()"/>
</row>
</rows>
</grid>
<style>
.z-listcell-cnt {
height: 20px;
}
div.z-listcell-cnt {
padding: 5px 0 1px 0;
}
</style>
<listbox id="listBoxResources" width="420px" height="340px"
vflex="true" multiple="@{selectorController.allowSelectMultipleResources}" style="margin:5px;"
itemRenderer="@{selectorController.listitemRenderer}" >
<listhead>
<listheader label="${i18n:_('Found resources')}"
tooltiptext="${i18n:_('Resources matching selected criteria')}" sort="auto" />
tooltiptext="${i18n:_('Resources matching selected criteria')}"
sort="auto" sortDirection="ascending"/>
<listheader label="${i18n:_('Availability')}" hflex="min"/>
<listheader label="${i18n:_('Overtime')}" hflex="min"/>
</listhead>
</listbox>