Merge branch 'master' into subcontracting

This commit is contained in:
Susana Montes Pedreira 2012-05-08 18:16:09 +01:00
commit 7364bb000d
245 changed files with 54491 additions and 3607 deletions

View file

@ -42,6 +42,7 @@ Translators
Diego Pino García <dpino@igalia.com> Diego Pino García <dpino@igalia.com>
* [it] Giuseppe Zizza <gzizza@gmail.com> * [it] Giuseppe Zizza <gzizza@gmail.com>
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl> * [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
* [pt] Helena Grosso <lenagrosso@gmail.com>, * [pt] Helena Grosso <lenagrosso@gmail.com>,
Joaquim Rocha <jrocha@igalia.com> Joaquim Rocha <jrocha@igalia.com>
* [ru] Pavel Rudensky <prudensky@gmail.com> * [ru] Pavel Rudensky <prudensky@gmail.com>

38
HACKING
View file

@ -351,6 +351,44 @@ command. For example:
mvn -Pprod,postgresql clean install mvn -Pprod,postgresql clean install
Compilation options
-------------------
In LibrePlan there are two custom Maven properties, which allow you to configure
some small bits in the project.
* *default.passwordsControl* - Warning about default passwords (``true`` by
default)
If this option is enabled, a warning is show in LibrePlan footer to
application administrators in order to change the default password (which
matches with user login) for the users created by default: admin, user,
wsreader and wswriter.
* *default.exampleUsersDisabled* - Disable default users (``true`` by default)
If true, example default users such as user, wsreader and wswriter are
disabled. This is a good option for production environments.
This option is set to ``false`` if you are using the development profile (the
default one).
How to set compilation options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Maven properties have a default value, but you can change it using the parameter
``-D`` for Maven command to set the value of each option you want to modify. For
example:
* Set *default.passwordsControl* to ``false``::
mvn -Ddefault.passwordsControl=false clean install
* Set *default.passwordsControl* and *default.exampleUsersDisabled* to false::
mvn -Ddefault.passwordsControl=false -Ddefault.exampleUsersDisabled=false clean install
Tests Tests
----- -----

View file

@ -46,7 +46,7 @@ Instructions:
* Download the package:: * Download the package::
$ wget http://downloads.sourceforge.net/project/libreplan/files/LibrePlan/libreplan_1.2.0-1_amd64.deb $ wget http://downloads.sourceforge.net/project/libreplan/LibrePlan/libreplan_1.2.0-1_amd64.deb
* Install package:: * Install package::

173
NEWS
View file

@ -1,6 +1,179 @@
NEWS NEWS
==== ====
Version 1.2.3 (19 Apr 2012)
---------------------------
Summary
~~~~~~~
A new minor version of the LibrePlan 1.2.* version family. The main changes
included in this new release are:
* Money based cost monitoring system: This is a new feature that allows users to
monitor the project cost based on the money spent comparing it to the budget.
Users can configure the budget for each task and, after this, LibrePlan
calculates the cost in money already spent using the worked time tracked, the
type of worked hours (standard, overtime,...) and the cost of each resource
hour according to the value defined by the cost category the worker belongs.
* Polish language: LibrePlan is now translated into Polish thanks to the work
done by Krzysztof Kamecki.
* Other minor enhancements and bugfixing:
* Fixed database synchronization issues which appeared on changing planning
points in the WBS. The problems arose when planning points were moved from
children to their parents or vice versa.
* Default users (user, wsreader and wswriter) are disabled by default.
* Fixed resource usage grouped by criteria load analysis that was being bad
calculated inside a project.
* Task duration was not being refreshed properly when doing an allocation and
you needed to apply the allocation twice to see it right.
* START_IN_FIXED_DATE constraint caused that the project duration was bad
calculated in company view.
Notes
~~~~~
.. WARNING::
Remove web browser cache to avoid any problem with changes in JavaScript
resources.
If you are upgrading from any 1.1.x version without using the Debian package,
you will need to manually execute on your database the SQL sentences from files:
``scripts/database/upgrade_1.2.0.sql``, ``scripts/database/upgrade_1.2.1.sql``,
``scripts/database/upgrade_1.2.2.sql`` and ``scripts/database/upgrade_1.2.3.sql``.
If you are upgrading from 1.2.0 version without using the Debian package,
you will need to manually execute on your database the SQL sentences from files:
``scripts/database/upgrade_1.2.1.sql``, ``scripts/database/upgrade_1.2.2.sql``
and ``scripts/database/upgrade_1.2.3.sql``.
If you are upgrading from 1.2.1 version without using the Debian package,
you will need to manually execute on your database the SQL sentences from files:
``scripts/database/upgrade_1.2.2.sql`` and ``scripts/database/upgrade_1.2.3.sql``.
If you are upgrading from 1.2.2 version without using the Debian package,
you will need to manually execute on your database the SQL sentences from file:
``scripts/database/upgrade_1.2.3.sql``.
Contributors
~~~~~~~~~~~~
Thanks to all the contributors to this new version:
* Jacobo Aragunde Pérez
* Óscar González Fernández
* Susana Montes Pedreira
* Francisco Javier Morán Rúa
* Manuel Rego Casasnovas
* Lorenzo Tilve Álvaro
Translators
~~~~~~~~~~~
Thanks to all the translators in this new version:
* [es] Manuel Rego Casasnovas
* [fr] Philippe Poumaroux
* [gl] Manuel Rego Casasnovas
* [it] Giuseppe Zizza
* [nl] Jeroen Baten
* [pl] Krzysztof Kamecki
Changes
~~~~~~~
* Bug #1417: Add UI validation to prevent empty codes
* doc: Update AUTHORS file info about new Polish translator
* i18n: Add Polish language to enum and modify pom.xml to use English userguide
* i18n: Add Polish translation
* Bug #1358: Removed unnecessary tooltip string
* Bug #1358: Added CSS max dimensions restriction to configured company logo
* Fixed vertical positioning of resources string next to containers
* Bug #1407: Run TaskComponent.updateProperties() after running the scheduling algorithm.
* Remove unused fields in Order Costs Per Resource Report
* Bug #1412: Fix problem converting to string clockStart and clockFinish
* Bug #1409: Rename RelatedWithAnyOf to RelatedWith
* Bug #1409: Fix problem replacing allocations for the ones related to the criterion
* Revert "Bug #1320: When asking a container for start constraints, return the leftmost"
* Bug #1411: Missing Spanish translation for "Project cost by resource"
* Fix Sahi test due to change in string
* i18n: Update Dutch translation
* i18n: Update French translation
* doc: Update HACKING file about the compilation options
* Add new compilation option to disable default users (user, wsreader and wswriter)
* Bug #1395: Fix issue setting width of date boxes to 100px
* i18n: Update Italian translation
* i18n: Update Spanish and Galician translations
* i18n: Update keys.pot files
* Bug #1402: Invalidate the TaskComponents instead of the whole GanttPanel
* Bug #1349: Fix translation issue in choosing template pop-up
* Bug #1349: Mark to translate exception day type
* Bug #1349: Fix translation in calendar type
* Bug #1298: Mark to translate roles in user and profile edition
* Remove CutyCaptTimeout
* Bug #1406: Add UI validation for name field too
* Bug #1406: Add validation in the UI and also a try catch for possible ValidationExceptions
* doc: Fix typo in INSTALL file
* doc: Fix broke link in INSTALL file
* doc: Update information about how to install in Fedora and openSUSE
* doc: Add info about JAVA_OPTS configuration in INSTALL file
* [Bug #1234] Fix the deletion of fields in progress reporting in subcontractor module.
* Fix problems in Liquibase changes in MySQL
* Fix compilation error in previous merge
* Merge branch 'libreplan-1.2' into money-cost-monitoring-system
* doc: Add info about add-apt-repository command in INSTALL file
* Bug #1387: Code refactor of the previous patches for this bug.
* Bug #1387: Fix bug when it happens in the opposite way.
* Show budget information in a read-only field inside task properties tab
* Bug #1387: Fix bug
* Change color of money cost bar to a darker one to avoid accessibility issues
* Bug #1403: Only regenerate codes if isCodeAutogenerated() is true
* Add a map in MoneyCostCalculator to cache calculated values
* Disable Money Cost Bar in company view to avoid performance issues
* Bug #1289: Added subcontractor name to tasks when showing resources is enabled
* Remove unneeded throws in MoneyCostCalculatorTest
* Add unit tests to check MoneyCostCalculator with a different type of hours
* Remove commented lines in MoneyCostCalculatorTest
* Update Copyright info in user documentation
* Improve sentence in "Imputed hours" tab editing a task
* Add information about budget in "Imputed hours" tab
* Add unit tests to check MoneyCostCalculator with a tree of tasks
* Remove unused parameters in CutyPrint.createCSSFile
* Add option to print money cost bar
* Add a new test case to check MoneyCostCalculator when there is not relationship via cost category
* Prevent possible rounding problems dividing BigDecimals
* Prevent NPE if there is not relationship between resource and type of hours via cost category
* Reload budget field in "General data" of templates
* Add field in "General data" tab to show the project budget
* Print Money Cost Bar proportinal to task size
* Prevent NPE calculating money cost for a TaskElement
* Remove method getMoneyCostBarPercentage from ITaskFundamentalProperties
* Improve tooltip message using budget, consumed money and percentage
* Using the new MoneyCostCalculator to print the new Money Cost bar
* Implement money cost calculation in a new class called MoneyCostCalculator
* Fix Money Cost Bar position in containers
* Add money cost percentage in the tooltip
* Change CSS for the money cost bar and reported hours bar
* Change icon for the new money cost bar
* Add new money cost bar at this moment using value, icon and color of reported hours
* doc: Update Fedora and openSUSE documentation for upgrade LibrePlan
* Merge branch 'libreplan-1.2' into money-cost-monitoring-system
* Fix typo in "Interporlation" (extra r)
* doc: Fix date format in on version at NEWS file
* Add no negative constraint in budget fields in edition forms
* Add budget field in order element template edition form
* Use budget field when creating a template from a task or vice versa
* Add budget field in order element details form
* Add budget cell in WBS
* Add new field budget to OrderLineTemplate
* Add basic tests for new attribute budget
* Add new field budget to OrderLine
Version 1.2.2 (15 Mar 2012) Version 1.2.2 (15 Mar 2012)
--------------------------- ---------------------------

View file

@ -1 +1 @@
1.2.2 1.2.3

6
debian/changelog vendored
View file

@ -1,3 +1,9 @@
libreplan (1.2.3-1) squeeze; urgency=low
* Released LibrePlan 1.2.3
-- Jacobo Aragunde Pérez <jaragunde@igalia.com> Wed, 18 Apr 2012 17:49:00 +0100
libreplan (1.2.2-1) squeeze; urgency=low libreplan (1.2.2-1) squeeze; urgency=low
* Released LibrePlan 1.2.2 * Released LibrePlan 1.2.2

View file

@ -6,3 +6,4 @@ debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.1.0
debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.0 debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.0
debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.1 debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.1
debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.2 debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.2
debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.3

3
debian/rules vendored
View file

@ -90,6 +90,9 @@ install:
# Copy SQL upgrade script for version 1.2.2 # Copy SQL upgrade script for version 1.2.2
$(call CMD,cp $(CURDIR)/scripts/database/upgrade_1.2.2.sql \ $(call CMD,cp $(CURDIR)/scripts/database/upgrade_1.2.2.sql \
$(CURDIR)/debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.2) $(CURDIR)/debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.2)
# Copy SQL upgrade script for version 1.2.3
$(call CMD,cp $(CURDIR)/scripts/database/upgrade_1.2.3.sql \
$(CURDIR)/debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.2.3)
# Install Policy file # Install Policy file
$(call CMD,mkdir -p $(CURDIR)/debian/tmp/etc/tomcat6/policy.d) $(call CMD,mkdir -p $(CURDIR)/debian/tmp/etc/tomcat6/policy.d)
$(call CMD,cp $(CURDIR)/debian/51libreplan.policy \ $(call CMD,cp $(CURDIR)/debian/51libreplan.policy \

View file

@ -29,7 +29,7 @@ a) Clone Git repository (recommended)::
b) Download last version source code:: b) Download last version source code::
$ wget http://downloads.sourceforge.net/project/libreplan/files/LibrePlan/libreplan_1.2.0.tar.gz $ wget http://downloads.sourceforge.net/project/libreplan/LibrePlan/libreplan_1.2.0.tar.gz
$ tar -xzvf libreplan_1.2.0.tar.gz $ tar -xzvf libreplan_1.2.0.tar.gz
You should review ``HACKING`` file to check that you have installed all the You should review ``HACKING`` file to check that you have installed all the

View file

@ -77,6 +77,7 @@ Translators
Diego Pino García <dpino@igalia.com> Diego Pino García <dpino@igalia.com>
* [it] Giuseppe Zizza <gzizza@gmail.com> * [it] Giuseppe Zizza <gzizza@gmail.com>
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl> * [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
* [pt] Helena Grosso <lenagrosso@gmail.com>, * [pt] Helena Grosso <lenagrosso@gmail.com>,
Joaquim Rocha <jrocha@igalia.com> Joaquim Rocha <jrocha@igalia.com>
* [ru] Pavel Rudensky <prudensky@gmail.com> * [ru] Pavel Rudensky <prudensky@gmail.com>

View file

@ -77,6 +77,7 @@ Traductores
Diego Pino García <dpino@igalia.com> Diego Pino García <dpino@igalia.com>
* [it] Giuseppe Zizza <gzizza@gmail.com> * [it] Giuseppe Zizza <gzizza@gmail.com>
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl> * [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
* [pt] Helena Grosso <lenagrosso@gmail.com>, * [pt] Helena Grosso <lenagrosso@gmail.com>,
Joaquim Rocha <jrocha@igalia.com> Joaquim Rocha <jrocha@igalia.com>
* [ru] Pavel Rudensky <prudensky@gmail.com> * [ru] Pavel Rudensky <prudensky@gmail.com>

View file

@ -77,6 +77,7 @@ Traductores
Diego Pino García <dpino@igalia.com> Diego Pino García <dpino@igalia.com>
* [it] Giuseppe Zizza <gzizza@gmail.com> * [it] Giuseppe Zizza <gzizza@gmail.com>
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl> * [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
* [pt] Helena Grosso <lenagrosso@gmail.com>, * [pt] Helena Grosso <lenagrosso@gmail.com>,
Joaquim Rocha <jrocha@igalia.com> Joaquim Rocha <jrocha@igalia.com>
* [ru] Pavel Rudensky <prudensky@gmail.com> * [ru] Pavel Rudensky <prudensky@gmail.com>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.libreplan</groupId> <groupId>org.libreplan</groupId>
<artifactId>libreplan</artifactId> <artifactId>libreplan</artifactId>
<version>1.2.2</version> <version>1.2.3</version>
</parent> </parent>
<artifactId>ganttzk</artifactId> <artifactId>ganttzk</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>

View file

@ -388,18 +388,19 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
} }
}); });
} catch (ParseException e) { } catch (ParseException e) {
getStartDateTextBox().setValue( // Do nothing as textbox is rested in the next sentence
dateFormat.format(task.getBeginDate()
.toDayRoundedDate()));
} }
getStartDateTextBox().setValue(
dateFormat.format(task.getBeginDate().toDayRoundedDate()));
} else if (updatedComponent == getEndDateTextBox()) { } else if (updatedComponent == getEndDateTextBox()) {
try { try {
Date newEnd = dateFormat.parse(getEndDateTextBox().getValue()); Date newEnd = dateFormat.parse(getEndDateTextBox().getValue());
task.resizeTo(LocalDate.fromDateFields(newEnd)); task.resizeTo(LocalDate.fromDateFields(newEnd));
} catch (ParseException e) { } catch (ParseException e) {
getEndDateTextBox().setValue( // Do nothing as textbox is rested in the next sentence
asString(task.getEndDate().toDayRoundedDate()));
} }
getEndDateTextBox().setValue(
asString(task.getEndDate().toDayRoundedDate()));
} }
planner.updateTooltips(); planner.updateTooltips();
} }

View file

@ -41,6 +41,7 @@ import org.zkoss.ganttz.data.GanttDiagramGraph.IDependenciesEnforcerHookFactory;
import org.zkoss.ganttz.data.GanttDiagramGraph.INotificationAfterDependenciesEnforcement; import org.zkoss.ganttz.data.GanttDiagramGraph.INotificationAfterDependenciesEnforcement;
import org.zkoss.ganttz.data.constraint.Constraint; import org.zkoss.ganttz.data.constraint.Constraint;
import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener; import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener;
import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
import org.zkoss.ganttz.util.ConstraintViolationNotificator; import org.zkoss.ganttz.util.ConstraintViolationNotificator;
import org.zkoss.ganttz.util.WeakReferencedListeners.Mode; import org.zkoss.ganttz.util.WeakReferencedListeners.Mode;
@ -471,6 +472,16 @@ public abstract class Task implements ITaskFundamentalProperties {
} }
} }
public static void reloadResourcesText(IContextWithPlannerTask<?> context) {
Task task = context.getTask();
task.reloadResourcesText();
List<? extends TaskContainer> parents = context.getMapper().getParents(
task);
for (TaskContainer each : parents) {
each.reloadResourcesText();
}
}
public boolean isSubcontracted() { public boolean isSubcontracted() {
return fundamentalProperties.isSubcontracted(); return fundamentalProperties.isSubcontracted();
} }

View file

@ -86,8 +86,8 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
private Listbox listZoomLevels; private Listbox listZoomLevels;
private final String FILTER_RESOURCES = _("by resources"); private final String FILTER_RESOURCES = _("Resources");
private final String FILTER_CRITERIA = _("by criteria"); private final String FILTER_CRITERIA = _("Generic allocation criteria");
private String feedBackMessage; private String feedBackMessage;
private Boolean filterbyResources; private Boolean filterbyResources;

View file

@ -10,10 +10,10 @@
# Manuel Rego Casasnovas <rego@igalia.com>, 2010, 2011, 2012. # Manuel Rego Casasnovas <rego@igalia.com>, 2010, 2011, 2012.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.2.1\n" "Project-Id-Version: libreplan-1.2.3\n"
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n" "Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
"POT-Creation-Date: 2012-01-13 16:49+0100\n" "POT-Creation-Date: 2012-04-11 08:32+0200\n"
"PO-Revision-Date: 2012-01-13 16:00+0000\n" "PO-Revision-Date: 2012-04-11 08:35+0000\n"
"Last-Translator: Manuel Rego Casasnovas <rego@igalia.com>\n" "Last-Translator: Manuel Rego Casasnovas <rego@igalia.com>\n"
"Language-Team: Español\n" "Language-Team: Español\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -22,12 +22,12 @@ msgstr ""
"Language: es\n" "Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:215 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:234 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
msgid "Erase" msgid "Erase"
msgstr "Borrar" msgstr "Borrar"
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:300 #: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
msgid "Add Dependency" msgid "Add Dependency"
msgstr "Añadir dependencia" msgstr "Añadir dependencia"
@ -35,11 +35,15 @@ msgstr "Añadir dependencia"
msgid "Worker" msgid "Worker"
msgstr "Trabajador" msgstr "Trabajador"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
msgid "Show money cost bar"
msgstr "Mostrar barra de coste monetario"
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29 #: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
msgid "Start" msgid "Start"
msgstr "Inicio" msgstr "Inicio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:635 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
msgid "Show reported hours" msgid "Show reported hours"
msgstr "Mostrar horas reportadas" msgstr "Mostrar horas reportadas"
@ -64,7 +68,7 @@ msgstr "Recursos limitantes"
msgid "The specified dependency is not allowed" msgid "The specified dependency is not allowed"
msgstr "La dependencia especificada no está permitida" msgstr "La dependencia especificada no está permitida"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:254 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:255
msgid "Set End-End" msgid "Set End-End"
msgstr "Definir Fin-Fin" msgstr "Definir Fin-Fin"
@ -88,6 +92,10 @@ msgstr "esfuerzo disponible: {0}, esfuerzo asignado: {1}"
msgid "Criterion" msgid "Criterion"
msgstr "Criterio" msgstr "Criterio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
msgid "Hide money cost bar"
msgstr "Ocultar barra de coste monetario"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
msgid "Print" msgid "Print"
msgstr "Imprimir" msgstr "Imprimir"
@ -116,6 +124,10 @@ msgstr "Fin"
msgid "changing zoom" msgid "changing zoom"
msgstr "cambiando zoom" msgstr "cambiando zoom"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
msgid "Show/Hide money cost bar"
msgstr "Mostrar/Ocultar barra de coste monetario"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
msgid "Quarter" msgid "Quarter"
msgstr "Trimestre" msgstr "Trimestre"
@ -141,7 +153,7 @@ msgstr "Nombre"
msgid "Name filter" msgid "Name filter"
msgstr "Filtro por nombres" msgstr "Filtro por nombres"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:615 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
msgid "Show progress" msgid "Show progress"
msgstr "Mostrar progreso" msgstr "Mostrar progreso"
@ -153,14 +165,14 @@ msgstr "Expandir/Plegar todo"
msgid "Show/Hide critical path" msgid "Show/Hide critical path"
msgstr "Mostrar/Ocultar camino crítico" msgstr "Mostrar/Ocultar camino crítico"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Año"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150 #: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
msgid "showing criteria" msgid "showing criteria"
msgstr "mostrando criterios" msgstr "mostrando criterios"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Año"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
msgid "Month" msgid "Month"
msgstr "Mes" msgstr "Mes"
@ -169,15 +181,15 @@ msgstr "Mes"
msgid "Show/Hide resources" msgid "Show/Hide resources"
msgstr "Mostrar/Ocultar recursos" msgstr "Mostrar/Ocultar recursos"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:246 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:247
msgid "Set End-Start" msgid "Set End-Start"
msgstr "Definir Fin-Inicio" msgstr "Definir Fin-Inicio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:297 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
msgid "decreasing zoom" msgid "decreasing zoom"
msgstr "reduciendo zoom" msgstr "reduciendo zoom"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:596 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
msgid "Hide critical path" msgid "Hide critical path"
msgstr "Ocultar camino crítico" msgstr "Ocultar camino crítico"
@ -185,7 +197,7 @@ msgstr "Ocultar camino crítico"
msgid "Day" msgid "Day"
msgstr "Día" msgstr "Día"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:642 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
msgid "Hide reported hours" msgid "Hide reported hours"
msgstr "Ocultar horas reportadas" msgstr "Ocultar horas reportadas"
@ -206,11 +218,11 @@ msgid "Hour"
msgstr "Hora" msgstr "Hora"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90 #: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:114 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
msgid "Graphics" msgid "Graphics"
msgstr "Gráficas" msgstr "Gráficas"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:250 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:251
msgid "Set Start-Start" msgid "Set Start-Start"
msgstr "Definir Inicio-Inicio" msgstr "Definir Inicio-Inicio"
@ -218,7 +230,7 @@ msgstr "Definir Inicio-Inicio"
msgid "See resource allocation" msgid "See resource allocation"
msgstr "Ver asignación de recursos" msgstr "Ver asignación de recursos"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:280 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
msgid "increasing zoom" msgid "increasing zoom"
msgstr "aumentando zoom" msgstr "aumentando zoom"
@ -234,10 +246,10 @@ msgstr "Todos"
msgid "Refresh" msgid "Refresh"
msgstr "Actualizar" msgstr "Actualizar"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:591 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
msgid "Show critical path" msgid "Show critical path"
msgstr "Mostrar camino crítico" msgstr "Mostrar camino crítico"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
msgid "Hide progress" msgid "Hide progress"
msgstr "Ocultar progreso" msgstr "Ocultar progreso"

View file

@ -8,10 +8,10 @@
# Philippe Poumaroux <philippe.poumaroux@free.fr>, 2012. # Philippe Poumaroux <philippe.poumaroux@free.fr>, 2012.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.2.1\n" "Project-Id-Version: libreplan-1.2.3\n"
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n" "Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
"POT-Creation-Date: 2012-01-13 16:49+0100\n" "POT-Creation-Date: 2012-04-11 08:32+0200\n"
"PO-Revision-Date: 2012-01-23 12:36+0000\n" "PO-Revision-Date: 2012-04-11 12:30+0000\n"
"Last-Translator: Philippe Poumaroux <philippe.poumaroux@free.fr>\n" "Last-Translator: Philippe Poumaroux <philippe.poumaroux@free.fr>\n"
"Language-Team: Français\n" "Language-Team: Français\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -20,12 +20,12 @@ msgstr ""
"Language: fr\n" "Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:215 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:234 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
msgid "Erase" msgid "Erase"
msgstr "Supprimer" msgstr "Supprimer"
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:300 #: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
msgid "Add Dependency" msgid "Add Dependency"
msgstr "Ajouter une dépendance" msgstr "Ajouter une dépendance"
@ -33,11 +33,15 @@ msgstr "Ajouter une dépendance"
msgid "Worker" msgid "Worker"
msgstr "Travailleur" msgstr "Travailleur"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
msgid "Show money cost bar"
msgstr "Afficher la barre de coût monétaire"
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29 #: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
msgid "Start" msgid "Start"
msgstr "Début" msgstr "Début"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:635 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
msgid "Show reported hours" msgid "Show reported hours"
msgstr "Afficher les heures comptabilisées" msgstr "Afficher les heures comptabilisées"
@ -62,7 +66,7 @@ msgstr "Ressources bloquantes"
msgid "The specified dependency is not allowed" msgid "The specified dependency is not allowed"
msgstr "La dépendance indiquée n'est pas disponible" msgstr "La dépendance indiquée n'est pas disponible"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:254 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:255
msgid "Set End-End" msgid "Set End-End"
msgstr "Faire correspondre les achèvements" msgstr "Faire correspondre les achèvements"
@ -86,6 +90,10 @@ msgstr "investissement disponible: {0}, investissement affecté: {1}"
msgid "Criterion" msgid "Criterion"
msgstr "Critère" msgstr "Critère"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
msgid "Hide money cost bar"
msgstr "Masquer la barre de coût monétaire"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
msgid "Print" msgid "Print"
msgstr "Imprimer" msgstr "Imprimer"
@ -114,6 +122,10 @@ msgstr "Fin"
msgid "changing zoom" msgid "changing zoom"
msgstr "Changer le zoom" msgstr "Changer le zoom"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
msgid "Show/Hide money cost bar"
msgstr "Afficher/Masquer la barre de coût monétaire"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
msgid "Quarter" msgid "Quarter"
msgstr "Trimestre" msgstr "Trimestre"
@ -139,7 +151,7 @@ msgstr "Nom"
msgid "Name filter" msgid "Name filter"
msgstr "Filtre par nom" msgstr "Filtre par nom"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:615 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
msgid "Show progress" msgid "Show progress"
msgstr "Monter l'avancement" msgstr "Monter l'avancement"
@ -151,14 +163,14 @@ msgstr "Déplier/Replier tout"
msgid "Show/Hide critical path" msgid "Show/Hide critical path"
msgstr "Montrer/Cacher le chemin critique" msgstr "Montrer/Cacher le chemin critique"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Année"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150 #: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
msgid "showing criteria" msgid "showing criteria"
msgstr "Montrer les critères" msgstr "Montrer les critères"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Année"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
msgid "Month" msgid "Month"
msgstr "Mois" msgstr "Mois"
@ -167,15 +179,15 @@ msgstr "Mois"
msgid "Show/Hide resources" msgid "Show/Hide resources"
msgstr "Montrer/Cacher les ressources" msgstr "Montrer/Cacher les ressources"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:246 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:247
msgid "Set End-Start" msgid "Set End-Start"
msgstr "Ajuster le début sur la fin" msgstr "Ajuster le début sur la fin"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:297 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
msgid "decreasing zoom" msgid "decreasing zoom"
msgstr "réduire le zoom" msgstr "réduire le zoom"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:596 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
msgid "Hide critical path" msgid "Hide critical path"
msgstr "Cacher le chemin critique" msgstr "Cacher le chemin critique"
@ -183,7 +195,7 @@ msgstr "Cacher le chemin critique"
msgid "Day" msgid "Day"
msgstr "Jour" msgstr "Jour"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:642 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
msgid "Hide reported hours" msgid "Hide reported hours"
msgstr "Cacher les heures comptabilisées" msgstr "Cacher les heures comptabilisées"
@ -204,11 +216,11 @@ msgid "Hour"
msgstr "Heure" msgstr "Heure"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90 #: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:114 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
msgid "Graphics" msgid "Graphics"
msgstr "Graphiques" msgstr "Graphiques"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:250 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:251
msgid "Set Start-Start" msgid "Set Start-Start"
msgstr "Ajuster sur le début" msgstr "Ajuster sur le début"
@ -216,7 +228,7 @@ msgstr "Ajuster sur le début"
msgid "See resource allocation" msgid "See resource allocation"
msgstr "Voir l'allocation des ressources" msgstr "Voir l'allocation des ressources"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:280 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
msgid "increasing zoom" msgid "increasing zoom"
msgstr "augmenter le zoom" msgstr "augmenter le zoom"
@ -232,10 +244,10 @@ msgstr "Tout"
msgid "Refresh" msgid "Refresh"
msgstr "Rafraîchir" msgstr "Rafraîchir"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:591 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
msgid "Show critical path" msgid "Show critical path"
msgstr "Montrer le chemin critique" msgstr "Montrer le chemin critique"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
msgid "Hide progress" msgid "Hide progress"
msgstr "Cacher l'avancement" msgstr "Cacher l'avancement"

View file

@ -10,11 +10,11 @@
# Manuel Rego Casasnovas <rego@igalia.com>, 2010, 2011, 2012. # Manuel Rego Casasnovas <rego@igalia.com>, 2010, 2011, 2012.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.2.1\n" "Project-Id-Version: libreplan-1.2.3\n"
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n" "Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
"POT-Creation-Date: 2012-01-13 16:49+0100\n" "POT-Creation-Date: 2012-04-11 08:32+0200\n"
"PO-Revision-Date: 2012-01-13 16:01+0000\n" "PO-Revision-Date: 2012-04-11 08:34+0000\n"
"Last-Translator: Manuel Rego Casasnovas<rego@igalia.com>\n" "Last-Translator: Manuel Rego Casasnovas <rego@igalia.com>\n"
"Language-Team: Galego\n" "Language-Team: Galego\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -22,12 +22,12 @@ msgstr ""
"Language: gl\n" "Language: gl\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:215 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:234 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
msgid "Erase" msgid "Erase"
msgstr "Borrar" msgstr "Borrar"
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:300 #: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
msgid "Add Dependency" msgid "Add Dependency"
msgstr "Engadir dependencia" msgstr "Engadir dependencia"
@ -35,11 +35,15 @@ msgstr "Engadir dependencia"
msgid "Worker" msgid "Worker"
msgstr "Traballador" msgstr "Traballador"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
msgid "Show money cost bar"
msgstr "Mostrar barra de coste monetario"
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29 #: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
msgid "Start" msgid "Start"
msgstr "Inicio" msgstr "Inicio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:635 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
msgid "Show reported hours" msgid "Show reported hours"
msgstr "Mostrar horas reportadas" msgstr "Mostrar horas reportadas"
@ -64,7 +68,7 @@ msgstr "Recursos limitantes"
msgid "The specified dependency is not allowed" msgid "The specified dependency is not allowed"
msgstr "A dependencia especificada non está permitida" msgstr "A dependencia especificada non está permitida"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:254 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:255
msgid "Set End-End" msgid "Set End-End"
msgstr "Definir Fin-Fin" msgstr "Definir Fin-Fin"
@ -88,6 +92,10 @@ msgstr "esforzo dispoñible: {0}, esforzo asignado: {1}"
msgid "Criterion" msgid "Criterion"
msgstr "Criterio" msgstr "Criterio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
msgid "Hide money cost bar"
msgstr "Ocultar barra de coste monetario"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
msgid "Print" msgid "Print"
msgstr "Imprimir" msgstr "Imprimir"
@ -116,6 +124,10 @@ msgstr "Fin"
msgid "changing zoom" msgid "changing zoom"
msgstr "cambiando zoom" msgstr "cambiando zoom"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
msgid "Show/Hide money cost bar"
msgstr "Mostrar/Ocultar barra de coste monetario"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
msgid "Quarter" msgid "Quarter"
msgstr "Trimestre" msgstr "Trimestre"
@ -141,7 +153,7 @@ msgstr "Nome"
msgid "Name filter" msgid "Name filter"
msgstr "Filtro por nomes" msgstr "Filtro por nomes"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:615 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
msgid "Show progress" msgid "Show progress"
msgstr "Mostrar progreso" msgstr "Mostrar progreso"
@ -153,14 +165,14 @@ msgstr "Expandir/Pregar todo"
msgid "Show/Hide critical path" msgid "Show/Hide critical path"
msgstr "Mostrar/Ocultar camiño crítico" msgstr "Mostrar/Ocultar camiño crítico"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Ano"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150 #: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
msgid "showing criteria" msgid "showing criteria"
msgstr "mostrando criterios" msgstr "mostrando criterios"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Ano"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
msgid "Month" msgid "Month"
msgstr "Mes" msgstr "Mes"
@ -169,15 +181,15 @@ msgstr "Mes"
msgid "Show/Hide resources" msgid "Show/Hide resources"
msgstr "Mostrar/Ocultar recursos" msgstr "Mostrar/Ocultar recursos"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:246 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:247
msgid "Set End-Start" msgid "Set End-Start"
msgstr "Definir Fin-Inicio" msgstr "Definir Fin-Inicio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:297 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
msgid "decreasing zoom" msgid "decreasing zoom"
msgstr "reducindo zoom" msgstr "reducindo zoom"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:596 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
msgid "Hide critical path" msgid "Hide critical path"
msgstr "Ocultar camiño crítico" msgstr "Ocultar camiño crítico"
@ -185,7 +197,7 @@ msgstr "Ocultar camiño crítico"
msgid "Day" msgid "Day"
msgstr "Día" msgstr "Día"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:642 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
msgid "Hide reported hours" msgid "Hide reported hours"
msgstr "Ocultar horas reportadas" msgstr "Ocultar horas reportadas"
@ -206,11 +218,11 @@ msgid "Hour"
msgstr "Hora" msgstr "Hora"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90 #: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:114 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
msgid "Graphics" msgid "Graphics"
msgstr "Gráficas" msgstr "Gráficas"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:250 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:251
msgid "Set Start-Start" msgid "Set Start-Start"
msgstr "Definir Inicio-Inicio" msgstr "Definir Inicio-Inicio"
@ -218,7 +230,7 @@ msgstr "Definir Inicio-Inicio"
msgid "See resource allocation" msgid "See resource allocation"
msgstr "Ver asignación de recursoss" msgstr "Ver asignación de recursoss"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:280 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
msgid "increasing zoom" msgid "increasing zoom"
msgstr "aumentando zoom" msgstr "aumentando zoom"
@ -234,10 +246,10 @@ msgstr "Todos"
msgid "Refresh" msgid "Refresh"
msgstr "Actualizar" msgstr "Actualizar"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:591 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
msgid "Show critical path" msgid "Show critical path"
msgstr "Mostrar camiño crítico" msgstr "Mostrar camiño crítico"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
msgid "Hide progress" msgid "Hide progress"
msgstr "Ocultar progreso" msgstr "Ocultar progreso"

View file

@ -8,10 +8,10 @@
# Giuseppe Zizza <gzizza@gmail.com>, 2012. # Giuseppe Zizza <gzizza@gmail.com>, 2012.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.2.1\n" "Project-Id-Version: libreplan-1.2.3\n"
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n" "Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
"POT-Creation-Date: 2012-01-13 16:49+0100\n" "POT-Creation-Date: 2012-04-11 08:32+0200\n"
"PO-Revision-Date: 2012-01-13 16:09+0000\n" "PO-Revision-Date: 2012-04-11 08:05+0000\n"
"Last-Translator: Giuseppe Zizza <gzizza@gmail.com>\n" "Last-Translator: Giuseppe Zizza <gzizza@gmail.com>\n"
"Language-Team: Italiano\n" "Language-Team: Italiano\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -20,12 +20,12 @@ msgstr ""
"Language: it\n" "Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:215 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:234 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
msgid "Erase" msgid "Erase"
msgstr "Cancella" msgstr "Cancella"
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:300 #: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
msgid "Add Dependency" msgid "Add Dependency"
msgstr "Aggiungi dipendenza" msgstr "Aggiungi dipendenza"
@ -33,11 +33,15 @@ msgstr "Aggiungi dipendenza"
msgid "Worker" msgid "Worker"
msgstr "Lavoratore" msgstr "Lavoratore"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
msgid "Show money cost bar"
msgstr "Mostra la barra dei costi"
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29 #: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
msgid "Start" msgid "Start"
msgstr "Inizio" msgstr "Inizio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:635 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
msgid "Show reported hours" msgid "Show reported hours"
msgstr "Mostra le ore riportate" msgstr "Mostra le ore riportate"
@ -62,7 +66,7 @@ msgstr "Risorse limitanti"
msgid "The specified dependency is not allowed" msgid "The specified dependency is not allowed"
msgstr "La dipendenza specifica non è permessa" msgstr "La dipendenza specifica non è permessa"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:254 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:255
msgid "Set End-End" msgid "Set End-End"
msgstr "Imposta Fine-Fine" msgstr "Imposta Fine-Fine"
@ -86,6 +90,10 @@ msgstr "Forza disponbile: {0}, forza assegnata: {1}"
msgid "Criterion" msgid "Criterion"
msgstr "Criterio" msgstr "Criterio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
msgid "Hide money cost bar"
msgstr "Nascondi la barra dei costi"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
msgid "Print" msgid "Print"
msgstr "Stampa" msgstr "Stampa"
@ -114,6 +122,10 @@ msgstr "Fine"
msgid "changing zoom" msgid "changing zoom"
msgstr "Cambio vista" msgstr "Cambio vista"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
msgid "Show/Hide money cost bar"
msgstr "Mostra/Nascondi la barra dei costi"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
msgid "Quarter" msgid "Quarter"
msgstr "Quarto" msgstr "Quarto"
@ -139,7 +151,7 @@ msgstr "Nome"
msgid "Name filter" msgid "Name filter"
msgstr "Nome filtro" msgstr "Nome filtro"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:615 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
msgid "Show progress" msgid "Show progress"
msgstr "Mostra progresso" msgstr "Mostra progresso"
@ -151,14 +163,14 @@ msgstr "Espandi/Riduci tutti"
msgid "Show/Hide critical path" msgid "Show/Hide critical path"
msgstr "Mostra/Nascondi percorso critico" msgstr "Mostra/Nascondi percorso critico"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Anno"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150 #: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
msgid "showing criteria" msgid "showing criteria"
msgstr "Mostro i criteri" msgstr "Mostro i criteri"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Anno"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
msgid "Month" msgid "Month"
msgstr "Mese" msgstr "Mese"
@ -167,15 +179,15 @@ msgstr "Mese"
msgid "Show/Hide resources" msgid "Show/Hide resources"
msgstr "Mostra/Nascondi risorse" msgstr "Mostra/Nascondi risorse"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:246 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:247
msgid "Set End-Start" msgid "Set End-Start"
msgstr "Imposta Fine-Inizio" msgstr "Imposta Fine-Inizio"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:297 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
msgid "decreasing zoom" msgid "decreasing zoom"
msgstr "Riduco ingrandimento" msgstr "Riduco ingrandimento"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:596 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
msgid "Hide critical path" msgid "Hide critical path"
msgstr "Nascondi percorso critico" msgstr "Nascondi percorso critico"
@ -183,7 +195,7 @@ msgstr "Nascondi percorso critico"
msgid "Day" msgid "Day"
msgstr "Giorno" msgstr "Giorno"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:642 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
msgid "Hide reported hours" msgid "Hide reported hours"
msgstr "Nascondi ore riportate" msgstr "Nascondi ore riportate"
@ -204,11 +216,11 @@ msgid "Hour"
msgstr "Ora" msgstr "Ora"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90 #: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:114 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
msgid "Graphics" msgid "Graphics"
msgstr "Grafici" msgstr "Grafici"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:250 #: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:251
msgid "Set Start-Start" msgid "Set Start-Start"
msgstr "Imposta Inizio-Inizio" msgstr "Imposta Inizio-Inizio"
@ -216,7 +228,7 @@ msgstr "Imposta Inizio-Inizio"
msgid "See resource allocation" msgid "See resource allocation"
msgstr "Mostra allocazione risorse" msgstr "Mostra allocazione risorse"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:280 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
msgid "increasing zoom" msgid "increasing zoom"
msgstr "Aumento l'ingrandimento" msgstr "Aumento l'ingrandimento"
@ -232,10 +244,10 @@ msgstr "Tutti"
msgid "Refresh" msgid "Refresh"
msgstr "Aggiorna" msgstr "Aggiorna"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:591 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
msgid "Show critical path" msgid "Show critical path"
msgstr "Mostra percorso critico" msgstr "Mostra percorso critico"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
msgid "Hide progress" msgid "Hide progress"
msgstr "Nascondi progresso" msgstr "Nascondi progresso"

View file

@ -7,9 +7,9 @@
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.2.2\n" "Project-Id-Version: libreplan-1.2.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-24 09:08+0100\n" "POT-Creation-Date: 2012-04-11 08:32+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -31,11 +31,15 @@ msgstr ""
msgid "Worker" msgid "Worker"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
msgid "Show money cost bar"
msgstr ""
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29 #: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
msgid "Start" msgid "Start"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:635 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
msgid "Show reported hours" msgid "Show reported hours"
msgstr "" msgstr ""
@ -84,6 +88,10 @@ msgstr ""
msgid "Criterion" msgid "Criterion"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
msgid "Hide money cost bar"
msgstr ""
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
msgid "Print" msgid "Print"
msgstr "" msgstr ""
@ -112,6 +120,10 @@ msgstr ""
msgid "changing zoom" msgid "changing zoom"
msgstr "" msgstr ""
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
msgid "Show/Hide money cost bar"
msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
msgid "Quarter" msgid "Quarter"
msgstr "" msgstr ""
@ -137,7 +149,7 @@ msgstr ""
msgid "Name filter" msgid "Name filter"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:615 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
msgid "Show progress" msgid "Show progress"
msgstr "" msgstr ""
@ -149,14 +161,14 @@ msgstr ""
msgid "Show/Hide critical path" msgid "Show/Hide critical path"
msgstr "" 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 #: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
msgid "showing criteria" msgid "showing criteria"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
msgid "Month" msgid "Month"
msgstr "" msgstr ""
@ -169,11 +181,11 @@ msgstr ""
msgid "Set End-Start" msgid "Set End-Start"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:297 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
msgid "decreasing zoom" msgid "decreasing zoom"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:596 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
msgid "Hide critical path" msgid "Hide critical path"
msgstr "" msgstr ""
@ -181,7 +193,7 @@ msgstr ""
msgid "Day" msgid "Day"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:642 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
msgid "Hide reported hours" msgid "Hide reported hours"
msgstr "" msgstr ""
@ -202,7 +214,7 @@ msgid "Hour"
msgstr "" msgstr ""
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90 #: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:114 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
msgid "Graphics" msgid "Graphics"
msgstr "" msgstr ""
@ -214,7 +226,7 @@ msgstr ""
msgid "See resource allocation" msgid "See resource allocation"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:280 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
msgid "increasing zoom" msgid "increasing zoom"
msgstr "" msgstr ""
@ -230,10 +242,10 @@ msgstr ""
msgid "Refresh" msgid "Refresh"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:591 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
msgid "Show critical path" msgid "Show critical path"
msgstr "" msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
msgid "Hide progress" msgid "Hide progress"
msgstr "" msgstr ""

View file

@ -8,10 +8,10 @@
# Jeroen Baten <jeroen@jeroenbaten.nl>, 2012. # Jeroen Baten <jeroen@jeroenbaten.nl>, 2012.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: LibrePlan\n" "Project-Id-Version: libreplan-1.2.3\n"
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n" "Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
"POT-Creation-Date: 2012-02-24 09:08+0100\n" "POT-Creation-Date: 2012-04-11 08:32+0200\n"
"PO-Revision-Date: 2012-02-29 19:53+0000\n" "PO-Revision-Date: 2012-04-13 14:30+0000\n"
"Last-Translator: Jeroen Baten <jeroen@jeroenbaten.nl>\n" "Last-Translator: Jeroen Baten <jeroen@jeroenbaten.nl>\n"
"Language-Team: Nederlands\n" "Language-Team: Nederlands\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -33,11 +33,15 @@ msgstr "Voeg afhankelijkheid toe"
msgid "Worker" msgid "Worker"
msgstr "Werker" msgstr "Werker"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
msgid "Show money cost bar"
msgstr "Toon geldelijke kosten balk"
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29 #: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
msgid "Start" msgid "Start"
msgstr "Start" msgstr "Start"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:635 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
msgid "Show reported hours" msgid "Show reported hours"
msgstr "Toon gerapporteerde uren" msgstr "Toon gerapporteerde uren"
@ -86,6 +90,10 @@ msgstr "Beschikbare inspanning: {0}, toegewezen inspanning: {1}"
msgid "Criterion" msgid "Criterion"
msgstr "Criterium" msgstr "Criterium"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
msgid "Hide money cost bar"
msgstr "Verberg geldelijke kosten balk"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
msgid "Print" msgid "Print"
msgstr "Afdrukken" msgstr "Afdrukken"
@ -114,6 +122,10 @@ msgstr "Einde"
msgid "changing zoom" msgid "changing zoom"
msgstr "wijzig zoom" msgstr "wijzig zoom"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
msgid "Show/Hide money cost bar"
msgstr "Toon/verberg geldelijke kosten balk"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
msgid "Quarter" msgid "Quarter"
msgstr "Kwartaal" msgstr "Kwartaal"
@ -139,7 +151,7 @@ msgstr "Naam"
msgid "Name filter" msgid "Name filter"
msgstr "Naam filter " msgstr "Naam filter "
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:615 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
msgid "Show progress" msgid "Show progress"
msgstr "Toon voortgang" msgstr "Toon voortgang"
@ -151,14 +163,14 @@ msgstr "Inklappen/Uitklappen alles"
msgid "Show/Hide critical path" msgid "Show/Hide critical path"
msgstr "Toon/Verberg kritieke pad" msgstr "Toon/Verberg kritieke pad"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Jaar"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150 #: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
msgid "showing criteria" msgid "showing criteria"
msgstr "tonen criteria" msgstr "tonen criteria"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Jaar"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58 #: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
msgid "Month" msgid "Month"
msgstr "Maand" msgstr "Maand"
@ -171,11 +183,11 @@ msgstr "Toon/Verberg resources"
msgid "Set End-Start" msgid "Set End-Start"
msgstr "Set End-Start" msgstr "Set End-Start"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:297 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
msgid "decreasing zoom" msgid "decreasing zoom"
msgstr "uitzoomen" msgstr "uitzoomen"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:596 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
msgid "Hide critical path" msgid "Hide critical path"
msgstr "Verberg kritieke pad" msgstr "Verberg kritieke pad"
@ -183,7 +195,7 @@ msgstr "Verberg kritieke pad"
msgid "Day" msgid "Day"
msgstr "Dag" msgstr "Dag"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:642 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
msgid "Hide reported hours" msgid "Hide reported hours"
msgstr "Verberg gerapporteerde uren" msgstr "Verberg gerapporteerde uren"
@ -204,7 +216,7 @@ msgid "Hour"
msgstr "Uur" msgstr "Uur"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90 #: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:114 #: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
msgid "Graphics" msgid "Graphics"
msgstr "Graphics" msgstr "Graphics"
@ -216,7 +228,7 @@ msgstr "Set Start-Start"
msgid "See resource allocation" msgid "See resource allocation"
msgstr "Zie resource allocation" msgstr "Zie resource allocation"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:280 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
msgid "increasing zoom" msgid "increasing zoom"
msgstr "Inzoomen" msgstr "Inzoomen"
@ -232,10 +244,10 @@ msgstr "Alle"
msgid "Refresh" msgid "Refresh"
msgstr "Ververs" msgstr "Ververs"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:591 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
msgid "Show critical path" msgid "Show critical path"
msgstr "Toon kritieke pad" msgstr "Toon kritieke pad"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620 #: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
msgid "Hide progress" msgid "Hide progress"
msgstr "Verberg voortgang" msgstr "Verberg voortgang"

View file

@ -0,0 +1,253 @@
# 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:
# Krzysztof Kamecki <dwerens90@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: libreplan-1.2.3\n"
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
"POT-Creation-Date: 2012-04-11 08:32+0200\n"
"PO-Revision-Date: 2012-04-11 06:39+0000\n"
"Last-Translator: Krzysztof Kamecki <dwerens90@gmail.com>\n"
"Language-Team: Polski\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pl\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
msgid "Erase"
msgstr "Usuń"
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
msgid "Add Dependency"
msgstr "Dodaj Zależność"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
msgid "Worker"
msgstr "Pracownik"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
msgid "Show money cost bar"
msgstr ""
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
msgid "Start"
msgstr "Start"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
msgid "Show reported hours"
msgstr "Pokaż zgłaszane godziny"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:90
msgid "by criteria"
msgstr "po kryteriach"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:85
msgid "Show/Hide reported hours"
msgstr "Pokaż/Ukryj zgłaszane godziny"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:35
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:49
msgid "Zoom"
msgstr "Powiększ"
#: ganttzk/src/main/java/org/zkoss/ganttz/TabsRegistry.java:121
msgid "Limiting resources"
msgstr "Ograniczanie zasobów"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:67
msgid "The specified dependency is not allowed"
msgstr "Określony zasób nie jest dozwolony"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:255
msgid "Set End-End"
msgstr "Ustaw End-End"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:78
msgid "Show/Hide progress"
msgstr "Pokaż/Ukryj postęp"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
msgid "Task"
msgstr "Zadanie"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:89
msgid "by resources"
msgstr "po zasobach"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:199
msgid "available effort: {0}, assigned effort: {1}"
msgstr "dostępny wysiłek: {0}, przydzielony wysiłek: {1}"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:64
msgid "Criterion"
msgstr "Kryterium"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
msgid "Hide money cost bar"
msgstr ""
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
msgid "Print"
msgstr "Drukuj"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:71
msgid "Week"
msgstr "Tydzień"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:501
msgid "filtering by name"
msgstr "filtruj po nazwie"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadLeftPane.java:111
msgid "See scheduling"
msgstr "Zobacz planowanie"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:43
msgid "Show"
msgstr "Pokaż"
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:30
msgid "End"
msgstr "Koniec"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/TimeTracker.java:243
msgid "changing zoom"
msgstr "zmiana przybliżenia"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
msgid "Show/Hide money cost bar"
msgstr ""
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
msgid "Quarter"
msgstr "Kwartał"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
msgid "None"
msgstr "Żaden"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:71
msgid "Flatten/Unflatten tree"
msgstr "Płaskie/Rozwinięte drzewo"
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
msgid "Project"
msgstr "Projekt"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:67
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:28
msgid "Name"
msgstr "Nazwa"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:50
msgid "Name filter"
msgstr "Filtr nazwy"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
msgid "Show progress"
msgstr "Pokaż postęp"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:67
msgid "Expand/Collapse all"
msgstr "Rozwiń/Zwiń wszystkie"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:58
msgid "Show/Hide critical path"
msgstr "Pokaż/Ukryj ścieżkę krytyczną"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
msgid "showing criteria"
msgstr "pokaż kryteria"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
msgid "Year"
msgstr "Rok"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
msgid "Month"
msgstr "Miesiąc"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:64
msgid "Show/Hide resources"
msgstr "Pokaż/Ukryj zasoby"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:247
msgid "Set End-Start"
msgstr "Ustaw End-Start"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
msgid "decreasing zoom"
msgstr "zmniejszenie powiększenia"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
msgid "Hide critical path"
msgstr "ukryj ścieżkę krytyczną"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:84
msgid "Day"
msgstr "Dzień"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
msgid "Hide reported hours"
msgstr "Ukryj zgłoszone godziny"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:193
msgid "Load: {0}%"
msgstr "Ładowanie: {0}%"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:147
msgid "showing resources"
msgstr "pokazuję zasoby"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:61
msgid "Show/Hide labels"
msgstr "Pokaż/Ukryj etykiety"
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:97
msgid "Hour"
msgstr "Godzina"
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
msgid "Graphics"
msgstr "Grafika"
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:251
msgid "Set Start-Start"
msgstr "Ustaw Start-Start"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:152
msgid "See resource allocation"
msgstr "Pokaż przydział zasobów"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
msgid "increasing zoom"
msgstr "powiększ powiększenie"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:467
msgid "Show all elements"
msgstr "Pokaż wszystkie elementy"
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:466
msgid "All"
msgstr "Wszystko"
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:38
msgid "Refresh"
msgstr "Odśwież"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
msgid "Show critical path"
msgstr "Pokaż ścieżkę krytyczną"
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
msgid "Hide progress"
msgstr "Ukryj postęp"

View file

@ -40,17 +40,17 @@ resourcesLoadPanel = self;
<separator/> <separator/>
<hbox id="additionalFilterInsertionPoint1" /> <hbox id="additionalFilterInsertionPoint1" />
<separator/> <separator/>
${ganttzk_i18n:_('Show')}: <label id="filterByNameLabel">${ganttzk_i18n:_('Page')}:</label>
<listbox id="listFilters" mold="select" rows="1" width="100px" <combobox id="filterByNameCombo" width="50px"
onChange="resourcesLoadPanel.onSelectFilterByName(self)" />
<separator/>
${ganttzk_i18n:_('Group by')}:
<listbox id="listFilters" mold="select" rows="1" width="150px"
model="${resourcesLoadPanel.filters}" model="${resourcesLoadPanel.filters}"
selectedIndex="0" selectedIndex="0"
onSelect="resourcesLoadPanel.setFilter(self.selectedItem.value);"> onSelect="resourcesLoadPanel.setFilter(self.selectedItem.value);">
</listbox> </listbox>
<separator/> <separator/>
<label id="filterByNameLabel">${ganttzk_i18n:_('Name filter')}:</label>
<combobox id="filterByNameCombo" width="50px"
onChange="resourcesLoadPanel.onSelectFilterByName(self)" />
<separator/>
<hbox id="additionalFilterInsertionPoint2" /> <hbox id="additionalFilterInsertionPoint2" />
</hbox> </hbox>
</north> </north>

View file

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.libreplan</groupId> <groupId>org.libreplan</groupId>
<artifactId>libreplan</artifactId> <artifactId>libreplan</artifactId>
<version>1.2.2</version> <version>1.2.3</version>
</parent> </parent>
<artifactId>libreplan-business</artifactId> <artifactId>libreplan-business</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -134,7 +134,7 @@
<plugin> <plugin>
<groupId>org.liquibase</groupId> <groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId> <artifactId>liquibase-maven-plugin</artifactId>
<version>2.0-rc7</version> <version>2.0.4</version>
<executions> <executions>
<execution> <execution>
<phase>process-resources</phase> <phase>process-resources</phase>
@ -162,7 +162,7 @@
<plugin> <plugin>
<groupId>org.liquibase</groupId> <groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId> <artifactId>liquibase-maven-plugin</artifactId>
<version>2.0-rc7</version> <version>2.0.4</version>
<executions> <executions>
<execution> <execution>
<phase>process-resources</phase> <phase>process-resources</phase>
@ -205,7 +205,7 @@
<pluginExecutionFilter> <pluginExecutionFilter>
<groupId>org.liquibase</groupId> <groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId> <artifactId>liquibase-maven-plugin</artifactId>
<versionRange>[2.0-rc7,)</versionRange> <versionRange>[2.0.4,)</versionRange>
<goals> <goals>
<goal>update</goal> <goal>update</goal>
</goals> </goals>

View file

@ -2,6 +2,7 @@
* This file is part of LibrePlan * This file is part of LibrePlan
* *
* Copyright (C) 2010-2011 Wireless Galicia, S.L. * Copyright (C) 2010-2011 Wireless Galicia, S.L.
* Copyright (C) 2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -19,24 +20,29 @@
package org.libreplan.business.common; package org.libreplan.business.common;
import org.libreplan.business.common.daos.IConfigurationDAO; import org.apache.commons.lang.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
/** /**
* It contains the compiling option to disable the warning changing default * This is a singleton that contains the compilation options passed from Maven.
* password and implements of singleton pattern. *
* Currently we have two options:
* <ul>
* <li>Enable/Disable the warning changing default password</li>
* <li>Enable/Disable default users (such as user, wsreader and wswriter)</li>
* </ul>
* *
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com> * @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
public class Configuration { public class Configuration {
private static final Configuration singleton = new Configuration(); private static final Configuration singleton = new Configuration();
@Autowired
private IConfigurationDAO configurationDAO;
private Boolean defaultPasswordsControl; private Boolean defaultPasswordsControl;
private Boolean exampleUsersDisabled;
private Configuration() { private Configuration() {
} }
@ -61,4 +67,19 @@ public class Configuration {
return defaultPasswordsControl; return defaultPasswordsControl;
} }
public void setExampleUsersDisabled(Boolean exampleUsersDisabled) {
this.exampleUsersDisabled = exampleUsersDisabled;
}
public Boolean getExampleUsersDisabled() {
return exampleUsersDisabled;
}
/**
* Returns the value of example users disabled compilation option
*/
public static boolean isExampleUsersDisabled() {
return BooleanUtils.isNotFalse(singleton.getExampleUsersDisabled());
}
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -91,6 +91,12 @@ public class Configuration extends BaseEntity {
private Boolean allowToGatherUsageStatsEnabled = false; private Boolean allowToGatherUsageStatsEnabled = false;
/**
* Currency code according to ISO-4217 (3 letters)
*/
private String currencyCode = "EUR";
private String currencySymbol = "";
public void setDefaultCalendar(BaseCalendar defaultCalendar) { public void setDefaultCalendar(BaseCalendar defaultCalendar) {
this.defaultCalendar = defaultCalendar; this.defaultCalendar = defaultCalendar;
} }
@ -363,4 +369,22 @@ public class Configuration extends BaseEntity {
this.allowToGatherUsageStatsEnabled = allowToGatherUsageStatsEnabled; this.allowToGatherUsageStatsEnabled = allowToGatherUsageStatsEnabled;
} }
@NotNull(message = "currency code not specified")
public String getCurrencyCode() {
return currencyCode;
}
public void setCurrencyCode(String currencyCode) {
this.currencyCode = currencyCode;
}
@NotNull(message = "currency symbol not specified")
public String getCurrencySymbol() {
return currencySymbol;
}
public void setCurrencySymbol(String currencySymbol) {
this.currencySymbol = currencySymbol;
}
} }

View file

@ -27,8 +27,6 @@ import org.hibernate.validator.NotEmpty;
*/ */
public class InfoComponent { public class InfoComponent {
private String code;
private String name; private String name;
private String description; private String description;
@ -36,15 +34,6 @@ public class InfoComponent {
public InfoComponent() { public InfoComponent() {
} }
public void setCode(String code) {
this.code = code;
}
@NotEmpty(message = "code not specified")
public String getCode() {
return code;
}
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
@ -64,7 +53,6 @@ public class InfoComponent {
public InfoComponent copy() { public InfoComponent copy() {
InfoComponent result = new InfoComponent(); InfoComponent result = new InfoComponent();
result.setCode(getCode());
result.setName(getName()); result.setName(getName());
result.setDescription(getDescription()); result.setDescription(getDescription());
return result; return result;

View file

@ -0,0 +1,47 @@
/*
* 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.orders.entities;
import org.hibernate.validator.NotEmpty;
/**
* @author Jacobo Aragunde Pérez <jaragunde@igalia.com>
*/
public class InfoComponentWithCode extends InfoComponent {
private String code;
public void setCode(String code) {
this.code = code;
}
@NotEmpty(message = "code not specified")
public String getCode() {
return code;
}
public InfoComponentWithCode copy() {
InfoComponentWithCode result = new InfoComponentWithCode();
result.setCode(getCode());
result.setName(getName());
result.setDescription(getDescription());
return result;
}
}

View file

@ -75,7 +75,7 @@ import org.libreplan.business.workreports.entities.WorkReportLine;
public abstract class OrderElement extends IntegrationEntity implements public abstract class OrderElement extends IntegrationEntity implements
ICriterionRequirable, ITreeNode<OrderElement> { ICriterionRequirable, ITreeNode<OrderElement> {
protected InfoComponent infoComponent = new InfoComponent(); protected InfoComponentWithCode infoComponent = new InfoComponentWithCode();
private Date initDate; private Date initDate;
@ -297,6 +297,16 @@ public abstract class OrderElement extends IntegrationEntity implements
//we have to remove the TaskSource which contains a TaskGroup instead of TaskElement //we have to remove the TaskSource which contains a TaskGroup instead of TaskElement
removeTaskSource(result); removeTaskSource(result);
} }
if(currentTaskSourceIsNotTheSame()) {
//this element was unscheduled and then scheduled again. Its TaskSource has
//been recreated but we have to remove the old one.
if(!getParent().currentTaskSourceIsNotTheSame()) {
//we only remove the TaskSource if the parent is not in the same situation.
//In case the parent is in the same situation, it will remove the related
//TaskSources in children tasks.
removeTaskSource(result);
}
}
result result
.addAll(synchronizationForSchedulingPoint(schedulingDataForVersion)); .addAll(synchronizationForSchedulingPoint(schedulingDataForVersion));
} else if (isSuperElementPartialOrCompletelyScheduled()) { } else if (isSuperElementPartialOrCompletelyScheduled()) {
@ -304,6 +314,15 @@ public abstract class OrderElement extends IntegrationEntity implements
if (wasASchedulingPoint()) { if (wasASchedulingPoint()) {
result.add(taskSourceRemoval()); result.add(taskSourceRemoval());
} }
if(currentTaskSourceIsNotTheSame()) {
//all the children of this element were unscheduled and then scheduled again,
//its TaskSource has been recreated but we have to remove the old one.
if(getParent() == null || !getParent().currentTaskSourceIsNotTheSame()) {
//if it's a container node inside another container we could have the
//same problem than in the case of leaf tasks.
result.add(taskSourceRemoval());
}
}
result result
.add(synchronizationForSuperelement(schedulingDataForVersion)); .add(synchronizationForSuperelement(schedulingDataForVersion));
} else if (schedulingState.isNoScheduled()) { } else if (schedulingState.isNoScheduled()) {
@ -331,6 +350,10 @@ public abstract class OrderElement extends IntegrationEntity implements
.getSchedulingStateType(); .getSchedulingStateType();
} }
protected boolean currentTaskSourceIsNotTheSame() {
return getOnDBTaskSource() != getTaskSource();
}
private List<TaskSourceSynchronization> childrenSynchronizations() { private List<TaskSourceSynchronization> childrenSynchronizations() {
List<TaskSourceSynchronization> childrenOfGroup = new ArrayList<TaskSourceSynchronization>(); List<TaskSourceSynchronization> childrenOfGroup = new ArrayList<TaskSourceSynchronization>();
for (OrderElement orderElement : getSomewhatScheduledOrderElements()) { for (OrderElement orderElement : getSomewhatScheduledOrderElements()) {
@ -1267,9 +1290,9 @@ public abstract class OrderElement extends IntegrationEntity implements
} }
@Valid @Valid
public InfoComponent getInfoComponent() { public InfoComponentWithCode getInfoComponent() {
if (infoComponent == null) { if (infoComponent == null) {
infoComponent = new InfoComponent(); infoComponent = new InfoComponentWithCode();
} }
return infoComponent; return infoComponent;
} }

View file

@ -0,0 +1,159 @@
/*
* 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.planner.entities;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.joda.time.LocalDate;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine.Interval;
import org.libreplan.business.hibernate.notification.PredefinedDatabaseSnapshots;
import org.libreplan.business.workreports.entities.WorkReportLine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* @author Diego Pino García <dpino@igalia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class CompanyEarnedValueCalculator extends EarnedValueCalculator implements ICompanyEarnedValueCalculator {
@Autowired
private PredefinedDatabaseSnapshots databaseSnapshots;
@Override
@Transactional(readOnly = true)
public SortedMap<LocalDate, BigDecimal> calculateBudgetedCostWorkScheduled(AvailabilityTimeLine.Interval interval) {
Map<TaskElement, SortedMap<LocalDate, BigDecimal>> estimatedCostPerTask = databaseSnapshots
.snapshotEstimatedCostPerTask();
Collection<TaskElement> list = filterTasksByDate(
estimatedCostPerTask.keySet(), interval);
SortedMap<LocalDate, BigDecimal> estimatedCost = new TreeMap<LocalDate, BigDecimal>();
for (TaskElement each : list) {
addCost(estimatedCost, estimatedCostPerTask.get(each));
}
return accumulateResult(estimatedCost);
}
private List<TaskElement> filterTasksByDate(
Collection<TaskElement> tasks,
AvailabilityTimeLine.Interval interval) {
List<TaskElement> result = new ArrayList<TaskElement>();
for(TaskElement task : tasks) {
if (interval.includes(task.getStartAsLocalDate())
|| interval.includes(task.getEndAsLocalDate())) {
result.add(task);
}
}
return result;
}
private List<WorkReportLine> filterWorkReportLinesByDate(
Collection<WorkReportLine> lines,
AvailabilityTimeLine.Interval interval) {
List<WorkReportLine> result = new ArrayList<WorkReportLine>();
for(WorkReportLine line: lines) {
if (interval.includes(line.getLocalDate())) {
result.add(line);
}
}
return result;
}
private void addCost(SortedMap<LocalDate, BigDecimal> currentCost,
SortedMap<LocalDate, BigDecimal> additionalCost) {
for (LocalDate day : additionalCost.keySet()) {
if (!currentCost.containsKey(day)) {
currentCost.put(day, BigDecimal.ZERO);
}
currentCost.put(day, currentCost.get(day).add(
additionalCost.get(day)));
}
}
private SortedMap<LocalDate, BigDecimal> accumulateResult(
SortedMap<LocalDate, BigDecimal> map) {
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
if (map.isEmpty()) {
return result;
}
BigDecimal accumulatedResult = BigDecimal.ZERO;
for (LocalDate day : map.keySet()) {
BigDecimal value = map.get(day);
accumulatedResult = accumulatedResult.add(value);
result.put(day, accumulatedResult);
}
return result;
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateActualCostWorkPerformed(
Interval interval) {
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
Collection<WorkReportLine> workReportLines = filterWorkReportLinesByDate(
databaseSnapshots.snapshotWorkReportLines(),
interval);
if (workReportLines.isEmpty()) {
return result;
}
for (WorkReportLine workReportLine : workReportLines) {
LocalDate day = new LocalDate(workReportLine.getDate());
BigDecimal cost = workReportLine.getEffort()
.toHoursAsDecimalWithScale(2);
if (!result.containsKey(day)) {
result.put(day, BigDecimal.ZERO);
}
result.put(day, result.get(day).add(cost));
}
return accumulateResult(result);
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateBudgetedCostWorkPerformed(
Interval interval) {
Map<TaskElement, SortedMap<LocalDate, BigDecimal>> advanceCostPerTask = databaseSnapshots
.snapshotAdvanceCostPerTask();
Collection<TaskElement> tasks = filterTasksByDate(
advanceCostPerTask.keySet(), interval);
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
for (TaskElement each : tasks) {
addCost(result, advanceCostPerTask.get(each));
}
return result;
}
}

View file

@ -0,0 +1,252 @@
/*
* 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.planner.entities;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
*
* Calculates generic 'Earned Value' indicators (those calculated out of
* BCWP, ACWP and BCWS
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class EarnedValueCalculator implements IEarnedValueCalculator {
@Override
public SortedMap<LocalDate, BigDecimal> calculateCostVariance(
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> acwp) {
return substract(bcwp, acwp);
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateScheduleVariance(
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> bcws) {
return substract(bcwp, bcws);
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateBudgetAtCompletion(
SortedMap<LocalDate, BigDecimal> bcws) {
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
BigDecimal value = Collections.max(bcws.values());
for (LocalDate day : bcws.keySet()) {
result.put(day, value);
}
return result;
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateEstimateAtCompletion(
SortedMap<LocalDate, BigDecimal> acwp,
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> bac) {
return multiply(divide(acwp, bcwp,
BigDecimal.ZERO), bac);
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateVarianceAtCompletion(
SortedMap<LocalDate, BigDecimal> bac,
SortedMap<LocalDate, BigDecimal> eac) {
return substract(bac, eac);
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateEstimatedToComplete(
SortedMap<LocalDate, BigDecimal> eac,
SortedMap<LocalDate, BigDecimal> acwp) {
return substract(eac, acwp);
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateCostPerformanceIndex(
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> acwp) {
return divide(bcwp, acwp, BigDecimal.ZERO);
}
@Override
public SortedMap<LocalDate, BigDecimal> calculateSchedulePerformanceIndex(
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> bcws) {
return divide(bcwp, bcws, BigDecimal.ZERO);
}
private SortedMap<LocalDate, BigDecimal> substract(
SortedMap<LocalDate, BigDecimal> minuend,
SortedMap<LocalDate, BigDecimal> subtrahend) {
final SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
forValuesAtSameKey(minuend, subtrahend, substractionOperation(result));
return result;
}
public static <K, V> void forValuesAtSameKey(Map<K, V> a, Map<K, V> b,
IOperation<K, V> onSameKey) {
for (Entry<K, V> each : a.entrySet()) {
V aValue = each.getValue();
V bValue = b.get(each.getKey());
onSameKey.operate(each.getKey(), aValue, bValue);
}
}
private static IOperation<LocalDate, BigDecimal> substractionOperation(
final SortedMap<LocalDate, BigDecimal> result) {
return notNullOperands(new IOperation<LocalDate, BigDecimal>() {
@Override
public void operate(LocalDate key, BigDecimal minuedValue,
BigDecimal subtrahendValue) {
result.put(key, minuedValue.subtract(subtrahendValue));
}
@Override
public void undefinedFor(LocalDate key) {
}
});
}
public static <K, V> IOperation<K, V> notNullOperands(
final IOperation<K, V> operation) {
return new PreconditionChecker<K, V>(operation) {
@Override
protected boolean isOperationDefinedFor(K key, V a, V b) {
return a != null && b != null;
}
};
}
public interface IOperation<K, V> {
public void operate(K key, V a, V b);
public void undefinedFor(K key);
}
protected static abstract class PreconditionChecker<K, V> implements
IOperation<K, V> {
private final IOperation<K, V> decorated;
protected PreconditionChecker(IOperation<K, V> decorated) {
this.decorated = decorated;
}
@Override
public void operate(K key, V a, V b) {
if (isOperationDefinedFor(key, a, b)) {
decorated.operate(key, a, b);
} else {
decorated.undefinedFor(key);
}
}
protected abstract boolean isOperationDefinedFor(K key, V a, V b);
@Override
public void undefinedFor(K key) {
decorated.undefinedFor(key);
}
}
private static SortedMap<LocalDate, BigDecimal> multiply(
Map<LocalDate, BigDecimal> firstFactor,
Map<LocalDate, BigDecimal> secondFactor) {
final SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
forValuesAtSameKey(firstFactor, secondFactor,
multiplicationOperation(result));
return result;
}
private static IOperation<LocalDate, BigDecimal> multiplicationOperation(
final SortedMap<LocalDate, BigDecimal> result) {
return notNullOperands(new IOperation<LocalDate, BigDecimal>() {
@Override
public void operate(LocalDate key, BigDecimal a,
BigDecimal b) {
result.put(key, a.multiply(b));
}
@Override
public void undefinedFor(LocalDate key) {
result.put(key, BigDecimal.ZERO);
}
});
}
private static SortedMap<LocalDate, BigDecimal> divide(
Map<LocalDate, BigDecimal> dividend,
Map<LocalDate, BigDecimal> divisor,
final BigDecimal defaultIfNotComputable) {
final TreeMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
forValuesAtSameKey(dividend, divisor,
divisionOperation(result, defaultIfNotComputable));
return result;
}
private static IOperation<LocalDate, BigDecimal> divisionOperation(
final TreeMap<LocalDate, BigDecimal> result,
final BigDecimal defaultIfNotComputable) {
return notNullOperands(secondOperandNotZero(new IOperation<LocalDate, BigDecimal>() {
@Override
public void operate(LocalDate key, BigDecimal dividendValue,
BigDecimal divisorValue) {
result.put(key,
dividendValue.divide(divisorValue, RoundingMode.DOWN));
}
@Override
public void undefinedFor(LocalDate key) {
result.put(key, defaultIfNotComputable);
}
}));
}
public static <K> IOperation<K, BigDecimal> secondOperandNotZero(
final IOperation<K, BigDecimal> operation) {
return new PreconditionChecker<K, BigDecimal>(operation) {
@Override
protected boolean isOperationDefinedFor(K key, BigDecimal a,
BigDecimal b) {
return b.signum() != 0;
}
};
}
}

View file

@ -0,0 +1,44 @@
/*
* 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.planner.entities;
import java.math.BigDecimal;
import java.util.SortedMap;
import org.joda.time.LocalDate;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine;
/**
* @author Diego Pino García <dpino@igalia.com>
*
* Utility class for calculating all 'Earned Value' indicators
*/
public interface ICompanyEarnedValueCalculator extends IEarnedValueCalculator {
SortedMap<LocalDate, BigDecimal> calculateBudgetedCostWorkScheduled(
AvailabilityTimeLine.Interval interval);
SortedMap<LocalDate, BigDecimal> calculateActualCostWorkPerformed(
AvailabilityTimeLine.Interval interval);
SortedMap<LocalDate, BigDecimal> calculateBudgetedCostWorkPerformed(
AvailabilityTimeLine.Interval interval);
}

View file

@ -0,0 +1,74 @@
/*
* 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.planner.entities;
import java.math.BigDecimal;
import java.util.SortedMap;
import org.joda.time.LocalDate;
/**
* @author Diego Pino García <dpino@igalia.com>
*
* Utility class for calculating all 'Earned Value' indicators
*/
public interface IEarnedValueCalculator {
// CV = BCWP - ACWP
SortedMap<LocalDate, BigDecimal> calculateCostVariance(
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> acwp);
// SV = BCWP - BCWS
SortedMap<LocalDate, BigDecimal> calculateScheduleVariance(
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> bcws);
// BAC = max (BCWS)
SortedMap<LocalDate, BigDecimal> calculateBudgetAtCompletion(
SortedMap<LocalDate, BigDecimal> bcws);
// EAC = (ACWP/BCWP) * BAC
SortedMap<LocalDate, BigDecimal> calculateEstimateAtCompletion(
SortedMap<LocalDate, BigDecimal> acwp,
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> bac);
// VAC = BAC - EAC
SortedMap<LocalDate, BigDecimal> calculateVarianceAtCompletion(
SortedMap<LocalDate, BigDecimal> bac,
SortedMap<LocalDate, BigDecimal> eac);
// ETC = EAC - ACWP
SortedMap<LocalDate, BigDecimal> calculateEstimatedToComplete(
SortedMap<LocalDate, BigDecimal> eac,
SortedMap<LocalDate, BigDecimal> acwp);
// SPI = BCWP / BCWS
SortedMap<LocalDate, BigDecimal> calculateSchedulePerformanceIndex(
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> bcws);
// CPI = BCWP / ACWP
SortedMap<LocalDate, BigDecimal> calculateCostPerformanceIndex(
SortedMap<LocalDate, BigDecimal> bcwp,
SortedMap<LocalDate, BigDecimal> acwp);
}

View file

@ -0,0 +1,66 @@
/*
* 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.planner.entities;
import java.math.BigDecimal;
import java.util.SortedMap;
import org.joda.time.LocalDate;
import org.libreplan.business.orders.entities.Order;
/**
* @author Diego Pino García <dpino@igalia.com>
*
* Utility class for calculating all 'Earned Value' indicators
*/
public interface IOrderEarnedValueCalculator extends IEarnedValueCalculator {
// ACWP (Actual Cost Work Performed)
SortedMap<LocalDate, BigDecimal> calculateActualCostWorkPerformed(
Order order);
// BCWP (Budgeted Cost Work Performed)
SortedMap<LocalDate, BigDecimal> calculateBudgetedCostWorkPerformed(
Order order);
// BCWS (Budgeted Cost Work Scheduled)
SortedMap<LocalDate, BigDecimal> calculateBudgetedCostWorkScheduled(Order order);
// ACWP at date
BigDecimal getActualCostWorkPerformedAt(Order order, LocalDate date);
// BAC (Budget at Completion)
BigDecimal getBudgetAtCompletion(Order order);
// BCWP at date
BigDecimal getBudgetedCostWorkPerformedAt(Order order, LocalDate date);
// CPI (Cost Performance Index)
BigDecimal getCostPerformanceIndex(BigDecimal budgetedCost,
BigDecimal actualCost);
// CV (Cost Variance)
BigDecimal getCostVariance(BigDecimal budgetedCost, BigDecimal actualCost);
// EAC (Estimate At Completion)
BigDecimal getEstimateAtCompletion(BigDecimal budgetAtCompletion,
BigDecimal costPerformanceIndex);
}

View file

@ -0,0 +1,181 @@
/*
* 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.planner.entities;
import java.math.BigDecimal;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import org.joda.time.LocalDate;
import org.libreplan.business.orders.entities.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* @author Diego Pino García <dpino@igalia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class OrderEarnedValueCalculator extends EarnedValueCalculator implements IOrderEarnedValueCalculator {
@Autowired
private ICostCalculator hoursCostCalculator;
@Transactional(readOnly = true)
@Override
public BigDecimal getActualCostWorkPerformedAt(Order order, LocalDate date) {
SortedMap<LocalDate, BigDecimal> actualCost = calculateActualCostWorkPerformed(order);
BigDecimal result = actualCost.get(date);
return (result != null) ? result : BigDecimal.ZERO;
}
@Transactional(readOnly = true)
@Override
public SortedMap<LocalDate, BigDecimal> calculateActualCostWorkPerformed(
Order order) {
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
for (TaskElement taskElement : getAllTaskElements(order)) {
if (taskElement instanceof Task) {
addCost(result, getWorkReportCost((Task) taskElement));
}
}
return accumulateResult(result);
}
private SortedMap<LocalDate, BigDecimal> accumulateResult(
SortedMap<LocalDate, BigDecimal> map) {
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
if (map.isEmpty()) {
return result;
}
BigDecimal accumulatedResult = BigDecimal.ZERO;
for (LocalDate day : map.keySet()) {
BigDecimal value = map.get(day);
accumulatedResult = accumulatedResult.add(value);
result.put(day, accumulatedResult);
}
return result;
}
private void addCost(SortedMap<LocalDate, BigDecimal> currentCost,
SortedMap<LocalDate, BigDecimal> additionalCost) {
for (LocalDate day : additionalCost.keySet()) {
if (!currentCost.containsKey(day)) {
currentCost.put(day, BigDecimal.ZERO);
}
currentCost.put(day,
currentCost.get(day).add(additionalCost.get(day)));
}
}
private List<TaskElement> getAllTaskElements(Order order) {
List<TaskElement> result = order.getAllChildrenAssociatedTaskElements();
result.add(order.getAssociatedTaskElement());
return result;
}
private SortedMap<LocalDate, BigDecimal> getWorkReportCost(Task taskElement) {
return hoursCostCalculator.getWorkReportCost(taskElement);
}
@Override
@Transactional(readOnly = true)
public BigDecimal getBudgetAtCompletion(Order order) {
SortedMap<LocalDate, BigDecimal> budgedtedCost = calculateBudgetedCostWorkScheduled(order);
LocalDate lastKey = budgedtedCost.lastKey();
return (lastKey) != null ? budgedtedCost.get(lastKey) : BigDecimal.ZERO;
}
@Override
@Transactional(readOnly = true)
public SortedMap<LocalDate, BigDecimal> calculateBudgetedCostWorkScheduled(
Order order) {
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
for (TaskElement taskElement : getAllTaskElements(order)) {
if (taskElement instanceof Task) {
addCost(result, getEstimatedCost((Task) taskElement));
}
}
return accumulateResult(result);
}
private SortedMap<LocalDate, BigDecimal> getEstimatedCost(Task task) {
return hoursCostCalculator.getEstimatedCost(task);
}
@Override
@Transactional(readOnly = true)
public BigDecimal getBudgetedCostWorkPerformedAt(Order order, LocalDate date) {
SortedMap<LocalDate, BigDecimal> budgetedCost = calculateBudgetedCostWorkPerformed(order);
BigDecimal result = budgetedCost.get(date);
return (result != null) ? result : BigDecimal.ZERO;
}
@Override
@Transactional(readOnly = true)
public SortedMap<LocalDate, BigDecimal> calculateBudgetedCostWorkPerformed(
Order order) {
SortedMap<LocalDate, BigDecimal> estimatedCost = new TreeMap<LocalDate, BigDecimal>();
for (TaskElement taskElement : getAllTaskElements(order)) {
if (taskElement instanceof Task) {
addCost(estimatedCost, getAdvanceCost((Task) taskElement));
}
}
return accumulateResult(estimatedCost);
}
private SortedMap<LocalDate, BigDecimal> getAdvanceCost(Task task) {
return hoursCostCalculator.getAdvanceCost(task);
}
@Override
public BigDecimal getCostPerformanceIndex(BigDecimal budgetedCost,
BigDecimal actualCost) {
if (BigDecimal.ZERO.compareTo(actualCost) == 0) {
return BigDecimal.ZERO;
}
return asPercentage(budgetedCost.divide(actualCost));
}
private BigDecimal asPercentage(BigDecimal value) {
return value.multiply(BigDecimal.valueOf(100)).setScale(2);
}
@Override
public BigDecimal getCostVariance(BigDecimal budgetedCost,
BigDecimal actualCost) {
return budgetedCost.subtract(actualCost);
}
@Override
public BigDecimal getEstimateAtCompletion(BigDecimal budgetAtCompletion,
BigDecimal costPerformanceIndex) {
if (BigDecimal.ZERO.compareTo(costPerformanceIndex) == 0) {
return BigDecimal.ZERO;
}
return asPercentage(budgetAtCompletion.divide(costPerformanceIndex));
}
}

View file

@ -209,9 +209,40 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
public static AllocationsSpecified allocating( public static AllocationsSpecified allocating(
List<ResourcesPerDayModification> resourceAllocations) { List<ResourcesPerDayModification> resourceAllocations) {
sortResourceAllocations(resourceAllocations);
return new AllocationsSpecified(resourceAllocations); return new AllocationsSpecified(resourceAllocations);
} }
/**
* Specific allocations should be done first in order to generic allocations
* selects the less charged resources if there are several allocations in
* the same task
*
* @param resourceAllocations
* Sorted with specific allocations before generic ones
*/
private static void sortResourceAllocations(
List<ResourcesPerDayModification> resourceAllocations) {
Collections.sort(resourceAllocations,
new Comparator<ResourcesPerDayModification>() {
@Override
public int compare(ResourcesPerDayModification o1,
ResourcesPerDayModification o2) {
if (o1.isSpecific() && o2.isSpecific()) {
return 0;
}
if (o1.isSpecific()) {
return -1;
}
if (o2.isSpecific()) {
return 1;
}
return 0;
}
});
}
private static void checkStartLessOrEqualToEnd(IntraDayDate startInclusive, private static void checkStartLessOrEqualToEnd(IntraDayDate startInclusive,
IntraDayDate endExclusive) { IntraDayDate endExclusive) {
Validate.isTrue(startInclusive.compareTo(endExclusive) <= 0, Validate.isTrue(startInclusive.compareTo(endExclusive) <= 0,
@ -2123,7 +2154,7 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
getDayAssignmentsState().detachAssignments(); getDayAssignmentsState().detachAssignments();
} }
void associateAssignmentsToResource() { public void associateAssignmentsToResource() {
for (DayAssignment dayAssignment : getAssignments()) { for (DayAssignment dayAssignment : getAssignments()) {
dayAssignment.associateToResource(); dayAssignment.associateToResource();
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -73,6 +73,7 @@ import org.libreplan.business.workingday.ResourcesPerDay;
/** /**
* @author Óscar González Fernández <ogonzalez@igalia.com> * @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
public class Task extends TaskElement implements ITaskPositionConstrained { public class Task extends TaskElement implements ITaskPositionConstrained {
@ -1218,4 +1219,10 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
public void resetStatus() { public void resetStatus() {
this.currentStatus = null; this.currentStatus = null;
} }
@Override
public boolean isAnyTaskWithConstraint(PositionConstraintType type) {
return getPositionConstraint().getConstraintType().equals(type);
}
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -63,6 +63,7 @@ import org.libreplan.business.workingday.ResourcesPerDay;
/** /**
* @author Óscar González Fernández <ogonzalez@igalia.com> * @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
public abstract class TaskElement extends BaseEntity { public abstract class TaskElement extends BaseEntity {
@ -769,4 +770,6 @@ public abstract class TaskElement extends BaseEntity {
return null; return null;
} }
public abstract boolean isAnyTaskWithConstraint(PositionConstraintType type);
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -44,6 +44,7 @@ import org.libreplan.business.workingday.IntraDayDate;
/** /**
* @author Óscar González Fernández <ogonzalez@igalia.com> * @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com> * @author Javier Moran Rua <jmoran@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
public class TaskGroup extends TaskElement { public class TaskGroup extends TaskElement {
@ -376,4 +377,15 @@ public class TaskGroup extends TaskElement {
public void resetStatus() { public void resetStatus() {
this.isFinished = this.isInProgress = null; this.isFinished = this.isInProgress = null;
} }
@Override
public boolean isAnyTaskWithConstraint(PositionConstraintType type) {
for (TaskElement taskElement : getChildren()) {
if (taskElement.isAnyTaskWithConstraint(type)) {
return true;
}
}
return false;
}
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -43,6 +43,7 @@ import org.libreplan.business.workingday.IntraDayDate;
/** /**
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com> * @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com> * @author Javier Moran Rua <jmoran@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
public class TaskMilestone extends TaskElement implements ITaskPositionConstrained { public class TaskMilestone extends TaskElement implements ITaskPositionConstrained {
@ -225,4 +226,9 @@ public class TaskMilestone extends TaskElement implements ITaskPositionConstrain
return false; return false;
} }
@Override
public boolean isAnyTaskWithConstraint(PositionConstraintType type) {
return getPositionConstraint().getConstraintType().equals(type);
}
} }

View file

@ -127,6 +127,11 @@ public abstract class ResourcesPerDayModification extends
return genericAllocation.createEffortDistributor(getResources()); return genericAllocation.createEffortDistributor(getResources());
} }
@Override
public boolean isSpecific() {
return false;
}
} }
private static class OnSpecificAllocation extends private static class OnSpecificAllocation extends
@ -194,6 +199,11 @@ public abstract class ResourcesPerDayModification extends
return resourceAllocation.createEffortDistributor(); return resourceAllocation.createEffortDistributor();
} }
@Override
public boolean isSpecific() {
return true;
}
} }
public static ResourcesPerDayModification create( public static ResourcesPerDayModification create(
@ -319,4 +329,6 @@ public abstract class ResourcesPerDayModification extends
getBeingModified().getNonConsolidatedResourcePerDay()); getBeingModified().getNonConsolidatedResourcePerDay());
} }
public abstract boolean isSpecific();
} }

View file

@ -29,7 +29,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
@ -89,8 +88,19 @@ public abstract class UntilFillingHoursAllocator {
IntraDayDate candidate = untilAllocating(dateFromWhichToAllocate, IntraDayDate candidate = untilAllocating(dateFromWhichToAllocate,
each.allocation, each.duration); each.allocation, each.duration);
currentResult = pickCurrentOrCandidate(currentResult, candidate); currentResult = pickCurrentOrCandidate(currentResult, candidate);
setNewDataForAllocation(each.allocation, currentResult);
// This is done in order that new assignments are taken into account
// for the next allocations in the same task
each.allocation.getResourceAllocation()
.associateAssignmentsToResource();
} }
setAssignmentsForEachAllocation(currentResult); // Then we detach the day assignments as they are going to be associated
// again later
for (EffortPerAllocation each : effortPerAllocation) {
each.allocation.getResourceAllocation().detach();
}
return currentResult; return currentResult;
} }
@ -228,22 +238,16 @@ public abstract class UntilFillingHoursAllocator {
} }
} }
private void setAssignmentsForEachAllocation(IntraDayDate resultDate) {
for (Entry<ResourcesPerDayModification, List<DayAssignment>> entry : resultAssignments
.entrySet()) {
setNewDataForAllocation(entry, resultDate);
}
}
private <T extends DayAssignment> void setNewDataForAllocation( private <T extends DayAssignment> void setNewDataForAllocation(
Entry<ResourcesPerDayModification, List<DayAssignment>> entry, ResourcesPerDayModification resourcesPerDayModification,
IntraDayDate resultDate) { IntraDayDate resultDate) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ResourceAllocation<T> allocation = (ResourceAllocation<T>) entry ResourceAllocation<T> allocation = (ResourceAllocation<T>) resourcesPerDayModification
.getKey().getBeingModified(); .getBeingModified();
ResourcesPerDay resourcesPerDay = entry.getKey().getGoal(); ResourcesPerDay resourcesPerDay = resourcesPerDayModification.getGoal();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<T> value = (List<T>) entry.getValue(); List<T> value = (List<T>) resultAssignments
.get(resourcesPerDayModification);
setNewDataForAllocation(allocation, resultDate, resourcesPerDay, setNewDataForAllocation(allocation, resultDate, resourcesPerDay,
value); value);
} }

View file

@ -38,9 +38,9 @@ public class HoursWorkedPerResourceDTO implements Comparable {
private Date date; private Date date;
private LocalTime clockStart; private String clockStart;
private LocalTime clockFinish; private String clockFinish;
private EffortDuration effort; private EffortDuration effort;
@ -59,8 +59,12 @@ public class HoursWorkedPerResourceDTO implements Comparable {
this.workerName = resource.getName(); this.workerName = resource.getName();
this.date = workReportLine.getDate(); this.date = workReportLine.getDate();
this.clockStart = workReportLine.getClockStart(); LocalTime clockStart = workReportLine.getClockStart();
this.clockFinish = workReportLine.getClockFinish(); this.clockStart = (clockStart != null) ? clockStart.toString("HH:mm")
: "";
LocalTime clockFinish = workReportLine.getClockFinish();
this.clockFinish = (clockFinish != null) ? clockFinish
.toString("HH:mm") : "";
this.effort = workReportLine.getEffort(); this.effort = workReportLine.getEffort();
this.orderElementCode = workReportLine.getOrderElement().getCode(); this.orderElementCode = workReportLine.getOrderElement().getCode();
this.orderElementName = workReportLine.getOrderElement().getName(); this.orderElementName = workReportLine.getOrderElement().getName();
@ -98,19 +102,19 @@ public class HoursWorkedPerResourceDTO implements Comparable {
this.effort = effort; this.effort = effort;
} }
public LocalTime getClockStart() { public String getClockStart() {
return clockStart; return clockStart;
} }
public void setClockStart(LocalTime clockStart) { public void setClockStart(String clockStart) {
this.clockStart = clockStart; this.clockStart = clockStart;
} }
public LocalTime getClockFinish() { public String getClockFinish() {
return clockFinish; return clockFinish;
} }
public void setClockFinish(LocalTime clockFinish) { public void setClockFinish(String clockFinish) {
this.clockFinish = clockFinish; this.clockFinish = clockFinish;
} }

View file

@ -2,6 +2,7 @@
* This file is part of LibrePlan * This file is part of LibrePlan
* *
* Copyright (C) 2011 ComtecSF, S.L. * Copyright (C) 2011 ComtecSF, S.L.
* Copyright (C) 2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -28,6 +29,7 @@ import java.util.Locale;
* *
* @author Cristina Alavarino Perez <cristina.alvarino@comtecsf.es> * @author Cristina Alavarino Perez <cristina.alvarino@comtecsf.es>
* @author Ignacio Diaz Teijido <ignacio.diaz@comtecsf.es> * @author Ignacio Diaz Teijido <ignacio.diaz@comtecsf.es>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
public enum Language { public enum Language {
@ -39,7 +41,8 @@ public enum Language {
PORTUGUESE_LANGUAGE("Português", new Locale("pt")), PORTUGUESE_LANGUAGE("Português", new Locale("pt")),
ITALIAN_LANGUAGE("Italiano", new Locale("it")), ITALIAN_LANGUAGE("Italiano", new Locale("it")),
FRENCH_LANGUAGE("Français", new Locale("fr")), FRENCH_LANGUAGE("Français", new Locale("fr")),
DUTCH_LANGUAGE("Nederlands", new Locale("nl")); DUTCH_LANGUAGE("Nederlands", new Locale("nl")),
POLISH_LANGUAGE("Polski", new Locale("pl"));
private final String displayName; private final String displayName;

View file

@ -354,14 +354,6 @@ public abstract class OrderElementTemplate extends BaseEntity implements
this.deadlineAsDaysFromBeginning = days; this.deadlineAsDaysFromBeginning = days;
} }
public String getCode() {
return getInfoComponent().getCode();
}
public void setCode(String code) {
getInfoComponent().setCode(code);
}
public String getDescription() { public String getDescription() {
return getInfoComponent().getDescription(); return getInfoComponent().getDescription();
} }
@ -384,7 +376,6 @@ public abstract class OrderElementTemplate extends BaseEntity implements
} }
protected void copyTo(OrderElementTemplate result) { protected void copyTo(OrderElementTemplate result) {
result.setCode(getCode());
result.setName(getName()); result.setName(getName());
result.setDescription(getDescription()); result.setDescription(getDescription());
result.setDeadlineAsDaysFromBeginning(getDeadlineAsDaysFromBeginning()); result.setDeadlineAsDaysFromBeginning(getDeadlineAsDaysFromBeginning());

View file

@ -186,12 +186,14 @@
columnDataType="BOOLEAN" /> columnDataType="BOOLEAN" />
</changeSet> </changeSet>
<changeSet id="change-column-description-in-order_element-to-text" author="mrego"> <changeSet id="change-column-description-in-order_element-to-text"
author="mrego" dbms="postgresql">
<comment>Change column description in order_element to TEXT</comment> <comment>Change column description in order_element to TEXT</comment>
<modifyDataType tableName="order_element" columnName="description" newDataType="TEXT" /> <modifyDataType tableName="order_element" columnName="description" newDataType="TEXT" />
</changeSet> </changeSet>
<changeSet id="change-column-description-in-order_element_template-to-text" author="mrego"> <changeSet id="change-column-description-in-order_element_template-to-text"
author="mrego" dbms="postgresql">
<comment>Change column description in order_element_template to TEXT</comment> <comment>Change column description in order_element_template to TEXT</comment>
<modifyDataType tableName="order_element_template" columnName="description" newDataType="TEXT" /> <modifyDataType tableName="order_element_template" columnName="description" newDataType="TEXT" />
</changeSet> </changeSet>
@ -223,6 +225,18 @@
<renameTable oldTableName="end_date_communication_to_customer" newTableName="end_date_communication" /> <renameTable oldTableName="end_date_communication_to_customer" newTableName="end_date_communication" />
</changeSet> </changeSet>
<changeSet id="change-column-description-in-to-text-in-mysql"
author="mrego" dbms="mysql">
<comment>
Change column description in order_element and
order_element_template to TEXT in MySQL.
Because of using modifyDataType convert the column in LONGTEXT and
this is causing some problems with Hibernate mapping.
</comment>
<sql>ALTER TABLE order_element MODIFY description TEXT</sql>
<sql>ALTER TABLE order_element_template MODIFY description TEXT</sql>
</changeSet>
<changeSet id="add-budget-column-to-order_line" author="mrego"> <changeSet id="add-budget-column-to-order_line" author="mrego">
<comment>add budget column to order_line</comment> <comment>add budget column to order_line</comment>
<addColumn tableName="order_line"> <addColumn tableName="order_line">
@ -318,4 +332,31 @@
<dropColumn tableName="order_element" columnName="sum_charged_effort_id"/> <dropColumn tableName="order_element" columnName="sum_charged_effort_id"/>
</changeSet> </changeSet>
<changeSet id="add-new-columns-for-currency-in-configuration" author="mrego">
<comment>Add new columns for currency in configuration table</comment>
<addColumn tableName="configuration">
<column name="currency_code" type="VARCHAR(255)" />
</addColumn>
<addDefaultValue tableName="configuration" columnName="currency_code"
defaultValue="EUR" />
<addNotNullConstraint tableName="configuration"
columnName="currency_code"
defaultNullValue="EUR"
columnDataType="VARCHAR(255)" />
<addColumn tableName="configuration">
<column name="currency_symbol" type="VARCHAR(255)" />
</addColumn>
<addDefaultValue tableName="configuration" columnName="currency_symbol"
defaultValue="€" />
<addNotNullConstraint tableName="configuration"
columnName="currency_symbol"
defaultNullValue="€"
columnDataType="VARCHAR(255)" />
</changeSet>
<changeSet id="remove-code-from-order_element_template" author="jaragunde">
<comment>Remove column code in order_element_template table</comment>
<dropColumn tableName="order_element_template" columnName="code" />
</changeSet>
</databaseChangeLog> </databaseChangeLog>

View file

@ -144,7 +144,10 @@
factory-method="getInstance" factory-method="getInstance"
lazy-init="false"> lazy-init="false">
<property name="defaultPasswordsControl"> <property name="defaultPasswordsControl">
<value>${default.passwordsControl}</value> <value>${default.passwordsControl}</value>
</property>
<property name="exampleUsersDisabled">
<value>${default.exampleUsersDisabled}</value>
</property> </property>
</bean> </bean>

View file

@ -66,6 +66,9 @@
<property name="scenariosVisible" not-null="true" <property name="scenariosVisible" not-null="true"
column="scenarios_visible" /> column="scenarios_visible" />
<property name="currencyCode" not-null="true" column="currency_code" />
<property name="currencySymbol" not-null="true" column="currency_symbol" />
<component name="ldapConfiguration" class="org.libreplan.business.common.entities.LDAPConfiguration"> <component name="ldapConfiguration" class="org.libreplan.business.common.entities.LDAPConfiguration">
<property name="ldapHost" column="ldap_Host"/> <property name="ldapHost" column="ldap_Host"/>
<property name="ldapPort" column="ldap_port"/> <property name="ldapPort" column="ldap_port"/>

View file

@ -8,7 +8,7 @@
</generator> </generator>
</id> </id>
<version name="version" access="property" type="long" /> <version name="version" access="property" type="long" />
<component name="infoComponent" class="org.libreplan.business.orders.entities.InfoComponent"> <component name="infoComponent" class="org.libreplan.business.orders.entities.InfoComponentWithCode">
<property name="name" access="field" /> <property name="name" access="field" />
<property name="description" access="field" type="text" /> <property name="description" access="field" type="text" />
<property name="code" access="field" unique="true" /> <property name="code" access="field" unique="true" />

View file

@ -12,7 +12,6 @@
<component name="infoComponent" class="org.libreplan.business.orders.entities.InfoComponent"> <component name="infoComponent" class="org.libreplan.business.orders.entities.InfoComponent">
<property name="name" access="field" /> <property name="name" access="field" />
<property name="description" access="field" type="text" /> <property name="description" access="field" type="text" />
<property name="code" access="field"/>
</component> </component>
<property name="startAsDaysFromBeginning" <property name="startAsDaysFromBeginning"
column="start_as_days_from_beginning" /> column="start_as_days_from_beginning" />

View file

@ -22,7 +22,6 @@
package org.libreplan.business.test.planner.entities; package org.libreplan.business.test.planner.entities;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.getCurrentArguments; import static org.easymock.EasyMock.getCurrentArguments;
import static org.easymock.EasyMock.isA; import static org.easymock.EasyMock.isA;
@ -778,7 +777,7 @@ public class GenericResourceAllocationTest {
givenGenericResourceAllocationForTask(task); givenGenericResourceAllocationForTask(task);
givenWorkersWithLoads(8, 6, 2); givenWorkersWithLoads(8, 6, 2);
IntraDayDate end = ResourceAllocation.allocating( IntraDayDate end = ResourceAllocation.allocating(
singletonList(ResourcesPerDayModification.create( Arrays.asList(ResourcesPerDayModification.create(
genericResourceAllocation, genericResourceAllocation,
ResourcesPerDay.amount(new BigDecimal(1)), workers))) ResourcesPerDay.amount(new BigDecimal(1)), workers)))
.untilAllocating(hours(12)); .untilAllocating(hours(12));
@ -798,7 +797,7 @@ public class GenericResourceAllocationTest {
givenGenericResourceAllocationForTask(task); givenGenericResourceAllocationForTask(task);
givenWorkersWithLoads(8, 2, 6); givenWorkersWithLoads(8, 2, 6);
IntraDayDate end = ResourceAllocation.allocating( IntraDayDate end = ResourceAllocation.allocating(
singletonList(ResourcesPerDayModification.create( Arrays.asList(ResourcesPerDayModification.create(
genericResourceAllocation, ResourcesPerDay.amount(1), genericResourceAllocation, ResourcesPerDay.amount(1),
workers))).untilAllocating(hours(16)); workers))).untilAllocating(hours(16));
assertThat(end.getDate(), equalTo(start.plusDays(2))); assertThat(end.getDate(), equalTo(start.plusDays(2)));

View file

@ -412,12 +412,11 @@ public class UntilFillingHoursAllocatorTest {
givenSpecificAllocations(ResourcesPerDay.amount(1), ResourcesPerDay givenSpecificAllocations(ResourcesPerDay.amount(1), ResourcesPerDay
.amount(1)); .amount(1));
ResourceAllocation.allocating(allocations).untilAllocating(hours(64)); ResourceAllocation.allocating(allocations).untilAllocating(hours(64));
ResourceAllocation<?> generic = allocations.get(0) ResourceAllocation<?> firstSpecific = allocations.get(0)
.getBeingModified(); .getBeingModified();
ResourceAllocation<?> firstSpecific = allocations.get(1) ResourceAllocation<?> secondSpecific = allocations.get(1)
.getBeingModified();
ResourceAllocation<?> secondSpecific = allocations.get(2)
.getBeingModified(); .getBeingModified();
ResourceAllocation<?> generic = allocations.get(2).getBeingModified();
assertThat(generic.getAssignments(), haveHours(16, 16)); assertThat(generic.getAssignments(), haveHours(16, 16));
assertThat(firstSpecific.getAssignments(), haveHours(8, 8)); assertThat(firstSpecific.getAssignments(), haveHours(8, 8));
assertThat(secondSpecific.getAssignments(), haveHours(8, 8)); assertThat(secondSpecific.getAssignments(), haveHours(8, 8));

View file

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>org.libreplan</groupId> <groupId>org.libreplan</groupId>
<artifactId>libreplan</artifactId> <artifactId>libreplan</artifactId>
<version>1.2.2</version> <version>1.2.3</version>
</parent> </parent>
<artifactId>libreplan-webapp</artifactId> <artifactId>libreplan-webapp</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
@ -126,6 +126,9 @@
<copy todir="src/main/webapp/help/nl" failonerror="false"> <copy todir="src/main/webapp/help/nl" failonerror="false">
<fileset dir="../doc/src/user/en/html"/> <fileset dir="../doc/src/user/en/html"/>
</copy> </copy>
<copy todir="src/main/webapp/help/pl" failonerror="false">
<fileset dir="../doc/src/user/en/html"/>
</copy>
</tasks> </tasks>
</configuration> </configuration>
</execution> </execution>
@ -434,5 +437,10 @@
<groupId>org.jgrapht</groupId> <groupId>org.jgrapht</groupId>
<artifactId>jgrapht-jdk1.5</artifactId> <artifactId>jgrapht-jdk1.5</artifactId>
</dependency> </dependency>
<!-- jqPlot -->
<dependency>
<groupId>br.com.digilabs.jqplot</groupId>
<artifactId>jqplot4java</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View file

@ -0,0 +1,16 @@
# Locale for completedEstimatedHours.jrxml
title = Raport godzin
subtitle = Zrealizowane szacowane godziny
order = Projekt \:
reference = Data referencyjna \:
criteria = Kryteria \:
labels = Etykiety \:
headers.column1 = Nazwa
headers.column2 = Wszystkie godziny
headers.column2.column1 = Szacowany
headers.column2.column2 = Planowany
headers.column3 = Godziny do tej pory
headers.column3.column1 = Planowany
headers.column3.column2 = Realny
page = strona
of = z

View file

@ -0,0 +1,11 @@
# Locale for hoursWorkedPerWorkerReportInAMonth.jrxml
title = Raport pracy
subtitle = Raport pracy wed\u0142ug zasobów w miesi\u0105cu
parameters.year = Rok\:
parameters.month = Miesi\u0105c\:
headers.column1 = Nazwa
headers.column2 = Godziny
total.hours = Wszystkie godziny\:
note1 = Brak raportów pracy dla zaznaczonych zasobów w tym zakresie wyszukiwania.
page = strona
of = z

View file

@ -9,8 +9,8 @@
<parameter name="labels" class="java.lang.String"/> <parameter name="labels" class="java.lang.String"/>
<field name="workerName" class="java.lang.String"/> <field name="workerName" class="java.lang.String"/>
<field name="date" class="java.util.Date"/> <field name="date" class="java.util.Date"/>
<field name="clockStart" class="java.util.Date"/> <field name="clockStart" class="java.lang.String"/>
<field name="clockFinish" class="java.util.Date"/> <field name="clockFinish" class="java.lang.String"/>
<field name="self" class="org.libreplan.business.reports.dtos.HoursWorkedPerResourceDTO"/> <field name="self" class="org.libreplan.business.reports.dtos.HoursWorkedPerResourceDTO"/>
<field name="effort" class="org.libreplan.business.workingday.EffortDuration"/> <field name="effort" class="org.libreplan.business.workingday.EffortDuration"/>
<field name="orderElementCode" class="java.lang.String"/> <field name="orderElementCode" class="java.lang.String"/>
@ -343,7 +343,7 @@
<rightPen lineWidth="1.0"/> <rightPen lineWidth="1.0"/>
</box> </box>
<textElement textAlignment="Center" verticalAlignment="Middle"/> <textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression class="java.util.Date"><![CDATA[$F{clockFinish}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$F{clockFinish}]]></textFieldExpression>
</textField> </textField>
<textField isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="116" y="0" width="70" height="30"/> <reportElement x="116" y="0" width="70" height="30"/>
@ -355,7 +355,7 @@
<rightPen lineWidth="1.0"/> <rightPen lineWidth="1.0"/>
</box> </box>
<textElement textAlignment="Center" verticalAlignment="Middle"/> <textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression class="java.util.Date"><![CDATA[$F{clockStart}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$F{clockStart}]]></textFieldExpression>
</textField> </textField>
<textField isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="0" y="0" width="116" height="15"/> <reportElement x="0" y="0" width="116" height="15"/>

View file

@ -0,0 +1,18 @@
# Locale for hoursWorkedPerWorkerReport.jrxml
title = Raport pracy
subtitle = Przepracowane godziny wed\u0142ug zasobów
date.start = Data rozpocz\u0119cia\:
date.end = Data zako\u0144czenia\:
criteria = Kryteria\:
labels = Etykiety\:
headers.column1 = Start
headers.column2 = Zako\u0144czenie
headers.column3 = Godziny
headers.column4 = Kod/nazwa zadania
headers.column5 = Pola tekstowe
headers.column6 = Etykiety
total.day = Wszystkie godziny wed\u0142ug dnia\:
total.worker = Wszystkie godziny wed\u0142ug pracownika\:
note1 = Nie ma raportów pracy dla zaznaczonych zasobów w zakresie wyszukiwania.
page = strona
of = z

View file

@ -7,10 +7,9 @@
<parameter name="logo" class="java.lang.String"/> <parameter name="logo" class="java.lang.String"/>
<parameter name="criteria" class="java.lang.String"/> <parameter name="criteria" class="java.lang.String"/>
<parameter name="labels" class="java.lang.String"/> <parameter name="labels" class="java.lang.String"/>
<parameter name="currencySymbol" class="java.lang.String"/>
<field name="workerName" class="java.lang.String"/> <field name="workerName" class="java.lang.String"/>
<field name="date" class="java.util.Date"/> <field name="date" class="java.util.Date"/>
<field name="clockStart" class="java.util.Date"/>
<field name="clockFinish" class="java.util.Date"/>
<field name="numHours" class="java.math.BigDecimal"/> <field name="numHours" class="java.math.BigDecimal"/>
<field name="orderElementCode" class="java.lang.String"/> <field name="orderElementCode" class="java.lang.String"/>
<field name="descriptionValues" class="java.lang.String"/> <field name="descriptionValues" class="java.lang.String"/>
@ -90,12 +89,12 @@
</textElement> </textElement>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumTotalHours}]]></textFieldExpression> <textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumTotalHours}]]></textFieldExpression>
</textField> </textField>
<textField pattern="###0.00 €;-###0.00 €"> <textField>
<reportElement x="422" y="2" width="119" height="20"/> <reportElement x="422" y="2" width="119" height="20"/>
<textElement textAlignment="Right" verticalAlignment="Middle"> <textElement textAlignment="Right" verticalAlignment="Middle">
<font isBold="true"/> <font isBold="true"/>
</textElement> </textElement>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumTotalCosts}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$V{sumTotalCosts}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField> </textField>
</band> </band>
</groupFooter> </groupFooter>
@ -137,10 +136,10 @@
<textElement textAlignment="Right" verticalAlignment="Middle"/> <textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumHoursPerTask}]]></textFieldExpression> <textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumHoursPerTask}]]></textFieldExpression>
</textField> </textField>
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="422" y="2" width="119" height="20"/> <reportElement x="422" y="2" width="119" height="20"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/> <textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumCostsPerTask}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$V{sumCostsPerTask}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField> </textField>
</band> </band>
</groupFooter> </groupFooter>
@ -230,10 +229,10 @@
</groupHeader> </groupHeader>
<groupFooter> <groupFooter>
<band height="28"> <band height="28">
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="422" y="2" width="119" height="20"/> <reportElement x="422" y="2" width="119" height="20"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/> <textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumCosts}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$V{sumCosts}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField> </textField>
<textField> <textField>
<reportElement x="71" y="2" width="258" height="20"/> <reportElement x="71" y="2" width="258" height="20"/>
@ -266,20 +265,20 @@
</groupHeader> </groupHeader>
<groupFooter> <groupFooter>
<band height="15"> <band height="15">
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="423" y="0" width="119" height="14"/> <reportElement x="423" y="0" width="119" height="14"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/> <textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumCostsPerWorkerandCost}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$V{sumCostsPerWorkerandCost}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField> </textField>
<textField pattern="###0.00 h"> <textField pattern="###0.00 h">
<reportElement x="330" y="0" width="93" height="14"/> <reportElement x="330" y="0" width="93" height="14"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/> <textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumHoursPerWorkerandCost}]]></textFieldExpression> <textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumHoursPerWorkerandCost}]]></textFieldExpression>
</textField> </textField>
<textField pattern="###0.00 €/h;-###0.00 €/h" isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="252" y="0" width="78" height="14"/> <reportElement x="252" y="0" width="78" height="14"/>
<textElement textAlignment="Right"/> <textElement textAlignment="Right"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{costPerHour}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$F{costPerHour}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol} + "/h"]]></textFieldExpression>
</textField> </textField>
<textField isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="110" y="0" width="141" height="14"/> <reportElement x="110" y="0" width="141" height="14"/>

View file

@ -1,17 +1,17 @@
# Locale for ordersCostPerResourcesReport.jrxml # Locale for ordersCostPerResourcesReport.jrxml
title = Project report title = Informe del proyecto
subtitle = Costs by Resource subtitle = Costes por recurso
date.start = Starting date: date.start = Fecha de inicio:
date.end = Ending date: date.end = Fecha de fin:
criteria = Criteria : criteria = Criterios:
labels = Labels : labels = Etiquetas:
headers.column1 = Type of hours headers.column1 = Tipo de horas
headers.column2 = Date headers.column2 = Fecha
headers.column3 = Salary headers.column3 = Salario
headers.column4 = Hours headers.column4 = Horas
headers.column5 = Costs headers.column5 = Costes
total.task = Total per task: total.task = Total por tarea:
total.worker = Total per worker: total.worker = Total por trabajador:
total = Project Total: total = Total por proyecto:
page = page page = página
of = of of = de

View file

@ -0,0 +1,17 @@
# Locale for ordersCostPerResourcesReport.jrxml
title = Raport projektu
subtitle = Koszty wed\u0142ug zasobu
date.start = Data rozpocz\u0119cia\:
date.end = Data zako\u0144czenia\:
criteria = Kryteria \:
labels = Etykiety \:
headers.column1 = Typ godzin
headers.column2 = Data
headers.column3 = Wynagrodzenie
headers.column4 = Godziny
headers.column5 = Koszty
total.task = Ogó\u0142em na dzie\u0144\:
total.worker = Ogó\u0142em na pracownika\:
total = Ca\u0142kowity projekt\:
page = strona
of = z

View file

@ -0,0 +1,27 @@
# Locale for schedulingProgressPerOrderReport.jrxml
title = Raport post\u0119pu
subtitle = Harmonogram post\u0119pu na projekt
tipo = Typ post\u0119pu\:
order = Projekty\:
date.start = Data rozpocz\u0119cia.
date.end = Data zako\u0144czenia\:
date.reference = Data referencyjna\:
headers.column1 = Wszystkie godziny
headers.column1.column1 = Szacowany
headers.column1.column2 = Planowany
headers.column2 = Post\u0119p
headers.column2.column1 = Mierzony
headers.column2.column2 = Kalkulacja
headers.column2.column3 = Planowany
headers.column3 = Godziny do tej pory
headers.column3.column1 = Planowany
headers.column3.column2 = Realny
headers.column4 = Ró\u017cnica
headers.column4.column1 = Koszt
headers.column4.column2 = Planowany
headers.column4.column3 = Wska\u017anik kosztów
headers.column4.column4 = Planowany wska\u017anik
note1 = Zaznaczony typ post\u0119pu nie jest dost\u0119pny dla tego projektu.
note2 = U\u017cywany rozpowszechniany typ procesu.
page = strona
of = z

View file

@ -5,6 +5,7 @@
<parameter name="endingDate" class="java.util.Date"/> <parameter name="endingDate" class="java.util.Date"/>
<parameter name="status" class="java.lang.String"/> <parameter name="status" class="java.lang.String"/>
<parameter name="logo" class="java.lang.String"/> <parameter name="logo" class="java.lang.String"/>
<parameter name="currencySymbol" class="java.lang.String"/>
<field name="status" class="java.lang.String"/> <field name="status" class="java.lang.String"/>
<field name="code" class="java.lang.String"/> <field name="code" class="java.lang.String"/>
<field name="name" class="java.lang.String"/> <field name="name" class="java.lang.String"/>
@ -156,7 +157,7 @@
<textField isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="434" y="14" width="72" height="15"/> <reportElement x="434" y="14" width="72" height="15"/>
<textElement textAlignment="Center" verticalAlignment="Middle"/> <textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumTotalPricePerDay}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$V{sumTotalPricePerDay}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField> </textField>
</band> </band>
</groupFooter> </groupFooter>
@ -291,7 +292,7 @@
<rightPen lineWidth="1.0"/> <rightPen lineWidth="1.0"/>
</box> </box>
<textElement textAlignment="Center" verticalAlignment="Middle"/> <textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{totalPrice}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$F{totalPrice}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField> </textField>
<textField isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="390" y="0" width="65" height="73"/> <reportElement x="390" y="0" width="65" height="73"/>
@ -303,7 +304,7 @@
<rightPen lineWidth="1.0"/> <rightPen lineWidth="1.0"/>
</box> </box>
<textElement textAlignment="Center" verticalAlignment="Middle"/> <textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{unitPrice}]]></textFieldExpression> <textFieldExpression class="java.lang.String"><![CDATA[$F{unitPrice}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField> </textField>
<textField isBlankWhenNull="true"> <textField isBlankWhenNull="true">
<reportElement x="520" y="0" width="60" height="73"> <reportElement x="520" y="0" width="60" height="73">

View file

@ -0,0 +1,17 @@
# Locale for timeLineRequiredMaterial.jrxml
title = Materia\u0142y
subtitle = Linia czasowa materia\u0142ów.
date.start = Data rozpocz\u0119cia\:
date.end = Data zako\u0144czenia\:
status = Status\:
headers.title = Dzie\u0144
headers.column1 = Materia\u0142
headers.column2 = Projekt - Zadanie
headers.column3 = Dost\u0119pno\u015b\u0107
headers.column4 = Jednostki
headers.column5 = Cena jednostkowa
headers.column6 = Cena
headers.column7 = Status
headers.total = Ca\u0142kowita cena za dzie\u0144\:
page = strona
of = z

View file

@ -0,0 +1,28 @@
# Locale for workingArrangementPerOrderReport.jrxml
title = Raport projektu
subtitle = Stan planowania zada\u0144.
order = Projekt\:
status = Status\:
name = Nazwa.
code = Kod\:
criteria = Kryteria \:
labels = Etykiety \:
headers1.column1 = Data rozpocz\u0119cia
headers1.column1.column1 = Szacowany
headers1.column1.column2 = Pierwszy raport
headers1.column2 = Data zako\u0144czenia
headers1.column2.column1 = Szacowany
headers1.column2.column2 = Ostatni raport
headers1.column2.column3 = Ostateczny termin
headers1.column3 = Post\u0119p
headers1.column4 = Status
headers1.column5 = Ostateczny termin
headers2.title = Zale\u017cno\u015bci.
headers2.column1 = Nazwa
headers2.column2 = Kod
headers2.column3 = Typ
headers2.column4 = Post\u0119p
overrun = przekroczenia
intime = W czasie.
page = strona
of = z

View file

@ -0,0 +1,24 @@
# Locale for workingProgressPerTaskReport.jrxml
title = Raport post\u0119pu
subtitle = Post\u0119p pracy wed\u0142ug zadania
order = Projekt
reference = Data odniesienia\:
criteria = Kryteria \:
labels = Etykiety \:
headers.column1 = Wszystkie godziny
headers.column1.column1 = Szacowany
headers.column1.column2 = Planowany
headers.column2 = Post\u0119p
headers.column2.column1 = Mierzony
headers.column2.column2 = Kalkulacja
headers.column2.column3 = Planowany
headers.column3 = Godziny do tej pory
headers.column3.column1 = Planowany
headers.column3.column2 = Realny
headers.column4 = Ró\u017cnica
headers.column4.column1 = Koszt
headers.column4.column2 = Planowany
headers.column4.column3 = Wska\u017anik kosztów
headers.column4.column4 = Planowany wska\u017anik
page = strona
of = z

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -836,4 +836,28 @@ public class ConfigurationController extends GenericForwardComposer {
.setAllowToGatherUsageStatsEnabled(allowToGatherUsageStatsEnabled); .setAllowToGatherUsageStatsEnabled(allowToGatherUsageStatsEnabled);
} }
public Set<String> getCurrencies() {
return configurationModel.getCurrencies();
}
public ListitemRenderer getCurrencyRenderer() {
return new ListitemRenderer() {
@Override
public void render(Listitem item, Object data) throws Exception {
String currencyCode = (String) data;
item.setLabel(currencyCode + " - "
+ configurationModel.getCurrencySymbol(currencyCode));
item.setValue(currencyCode);
}
};
}
public String getSelectedCurrency() {
return configurationModel.getCurrencyCode();
}
public void setSelectedCurrency(String currencyCode) {
configurationModel.setCurrency(currencyCode);
}
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -25,12 +25,16 @@ import static org.libreplan.web.I18nHelper._;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Currency;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import org.apache.commons.lang.StringUtils;
import org.libreplan.business.calendars.daos.IBaseCalendarDAO; import org.libreplan.business.calendars.daos.IBaseCalendarDAO;
import org.libreplan.business.calendars.entities.BaseCalendar; import org.libreplan.business.calendars.entities.BaseCalendar;
import org.libreplan.business.common.daos.IConfigurationDAO; import org.libreplan.business.common.daos.IConfigurationDAO;
@ -66,6 +70,8 @@ public class ConfigurationModel implements IConfigurationModel {
private Map<EntityNameEnum, List<EntitySequence>> entitySequences = new HashMap<EntityNameEnum, List<EntitySequence>>(); private Map<EntityNameEnum, List<EntitySequence>> entitySequences = new HashMap<EntityNameEnum, List<EntitySequence>>();
private static Map<String, String> currencies = getAllCurrencies();
@Autowired @Autowired
private IConfigurationDAO configurationDAO; private IConfigurationDAO configurationDAO;
@ -557,4 +563,39 @@ public class ConfigurationModel implements IConfigurationModel {
.setAllowToGatherUsageStatsEnabled(allowToGatherUsageStatsEnabled); .setAllowToGatherUsageStatsEnabled(allowToGatherUsageStatsEnabled);
} }
private static Map<String, String> getAllCurrencies() {
Map<String, String> currencies = new TreeMap<String, String>();
for (Locale locale : Locale.getAvailableLocales()) {
if (StringUtils.isNotBlank(locale.getCountry())) {
Currency currency = Currency.getInstance(locale);
currencies.put(currency.getCurrencyCode(),
currency.getSymbol(locale));
}
}
return currencies;
}
@Override
public Set<String> getCurrencies() {
return currencies.keySet();
}
@Override
public String getCurrencySymbol(String currencyCode) {
return currencies.get(currencyCode);
}
@Override
public String getCurrencyCode() {
return configuration.getCurrencyCode();
}
@Override
public void setCurrency(String currencyCode) {
if (configuration != null) {
configuration.setCurrencyCode(currencyCode);
configuration.setCurrencySymbol(currencies.get(currencyCode));
}
}
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -22,6 +22,7 @@
package org.libreplan.web.common; package org.libreplan.web.common;
import java.util.List; import java.util.List;
import java.util.Set;
import org.libreplan.business.calendars.entities.BaseCalendar; import org.libreplan.business.calendars.entities.BaseCalendar;
import org.libreplan.business.common.entities.EntityNameEnum; import org.libreplan.business.common.entities.EntityNameEnum;
@ -153,4 +154,13 @@ public interface IConfigurationModel {
void setAllowToGatherUsageStatsEnabled( void setAllowToGatherUsageStatsEnabled(
boolean allowToGatherUsageStatsEnabled); boolean allowToGatherUsageStatsEnabled);
Set<String> getCurrencies();
String getCurrencySymbol(String currencyCode);
String getCurrencyCode();
void setCurrency(String currencyCode);
} }

View file

@ -24,7 +24,6 @@ package org.libreplan.web.common;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper._;
import java.util.ConcurrentModificationException; import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -125,9 +124,4 @@ public abstract class IntegrationEntityModel implements IIntegrationEntityModel
return entitySequenceDAO; return entitySequenceDAO;
} }
public Date getCurrentExpiringDate() {
// TODO Auto-generated method stub
return null;
}
} }

View file

@ -482,7 +482,11 @@ public class TemplateModel implements ITemplateModel {
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public boolean isUserAdmin() { public boolean isUserAdmin() {
return UserUtil.getUserFromSession().isAdministrator(); User user = UserUtil.getUserFromSession();
if(user == null) {
return false;
}
return user.isAdministrator();
} }
@Override @Override

View file

@ -24,6 +24,7 @@ package org.libreplan.web.common;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper._;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
@ -31,6 +32,9 @@ import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.libreplan.business.common.Configuration;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.common.Registry;
import org.zkoss.ganttz.util.ComponentsFinder; import org.zkoss.ganttz.util.ComponentsFinder;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Event;
@ -62,6 +66,12 @@ public class Util {
private static final Log LOG = LogFactory.getLog(Util.class); private static final Log LOG = LogFactory.getLog(Util.class);
/**
* Special chars from {@link DecimalFormat} class.
*/
private static final String[] DECIMAL_FORMAT_SPECIAL_CHARS = { "0", ",",
".", "\u2030", "%", "#", ";", "-" };
private Util() { private Util() {
} }
@ -629,4 +639,55 @@ public class Util {
} }
} }
/**
* Gets currency symbol from {@link Configuration} object.
*
* @return Currency symbol configured in the application
*/
public static String getCurrencySymbol() {
return Registry.getTransactionService().runOnReadOnlyTransaction(
new IOnTransaction<String>() {
@Override
public String execute() {
return Registry.getConfigurationDAO()
.getConfiguration().getCurrencySymbol();
}
});
}
/**
* Returns the value using the money format, that means, 2 figures for the
* decimal part and concatenating the currency symbol from
* {@link Configuration} object.
*/
public static String addCurrencySymbol(BigDecimal value) {
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat
.getInstance();
decimalFormat.applyPattern(getMoneyFormat());
return decimalFormat.format(value);
}
/**
* Gets money format for a {@link Decimalbox} using 2 figures for the
* decimal part and concatenating the currency symbol
*
* @return Format for a {@link Decimalbox} <code>###.##</code> plus currency
* symbol
*/
public static String getMoneyFormat() {
return "###.## " + escapeDecimalFormatSpecialChars(getCurrencySymbol());
}
/**
* Escapes special chars used in {@link DecimalFormat} to define the number
* format that appear in the <code>currencySymbol</code>.
*/
private static String escapeDecimalFormatSpecialChars(String currencySymbol) {
for (String specialChar : DECIMAL_FORMAT_SPECIAL_CHARS) {
currencySymbol = currencySymbol.replace(specialChar, "'"
+ specialChar + "'");
}
return currencySymbol;
}
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -53,9 +53,15 @@ import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.api.Listbox; import org.zkoss.zul.api.Listbox;
/** /**
* {@link Bandbox} allowing to choose more than one element from the drop down
* list separating them by "<code>;</code>".<br />
*
* When an element is selected {@link Events.ON_CHANGE} event over this
* component is launched.
*
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com> * @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class BandboxMultipleSearch extends HtmlMacroComponent { public class BandboxMultipleSearch extends HtmlMacroComponent {
@ -168,6 +174,7 @@ public class BandboxMultipleSearch extends HtmlMacroComponent {
} }
} }
bandbox.close(); bandbox.close();
Events.postEvent(Events.ON_CHANGE, this, null);
} }
private void searchMultipleFilters() { private void searchMultipleFilters() {

View file

@ -0,0 +1,50 @@
/*
* 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.web.common.components.finders;
import org.libreplan.business.resources.entities.Resource;
/**
* Diferent filters for {@link Resource}.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/
public enum ResourceFilterEnumByResourceAndCriterion implements IFilterEnum {
RESOURCE(_("Resource")), CRITERION(_("Criterion"));
/**
* Forces to mark the string as needing translation
*/
private static String _(String string) {
return string;
}
private String description;
private ResourceFilterEnumByResourceAndCriterion(String description) {
this.description = description;
}
public String toString() {
return this.description;
}
}

View file

@ -0,0 +1,184 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2012 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.web.common.components.finders;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import org.apache.commons.lang.StringUtils;
import org.libreplan.business.hibernate.notification.PredefinedDatabaseSnapshots;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.CriterionType;
import org.libreplan.business.resources.entities.Resource;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Implements all the methods needed to search the different criteria to filter
* the {@link Resource}s.<br />
* It provides the following criteria to filter: {@link Resource} and
* {@link Criterion}.
*
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/
public class ResourceMultipleFiltersFinderByResourceAndCriterion extends MultipleFiltersFinder {
@Autowired
private PredefinedDatabaseSnapshots databaseSnapshots;
protected ResourceMultipleFiltersFinderByResourceAndCriterion() {
}
@Override
public List<FilterPair> getFirstTenFilters() {
getListMatching().clear();
fillWithFirstTenFiltersResources();
fillWithFirstTenFiltersCriterions();
addNoneFilter();
return getListMatching();
}
private List<FilterPair> fillWithFirstTenFiltersResources() {
Map<Class<?>, List<Resource>> mapResources = getMapResources();
Iterator<Class<?>> iteratorClass = mapResources.keySet().iterator();
while (iteratorClass.hasNext() && getListMatching().size() < 10) {
Class<?> className = iteratorClass.next();
for (int i = 0; getListMatching().size() < 10
&& i < mapResources.get(className).size(); i++) {
Resource resource = mapResources.get(className).get(i);
addResource(className, resource);
}
}
return getListMatching();
}
private Map<Class<?>, List<Resource>> getMapResources() {
return databaseSnapshots.snapshotMapResources();
}
private void addResource(Class<?> className, Resource resource) {
String pattern = resource.getName();
getListMatching().add(
new FilterPair(ResourceFilterEnumByResourceAndCriterion.RESOURCE, className
.getSimpleName(), pattern, resource));
}
private List<FilterPair> fillWithFirstTenFiltersCriterions() {
SortedMap<CriterionType, List<Criterion>> mapCriterions = getMapCriterions();
Iterator<CriterionType> iteratorCriterionType = mapCriterions.keySet()
.iterator();
while (iteratorCriterionType.hasNext() && getListMatching().size() < 10) {
CriterionType type = iteratorCriterionType.next();
for (int i = 0; getListMatching().size() < 10
&& i < mapCriterions.get(type).size(); i++) {
Criterion criterion = mapCriterions.get(type).get(i);
addCriterion(type, criterion);
}
}
return getListMatching();
}
private SortedMap<CriterionType, List<Criterion>> getMapCriterions() {
return databaseSnapshots.snapshotCriterionsMap();
}
private void addCriterion(CriterionType type, Criterion criterion) {
String pattern = criterion.getName() + " ( " + type.getName() + " )";
getListMatching().add(
new FilterPair(ResourceFilterEnumByResourceAndCriterion.CRITERION, type
.getResource().toLowerCase(), pattern, criterion));
}
public List<FilterPair> getMatching(String filter) {
getListMatching().clear();
if ((filter != null) && (!filter.isEmpty())) {
filter = StringUtils.deleteWhitespace(filter.toLowerCase());
searchInResources(filter);
searchInCriterionTypes(filter);
}
addNoneFilter();
return getListMatching();
}
private void searchInResources(String filter) {
Map<Class<?>, List<Resource>> mapResources = databaseSnapshots
.snapshotMapResources();
for (Class<?> className : mapResources.keySet()) {
for (Resource resource : mapResources.get(className)) {
String name = StringUtils.deleteWhitespace(resource.getName()
.toLowerCase());
if (name.contains(filter)) {
addResource(className, resource);
if ((filter.length() < 3) && (getListMatching().size() > 9)) {
return;
}
}
}
}
}
private void searchInCriterionTypes(String filter) {
boolean limited = (filter.length() < 3);
for (CriterionType type : getMapCriterions().keySet()) {
String name = StringUtils.deleteWhitespace(type.getName()
.toLowerCase());
if (name.contains(filter)) {
setFilterPairCriterionType(type, limited);
} else {
searchInCriterions(type, filter);
}
}
}
private void searchInCriterions(CriterionType type, String filter) {
List<Criterion> list = getMapCriterions().get(type);
if (list == null) {
return;
}
for (Criterion criterion : list) {
String name = StringUtils.deleteWhitespace(criterion.getName()
.toLowerCase());
if (name.contains(filter)) {
addCriterion(type, criterion);
if ((filter.length() < 3) && (getListMatching().size() > 9)) {
return;
}
}
}
}
private void setFilterPairCriterionType(CriterionType type, boolean limited) {
List<Criterion> list = getMapCriterions().get(type);
if (list == null) {
return;
}
for (Criterion criterion : list) {
addCriterion(type, criterion);
if ((limited) && (getListMatching().size() > 9)) {
return;
}
}
}
}

View file

@ -35,11 +35,11 @@ import org.springframework.beans.factory.annotation.Autowired;
/** /**
* Implements all the methods needed to search the criterion to filter the * Implements all the methods needed to search the criterion to filter the
* resources. Provides multiples criterions to filter like {@link Criterion}, * resources. Provides multiples criteria to filter like {@link Criterion} or
* {@link Category} or filter by name or nif. * {@link CostCategory}.
*
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com> * @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/ */
public class ResourcesMultipleFiltersFinder extends MultipleFiltersFinder { public class ResourcesMultipleFiltersFinder extends MultipleFiltersFinder {
@Autowired @Autowired

View file

@ -79,7 +79,7 @@ public abstract class TemplateFinder<T extends OrderElementTemplate> extends
} }
protected String extractStringFor(T template) { protected String extractStringFor(T template) {
return template.getName() + " (" + template.getCode() + ")"; return template.getName();
} }
@Override @Override
@ -92,7 +92,6 @@ public abstract class TemplateFinder<T extends OrderElementTemplate> extends
protected void generateColumnsForRenderer(Listitem item, T template) { protected void generateColumnsForRenderer(Listitem item, T template) {
final Listcell codeCell = new Listcell(); final Listcell codeCell = new Listcell();
codeCell.setLabel(template.getCode());
codeCell.setParent(item); codeCell.setParent(item);
codeCell.setStyle("width:200px"); codeCell.setStyle("width:200px");

View file

@ -1,91 +0,0 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 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.components.finders;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.libreplan.business.hibernate.notification.PredefinedDatabaseSnapshots;
import org.libreplan.business.resources.entities.Worker;
import org.springframework.beans.factory.annotation.Autowired;
public class WorkerMultipleFiltersFinder extends MultipleFiltersFinder {
@Autowired
private PredefinedDatabaseSnapshots databaseSnapshots;
private IFilterEnum workerFilterEnum = new IFilterEnum() {
@Override
public String toString() {
return "Resource ( Worker )";
}
};
/**
* Forces to mark the string as needing translation
*/
private static String _(String string) {
return string;
}
@Override
public List<FilterPair> getFirstTenFilters() {
getListMatching().clear();
Iterator<Worker> iteratorWorker = getListWorkers().iterator();
while(iteratorWorker.hasNext() && getListMatching().size() < 10) {
Worker worker = iteratorWorker.next();
getListMatching().add(
new FilterPair(workerFilterEnum, worker.getDescription(),
worker));
}
addNoneFilter();
return getListMatching();
}
private List<Worker> getListWorkers() {
return databaseSnapshots.snapshotListWorkers();
}
@Override
public List<FilterPair> getMatching(String filter) {
getListMatching().clear();
if ((filter != null) && (!filter.isEmpty())) {
filter = StringUtils.deleteWhitespace(filter.toLowerCase());
searchInWorkers(filter);
}
addNoneFilter();
return getListMatching();
}
private void searchInWorkers(String filter) {
for (Worker worker : getListWorkers()) {
String name = StringUtils.deleteWhitespace(worker.getDescription()
.toLowerCase());
if(name.contains(filter)) {
getListMatching().add(new FilterPair(
workerFilterEnum, worker.getShortDescription(), worker));
}
}
}
}

View file

@ -38,10 +38,8 @@ import org.libreplan.business.costcategories.entities.CostCategory;
import org.libreplan.business.costcategories.entities.HourCost; import org.libreplan.business.costcategories.entities.HourCost;
import org.libreplan.business.costcategories.entities.TypeOfWorkHours; import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
import org.libreplan.web.common.BaseCRUDController; import org.libreplan.web.common.BaseCRUDController;
import org.libreplan.web.common.ConstraintChecker;
import org.libreplan.web.common.Level; import org.libreplan.web.common.Level;
import org.libreplan.web.common.Util; import org.libreplan.web.common.Util;
import org.libreplan.web.util.ValidationExceptionPrinter;
import org.libreplan.web.workreports.WorkReportCRUDController; import org.libreplan.web.workreports.WorkReportCRUDController;
import org.zkoss.ganttz.util.ComponentsFinder; import org.zkoss.ganttz.util.ComponentsFinder;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
@ -305,6 +303,7 @@ public class CostCategoryCRUDController extends BaseCRUDController<CostCategory>
Decimalbox boxCost = new Decimalbox(); Decimalbox boxCost = new Decimalbox();
bindDecimalboxCost(boxCost, (HourCost) row.getValue()); bindDecimalboxCost(boxCost, (HourCost) row.getValue());
boxCost.setConstraint("no empty:" + _("cannot be null or empty")); boxCost.setConstraint("no empty:" + _("cannot be null or empty"));
boxCost.setFormat(Util.getMoneyFormat());
row.appendChild(boxCost); row.appendChild(boxCost);
} }

View file

@ -141,4 +141,13 @@ public class TypeOfWorkHoursCRUDController extends BaseCRUDController<TypeOfWork
protected boolean beforeDeleting(TypeOfWorkHours typeOfWorkHours) { protected boolean beforeDeleting(TypeOfWorkHours typeOfWorkHours) {
return !isReferencedByOtherEntities(typeOfWorkHours); return !isReferencedByOtherEntities(typeOfWorkHours);
} }
public String getCurrencySymbol() {
return Util.getCurrencySymbol();
}
public String getMoneyFormat() {
return Util.getMoneyFormat();
}
} }

View file

@ -0,0 +1,123 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2010-2012 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.web.dashboard;
import static org.libreplan.web.I18nHelper._;
import java.math.BigDecimal;
import java.util.Date;
import org.joda.time.LocalDate;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.web.common.Util;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Label;
/**
* @author Diego Pino García <dpino@igalia.com>
*
* Contains operations for calculations in the CostStatus table in the
* Dashboard view
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class CostStatusController extends GenericForwardComposer {
private ICostStatusModel costStatusModel;
// Cost Variance
public Label lblCV;
// Cost Performance Index
public Label lblCPI;
// Budget at Completion
public Label lblBAC;
// Estimate at Completion
public Label lblEAC;
// Variance at Completion
public Label lblVAC;
@Override
public void doAfterCompose(org.zkoss.zk.ui.Component comp) throws Exception {
super.doAfterCompose(comp);
self.setAttribute("controller", this);
Util.createBindingsFor(self);
}
public void setOrder(Order order) {
costStatusModel.setCurrentOrder(order);
}
public void render() {
LocalDate today = LocalDate.fromDateFields(new Date());
BigDecimal budgetedCost = costStatusModel
.getBudgetedCostWorkPerformedAt(today);
BigDecimal actualCost = costStatusModel
.getActualCostWorkPerformedAt(today);
BigDecimal costVariance = costStatusModel.getCostVariance(budgetedCost,
actualCost);
setCostVariance(costVariance);
BigDecimal costPerformanceIndex = costStatusModel
.getCostPerformanceIndex(budgetedCost, actualCost);
setCostPerformanceIndex(costPerformanceIndex);
BigDecimal budgetAtCompletion = costStatusModel.getBudgetAtCompletion();
setBudgetAtCompletion(budgetAtCompletion);
BigDecimal estimateAtCompletion = costStatusModel
.getEstimateAtCompletion(budgetAtCompletion,
costPerformanceIndex);
setEstimateAtCompletion(estimateAtCompletion);
BigDecimal varianceAtCompletion = costStatusModel
.getVarianceAtCompletion(budgetAtCompletion,
estimateAtCompletion);
setVarianceAtCompletion(varianceAtCompletion);
}
private void setEstimateAtCompletion(BigDecimal value) {
lblEAC.setValue(String.format("%.2f %%", value.doubleValue()));
}
private void setCostPerformanceIndex(BigDecimal value) {
lblCPI.setValue(String.format("%.2f %%", value.doubleValue()));
}
private void setBudgetAtCompletion(BigDecimal value) {
lblBAC.setValue(String.format(_("%s h"), value.toString()));
}
private void setCostVariance(BigDecimal value) {
lblCV.setValue(String.format(_("%s h"), value.toString()));
}
private void setVarianceAtCompletion(BigDecimal value) {
lblVAC.setValue(String.format(_("%s h"), value.toString()));
}
}

View file

@ -0,0 +1,107 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2010-2012 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.web.dashboard;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.planner.entities.IOrderEarnedValueCalculator;
import org.libreplan.web.planner.order.OrderPlanningModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* @author Diego Pino García <ltilve@igalia.com>
*
* Model for UI operations related to CostStatus in Dashboard view
*
* FIXME: This Model contains several operations for calculating 'Earned
* Value' measures related with cost. The code for calculating the basic
* measures: BCWP, ACWP and BCWS is copied from
* {@link OrderPlanningModel}. At this moment this code cannot be reused
* as it's coupled with the logic for displaying the 'Earned Value'
* chart. We may consider to refactor this code in the future.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class CostStatusModel implements ICostStatusModel {
@Autowired
private IOrderEarnedValueCalculator earnedValueCalculator;
private Order order;
public CostStatusModel() {
}
@Override
@Transactional(readOnly = true)
public BigDecimal getActualCostWorkPerformedAt(LocalDate date) {
return earnedValueCalculator.getActualCostWorkPerformedAt(order, date);
}
@Override
public BigDecimal getCostPerformanceIndex(BigDecimal budgetedCost,
BigDecimal actualCost) {
return earnedValueCalculator.getCostPerformanceIndex(budgetedCost,
actualCost);
}
@Override
public BigDecimal getCostVariance(BigDecimal budgetedCost,
BigDecimal actualCost) {
return earnedValueCalculator.getCostVariance(budgetedCost, actualCost);
}
@Override
public BigDecimal getEstimateAtCompletion(BigDecimal budgetAtCompletion,
BigDecimal costPerformanceIndex) {
return earnedValueCalculator.getEstimateAtCompletion(
budgetAtCompletion, costPerformanceIndex);
}
@Override
public BigDecimal getVarianceAtCompletion(BigDecimal budgetAtCompletion,
BigDecimal estimateAtCompletion) {
return budgetAtCompletion.subtract(estimateAtCompletion);
}
@Override
public void setCurrentOrder(Order order) {
this.order = order;
}
@Override
public BigDecimal getBudgetAtCompletion() {
return earnedValueCalculator.getBudgetAtCompletion(order);
}
@Override
public BigDecimal getBudgetedCostWorkPerformedAt(LocalDate date) {
return earnedValueCalculator
.getBudgetedCostWorkPerformedAt(order, date);
}
}

View file

@ -21,29 +21,40 @@ package org.libreplan.web.dashboard;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper._;
import java.awt.Color;
import java.awt.Font;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Iterator; import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.libreplan.business.orders.entities.Order; import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.planner.entities.TaskStatusEnum;
import org.libreplan.web.common.Util; import org.libreplan.web.common.Util;
import org.libreplan.web.dashboard.DashboardModel.Interval;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.CategoryModel;
import org.zkoss.zul.Chart;
import org.zkoss.zul.Div; import org.zkoss.zul.Div;
import org.zkoss.zul.PieModel; import org.zkoss.zul.Grid;
import org.zkoss.zul.SimpleCategoryModel; import org.zkoss.zul.Label;
import org.zkoss.zul.SimplePieModel;
import org.zkoss.zul.Window; import org.zkoss.zul.Window;
import br.com.digilabs.jqplot.Chart;
import br.com.digilabs.jqplot.JqPlotUtils;
import br.com.digilabs.jqplot.chart.BarChart;
import br.com.digilabs.jqplot.chart.PieChart;
import br.com.digilabs.jqplot.elements.Serie;
/** /**
* Controller for dashboardfororder view
* @author Nacho Barrientos <nacho@igalia.com> * @author Nacho Barrientos <nacho@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
*
* Controller for dashboardfororder view
*/ */
@Component @Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -53,12 +64,10 @@ public class DashboardController extends GenericForwardComposer {
private Window dashboardWindow; private Window dashboardWindow;
private Chart progressKPIglobalProgressChart; private Grid gridTasksSummary;
private Chart progressKPItaskStatusChart; private Grid gridMarginWithDeadline;
private Chart progressKPItaskDeadlineViolationStatusChart;
private Chart timeKPImarginWithDeadlineChart; private org.zkoss.zk.ui.Component costStatus;
private Chart timeKPIEstimationAccuracyChart;
private Chart timeKPILagInTaskCompletionChart;
private Div projectDashboardChartsDiv; private Div projectDashboardChartsDiv;
private Div projectDashboardNoTasksWarningDiv; private Div projectDashboardNoTasksWarningDiv;
@ -69,171 +78,415 @@ public class DashboardController extends GenericForwardComposer {
@Override @Override
public void doAfterCompose(org.zkoss.zk.ui.Component comp) throws Exception { public void doAfterCompose(org.zkoss.zk.ui.Component comp) throws Exception {
super.doAfterCompose(comp); super.doAfterCompose(comp);
this.dashboardWindow = (Window)comp; this.dashboardWindow = (Window) comp;
self.setAttribute("controller", this);
Util.createBindingsFor(this.dashboardWindow); Util.createBindingsFor(this.dashboardWindow);
} }
public void setCurrentOrder(Order order) { public void setCurrentOrder(Order order) {
dashboardModel.setCurrentOrder(order); dashboardModel.setCurrentOrder(order);
if(dashboardModel.tasksAvailable()) { if (dashboardModel.tasksAvailable()) {
this.reloadCharts(); showCharts();
} else { } else {
this.hideChartsAndShowWarningMessage(); hideCharts();
} }
if (this.dashboardWindow != null) { if (this.dashboardWindow != null) {
Util.reloadBindings(this.dashboardWindow); renderGlobalProgress();
renderTaskStatus();
renderTaskCompletationLag();
renderTasksSummary();
renderDeadlineViolation();
renderMarginWithDeadline();
renderEstimationAccuracy();
renderCostStatus(order);
} }
} }
private void reloadCharts() { private void renderCostStatus(Order order) {
generateProgressKPIglobalProgressChart(); CostStatusController costStatusController = getCostStatusController();
generateProgressKPItaskStatusChart(); costStatusController.setOrder(order);
generateProgressKPItaskDeadlineViolationStatusChart(); costStatusController.render();
generateTimeKPImarginWithDeadlineChart();
generateTimeKPIEstimationAccuracyChart();
generateTimeKPILagInTaskCompletionChart();
} }
private void hideChartsAndShowWarningMessage() { private CostStatusController getCostStatusController() {
return (CostStatusController) costStatus.getAttribute("controller");
}
private void renderMarginWithDeadline() {
marginWithDeadline(dashboardModel.getMarginWithDeadLine());
absoluteMarginWithDeadline(dashboardModel
.getAbsoluteMarginWithDeadLine());
}
private void marginWithDeadline(BigDecimal value) {
Label label = (Label) gridMarginWithDeadline
.getFellowIfAny("lblRelative");
if (label != null) {
if (value != null) {
label.setValue(String.format(_("%.2f %%"),
value.doubleValue() * 100));
} else {
label.setValue(_("<No deadline>"));
}
}
}
private void absoluteMarginWithDeadline(Integer value) {
Label label = (Label) gridMarginWithDeadline
.getFellowIfAny("lblAbsolute");
if (label != null) {
if (value != null) {
label.setValue(String.format(_("%d days"), value));
} else {
label.setValue(_("<No deadline>"));
}
}
}
private void renderDeadlineViolation() {
final String divId = "deadline-violation";
PieChart<Number> pieChart = new PieChart<Number>(
_("Deadline Violation"));
pieChart.addValue(_("On schedule"),
dashboardModel.getPercentageOfOnScheduleTasks());
pieChart.addValue(_("Violated deadline"),
dashboardModel.getPercentageOfTasksWithViolatedDeadline());
pieChart.addValue(_("No deadline"),
dashboardModel.getPercentageOfTasksWithNoDeadline());
renderChart(pieChart, divId);
}
private void renderChart(Chart<?> chart, String divId) {
String jsCode = JqPlotUtils.createJquery(chart, divId);
Clients.evalJavaScript(jsCode);
}
private void renderTaskCompletationLag() {
final String divId = "task-completation-lag";
BarChart<Integer> barChart;
barChart = new BarChart<Integer>("Task Completation Lead/Lag");
barChart.setFillZero(true);
barChart.setHighlightMouseDown(true);
barChart.setStackSeries(false);
barChart.setBarMargin(30);
barChart.addSeries(new Serie("Tasks"));
TaskCompletationData taskCompletationData = TaskCompletationData
.create(dashboardModel);
barChart.setTicks(taskCompletationData.getTicks());
barChart.addValues(taskCompletationData.getValues());
barChart.getAxes().getXaxis()
.setLabel(_("Number of Days / Days Interval"));
renderChart(barChart, divId);
}
private void renderEstimationAccuracy() {
final String divId = "estimation-accuracy";
BarChart<Integer> barChart;
barChart = new BarChart<Integer>("Estimation Accuracy");
barChart.setFillZero(true);
barChart.setHighlightMouseDown(true);
barChart.setStackSeries(false);
barChart.setBarMargin(30);
barChart.addSeries(new Serie("Tasks"));
EstimationAccuracy estimationAccuracyData = EstimationAccuracy
.create(dashboardModel);
barChart.setTicks(estimationAccuracyData.getTicks());
barChart.addValues(estimationAccuracyData.getValues());
barChart.getAxes().getXaxis()
.setLabel(_("Number of Tasks / % Deviation"));
renderChart(barChart, divId);
}
private void renderTasksSummary() {
Map<TaskStatusEnum, Integer> taskStatus = dashboardModel
.calculateTaskStatus();
taskStatus("lblTasksFinished", taskStatus.get(TaskStatusEnum.FINISHED));
taskStatus("lblTasksBlocked", taskStatus.get(TaskStatusEnum.BLOCKED));
taskStatus("lblTasksInProgress",
taskStatus.get(TaskStatusEnum.IN_PROGRESS));
taskStatus("lblTasksReadyToStart",
taskStatus.get(TaskStatusEnum.READY_TO_START));
}
private void taskStatus(String key, Integer value) {
Label label = (Label) gridTasksSummary.getFellowIfAny(key);
if (label != null) {
label.setValue(String.format(_("%d tasks"), value));
}
}
private void renderTaskStatus() {
final String divId = "task-status";
PieChart<Number> taskStatus = new PieChart<Number>(_("Task Status"));
taskStatus.addValue(_("Finished"),
dashboardModel.getPercentageOfFinishedTasks());
taskStatus.addValue(_("In progress"),
dashboardModel.getPercentageOfInProgressTasks());
taskStatus.addValue(_("Ready to start"),
dashboardModel.getPercentageOfReadyToStartTasks());
taskStatus.addValue(_("Blocked"),
dashboardModel.getPercentageOfBlockedTasks());
renderChart(taskStatus, divId);
}
private void renderGlobalProgress() {
GlobalProgress globalProgress = GlobalProgress.create();
// Current values
globalProgress.current(GlobalProgress.CRITICAL_PATH_DURATION,
dashboardModel.getCriticalPathProgressByDuration());
globalProgress.current(GlobalProgress.CRITICAL_PATH_HOURS,
dashboardModel.getCriticalPathProgressByNumHours());
globalProgress.current(GlobalProgress.ALL_TASKS_HOURS,
dashboardModel.getAdvancePercentageByHours());
// Expected values
globalProgress.expected(GlobalProgress.CRITICAL_PATH_DURATION,
dashboardModel.getExpectedCriticalPathProgressByDuration());
globalProgress.expected(GlobalProgress.CRITICAL_PATH_HOURS,
dashboardModel.getExpectedCriticalPathProgressByNumHours());
globalProgress.expected(GlobalProgress.ALL_TASKS_HOURS,
dashboardModel.getExpectedAdvancePercentageByHours());
globalProgress.render();
}
private void showCharts() {
projectDashboardChartsDiv.setVisible(true);
projectDashboardNoTasksWarningDiv.setVisible(false);
}
private void hideCharts() {
projectDashboardChartsDiv.setVisible(false); projectDashboardChartsDiv.setVisible(false);
projectDashboardNoTasksWarningDiv.setVisible(true); projectDashboardNoTasksWarningDiv.setVisible(true);
} }
private void generateTimeKPILagInTaskCompletionChart() { /**
CategoryModel categoryModel; *
categoryModel = refreshTimeKPILagInTaskCompletionCategoryModel(); * @author Diego Pino García <dpino@igalia.com>
Font labelFont = new Font("serif", Font.PLAIN, 10); *
timeKPILagInTaskCompletionChart.setXAxisTickFont(labelFont); */
Color[] seriesColorMappings = {Color.BLUE}; static class GlobalProgress {
timeKPILagInTaskCompletionChart.setAttribute("series-color-mappings",
seriesColorMappings);
timeKPILagInTaskCompletionChart.setModel(categoryModel);
}
private void generateTimeKPIEstimationAccuracyChart() { public static final String ALL_TASKS_HOURS = _("All tasks (hours)");
CategoryModel categoryModel;
categoryModel = refreshTimeKPIEstimationAccuracyCategoryModel(); public static final String CRITICAL_PATH_HOURS = _("Critical path (hours)");
Font labelFont = new Font("serif", Font.PLAIN, 10);
timeKPIEstimationAccuracyChart.setXAxisTickFont(labelFont); public static final String CRITICAL_PATH_DURATION = _("Critical path (duration)");
Color[] seriesColorMappings = {Color.BLUE};
timeKPIEstimationAccuracyChart.setAttribute("series-color-mappings", private final Map<String, BigDecimal> current = new LinkedHashMap<String, BigDecimal>();
seriesColorMappings);
timeKPIEstimationAccuracyChart.setModel(categoryModel); private final Map<String, BigDecimal> expected = new LinkedHashMap<String, BigDecimal>();
}
private static List<Series> series = new ArrayList<Series>() {
{
add(Series.create(_("Current"), "#33c"));
add(Series.create(_("Expected"), "#c33"));
}
};
private GlobalProgress() {
private void generateTimeKPImarginWithDeadlineChart() {
CategoryModel categoryModel;
categoryModel = refreshTimeKPImarginWithDeadlineCategoryModel();
if (categoryModel == null) { // Project has no deadline set.
timeKPImarginWithDeadlineChart.setVisible(false);
return;
} }
timeKPImarginWithDeadlineChart.setAttribute("range-axis-lower-bound",
new Double(-3.0)); public void current(String key, BigDecimal value) {
timeKPImarginWithDeadlineChart.setAttribute("range-axis-upper-bound", current.put(key, value);
new Double(3.0));
Color[] seriesColorMappings = new Color[1];
if(dashboardModel.getMarginWithDeadLine().compareTo(BigDecimal.ZERO) >= 0) {
seriesColorMappings[0] = Color.GREEN;
} else {
seriesColorMappings[0] = Color.RED;
} }
timeKPImarginWithDeadlineChart.setAttribute("series-color-mappings",
seriesColorMappings);
timeKPImarginWithDeadlineChart.setModel(categoryModel);
}
private void generateProgressKPItaskStatusChart() { public void expected(String key, BigDecimal value) {
PieModel model = refreshProgressKPItaskStatusPieModel(); expected.put(key, value);
progressKPItaskStatusChart.setModel(model);
}
private void generateProgressKPItaskDeadlineViolationStatusChart() {
PieModel model = refreshProgressKPItaskDeadlieViolationStatusPieModel();
progressKPItaskDeadlineViolationStatusChart.setModel(model);
}
private void generateProgressKPIglobalProgressChart() {
CategoryModel categoryModel;
categoryModel = refreshProgressKPIglobalProgressCategoryModel();
progressKPIglobalProgressChart.setAttribute("range-axis-lower-bound",
new Double(0.0));
progressKPIglobalProgressChart.setAttribute("range-axis-upper-bound",
new Double(100.0));
progressKPIglobalProgressChart.setModel(categoryModel);
}
private PieModel refreshProgressKPItaskStatusPieModel() {
PieModel model = new SimplePieModel();
model.setValue(_("Finished"), dashboardModel.getPercentageOfFinishedTasks());
model.setValue(_("In progress"), dashboardModel.getPercentageOfInProgressTasks());
model.setValue(_("Ready to start"), dashboardModel.getPercentageOfReadyToStartTasks());
model.setValue(_("Blocked"), dashboardModel.getPercentageOfBlockedTasks());
return model;
}
private PieModel refreshProgressKPItaskDeadlieViolationStatusPieModel() {
PieModel model = new SimplePieModel();
model.setValue(_("On schedule"), dashboardModel.getPercentageOfOnScheduleTasks());
model.setValue(_("Violated deadline"), dashboardModel.getPercentageOfTasksWithViolatedDeadline());
model.setValue(_("No deadline"), dashboardModel.getPercentageOfTasksWithNoDeadline());
return model;
}
private CategoryModel refreshProgressKPIglobalProgressCategoryModel() {
CategoryModel result = new SimpleCategoryModel();
result.setValue(_("Current"), _("All tasks (hours)"),
dashboardModel.getAdvancePercentageByHours());
result.setValue(_("Expected"), _("All tasks (hours)"),
dashboardModel.getTheoreticalAdvancePercentageByHoursUntilNow());
result.setValue(_("Current"), _("Critical path (hours)"),
dashboardModel.getCriticalPathProgressByNumHours());
result.setValue(_("Expected"), _("Critical path (hours)"), dashboardModel
.getTheoreticalProgressByNumHoursForCriticalPathUntilNow());
result.setValue(_("Current"), _("Critical path (duration)"),
dashboardModel.getCriticalPathProgressByDuration());
result.setValue(_("Expected"), _("Critical path (duration)"),
dashboardModel.getTheoreticalProgressByDurationForCriticalPathUntilNow());
return result;
}
private CategoryModel refreshTimeKPImarginWithDeadlineCategoryModel() {
CategoryModel result = null;
BigDecimal marginWithDeadLine = dashboardModel.getMarginWithDeadLine();
if (marginWithDeadLine != null) {
result = new SimpleCategoryModel();
result.setValue(_("None"), _("Deviation"), marginWithDeadLine);
} }
return result;
public static GlobalProgress create() {
return new GlobalProgress();
}
public String getPercentages() {
return String.format("'[%s, %s]'",
jsonifyPercentages(current.values()),
jsonifyPercentages(expected.values()));
}
private String jsonifyPercentages(Collection<BigDecimal> array) {
List<String> result = new ArrayList<String>();
int i = 1;
for (BigDecimal each : array) {
result.add(String.format("[%.2f, %d]", each.doubleValue(), i++));
}
return String.format("[%s]", StringUtils.join(result, ","));
}
private String jsonify(Collection<?> list) {
Collection<String> result = new ArrayList<String>();
for (Object each : list) {
if (each.getClass() == String.class) {
result.add(String.format("\"%s\"", each.toString()));
} else {
result.add(String.format("%s", each.toString()));
}
}
return String.format("'[%s]'", StringUtils.join(result, ','));
}
public String getSeries() {
return jsonify(series);
}
/**
* The order of the ticks is taken from the keys in current
*
* @return
*/
public String getTicks() {
return jsonify(current.keySet());
}
public void render() {
String command = String.format(
"global_progress.render(%s, %s, %s);", getPercentages(),
getTicks(), getSeries());
Clients.evalJavaScript(command);
}
} }
private CategoryModel refreshTimeKPIEstimationAccuracyCategoryModel() { /**
CategoryModel result = new SimpleCategoryModel(); *
List<Double> values = dashboardModel.getFinishedTasksEstimationAccuracyHistogram(); * @author Diego Pino García <dpino@igalia.com>
Iterator<Double> it = values.iterator(); *
for(int ii= DashboardModel.EA_STRETCHES_MIN_VALUE; */
ii < DashboardModel.EA_STRETCHES_MAX_VALUE; static class Series {
ii += DashboardModel.EA_STRETCHES_PERCENTAGE_STEP) {
result.setValue(_("None"), _(String.valueOf(ii)), it.next()); private String label;
private String color;
private Series() {
} }
result.setValue(_("None"),
_(">"+DashboardModel.EA_STRETCHES_MAX_VALUE), public static Series create(String label) {
it.next()); Series series = new Series();
return result; series.label = label;
return series;
}
public static Series create(String label, String color) {
Series series = new Series();
series.label = label;
series.color = color;
return series;
}
@Override
public String toString() {
return String.format("{\"label\": \"%s\", \"color\": \"%s\"}",
label, color);
}
} }
private CategoryModel refreshTimeKPILagInTaskCompletionCategoryModel() { /**
CategoryModel result = new SimpleCategoryModel(); *
List<Double> values = dashboardModel.getLagInTaskCompletionHistogram(); * @author Diego Pino García<dpino@igalia.com>
Iterator<Double> it = values.iterator(); *
for(double ii= DashboardModel.LTC_STRETCHES_MIN_VALUE; */
ii < DashboardModel.LTC_STRETCHES_MAX_VALUE; static class TaskCompletationData {
ii += DashboardModel.LTC_STRETCHES_STEP) {
result.setValue(_("None"), _(String.valueOf(ii)), it.next()); private final IDashboardModel dashboardModel;
private Map<Interval, Integer> taskCompletationData;
private TaskCompletationData(IDashboardModel dashboardModel) {
this.dashboardModel = dashboardModel;
} }
result.setValue(_("None"),
_(">"+DashboardModel.LTC_STRETCHES_MAX_VALUE), public static TaskCompletationData create(IDashboardModel dashboardModel) {
it.next()); return new TaskCompletationData(dashboardModel);
return result; }
private Map<Interval, Integer> getData() {
if (taskCompletationData == null) {
taskCompletationData = dashboardModel
.calculateTaskCompletation();
}
return taskCompletationData;
}
public String[] getTicks() {
Set<Interval> intervals = getData().keySet();
String[] result = new String[intervals.size()];
int i = 0;
for (Interval each : intervals) {
result[i++] = each.toString();
}
return result;
}
public Collection<Integer> getValues() {
return getData().values();
}
} }
/**
*
* @author Diego Pino García<dpino@igalia.com>
*
*/
static class EstimationAccuracy {
private final IDashboardModel dashboardModel;
private Map<Interval, Integer> estimationAccuracyData;
private EstimationAccuracy(IDashboardModel dashboardModel) {
this.dashboardModel = dashboardModel;
}
public static EstimationAccuracy create(IDashboardModel dashboardModel) {
return new EstimationAccuracy(dashboardModel);
}
private Map<Interval, Integer> getData() {
if (estimationAccuracyData == null) {
estimationAccuracyData = dashboardModel
.calculateEstimationAccuracy();
}
return estimationAccuracyData;
}
public String[] getTicks() {
Set<Interval> intervals = getData().keySet();
String[] result = new String[intervals.size()];
int i = 0;
for (Interval each : intervals) {
result[i++] = each.toString();
}
return result;
}
public Collection<Integer> getValues() {
return getData().values();
}
}
} }

View file

@ -22,10 +22,14 @@ package org.libreplan.web.dashboard;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.MathContext; import java.math.MathContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.joda.time.Days; import org.joda.time.Days;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
@ -64,14 +68,14 @@ public class DashboardModel implements IDashboardModel {
public static double LTC_STRETCHES_MIN_VALUE = 0; public static double LTC_STRETCHES_MIN_VALUE = 0;
public static double LTC_STRETCHES_MAX_VALUE = 0; public static double LTC_STRETCHES_MAX_VALUE = 0;
private Order currentOrder; private Order currentOrder;
private Integer taskCount = null; private Integer taskCount = null;
private Map<TaskStatusEnum, BigDecimal> taskStatusStats; private final Map<TaskStatusEnum, BigDecimal> taskStatusStats;
private Map<TaskDeadlineViolationStatusEnum, BigDecimal> taskDeadlineViolationStatusStats; private final Map<TaskDeadlineViolationStatusEnum, BigDecimal> taskDeadlineViolationStatusStats;
private List<Double> taskEstimationAccuracyHistogram; private List<Double> taskEstimationAccuracyHistogram;
private BigDecimal marginWithDeadLine; private BigDecimal marginWithDeadLine;
private Integer absoluteMarginWithDeadLine;
private List<Double> lagInTaskCompletionHistogram; private List<Double> lagInTaskCompletionHistogram;
public DashboardModel() { public DashboardModel() {
@ -81,10 +85,11 @@ public class DashboardModel implements IDashboardModel {
TaskDeadlineViolationStatusEnum.class); TaskDeadlineViolationStatusEnum.class);
} }
@Override
public void setCurrentOrder(Order order) { public void setCurrentOrder(Order order) {
this.currentOrder = order; this.currentOrder = order;
this.taskCount = null; this.taskCount = null;
if(tasksAvailable()) { if (tasksAvailable()) {
this.calculateTaskStatusStatistics(); this.calculateTaskStatusStatistics();
this.calculateTaskViolationStatusStatistics(); this.calculateTaskViolationStatusStatistics();
this.calculateMarginWithDeadLine(); this.calculateMarginWithDeadLine();
@ -94,91 +99,110 @@ public class DashboardModel implements IDashboardModel {
} }
/* Progress KPI: "Number of tasks by status" */ /* Progress KPI: "Number of tasks by status" */
@Override
public BigDecimal getPercentageOfFinishedTasks() { public BigDecimal getPercentageOfFinishedTasks() {
return taskStatusStats.get(TaskStatusEnum.FINISHED); return taskStatusStats.get(TaskStatusEnum.FINISHED);
} }
@Override
public BigDecimal getPercentageOfInProgressTasks() { public BigDecimal getPercentageOfInProgressTasks() {
return taskStatusStats.get(TaskStatusEnum.IN_PROGRESS); return taskStatusStats.get(TaskStatusEnum.IN_PROGRESS);
} }
@Override
public BigDecimal getPercentageOfReadyToStartTasks() { public BigDecimal getPercentageOfReadyToStartTasks() {
return taskStatusStats.get(TaskStatusEnum.READY_TO_START); return taskStatusStats.get(TaskStatusEnum.READY_TO_START);
} }
@Override
public BigDecimal getPercentageOfBlockedTasks() { public BigDecimal getPercentageOfBlockedTasks() {
return taskStatusStats.get(TaskStatusEnum.BLOCKED); return taskStatusStats.get(TaskStatusEnum.BLOCKED);
} }
/* Progress KPI: "Deadline violation" */ /* Progress KPI: "Deadline violation" */
@Override
public BigDecimal getPercentageOfOnScheduleTasks() { public BigDecimal getPercentageOfOnScheduleTasks() {
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.ON_SCHEDULE); return taskDeadlineViolationStatusStats
.get(TaskDeadlineViolationStatusEnum.ON_SCHEDULE);
} }
@Override
public BigDecimal getPercentageOfTasksWithViolatedDeadline() { public BigDecimal getPercentageOfTasksWithViolatedDeadline() {
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED); return taskDeadlineViolationStatusStats
.get(TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED);
} }
@Override
public BigDecimal getPercentageOfTasksWithNoDeadline() { public BigDecimal getPercentageOfTasksWithNoDeadline() {
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.NO_DEADLINE); return taskDeadlineViolationStatusStats
.get(TaskDeadlineViolationStatusEnum.NO_DEADLINE);
} }
/* Progress KPI: "Global Progress of the Project" */ /* Progress KPI: "Global Progress of the Project" */
public BigDecimal getAdvancePercentageByHours(){ @Override
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); public BigDecimal getAdvancePercentageByHours() {
if (this.getRootTask() == null) { TaskGroup rootTask = (TaskGroup) getRootTask();
if (rootTask == null) {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
BigDecimal ratio = rootAsTaskGroup.getProgressAllByNumHours(); return asPercentage(rootTask.getProgressAllByNumHours());
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
} }
public BigDecimal getTheoreticalAdvancePercentageByHoursUntilNow(){ private BigDecimal asPercentage(BigDecimal value) {
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); return value != null ? value.multiply(BigDecimal.valueOf(100))
if (this.getRootTask() == null) { : BigDecimal.ZERO;
}
@Override
public BigDecimal getExpectedAdvancePercentageByHours() {
TaskGroup rootTask = (TaskGroup) getRootTask();
if (rootTask == null) {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByNumHoursForAllTasksUntilNow(); return asPercentage(rootTask
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); .getTheoreticalProgressByNumHoursForAllTasksUntilNow());
} }
@Override
public BigDecimal getCriticalPathProgressByNumHours() { public BigDecimal getCriticalPathProgressByNumHours() {
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); TaskGroup rootTask = (TaskGroup) getRootTask();
if (this.getRootTask() == null) { if (rootTask == null) {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
BigDecimal ratio = rootAsTaskGroup.getCriticalPathProgressByNumHours(); return asPercentage(rootTask.getCriticalPathProgressByNumHours());
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
} }
public BigDecimal getTheoreticalProgressByNumHoursForCriticalPathUntilNow() { @Override
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); public BigDecimal getExpectedCriticalPathProgressByNumHours() {
if (this.getRootTask() == null) { TaskGroup rootTask = (TaskGroup) getRootTask();
if (rootTask == null) {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByNumHoursForCriticalPathUntilNow(); return asPercentage(rootTask
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); .getTheoreticalProgressByNumHoursForCriticalPathUntilNow());
} }
@Override
public BigDecimal getCriticalPathProgressByDuration() { public BigDecimal getCriticalPathProgressByDuration() {
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); TaskGroup rootTask = (TaskGroup) getRootTask();
if (this.getRootTask() == null) { if (rootTask == null) {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
BigDecimal ratio = rootAsTaskGroup.getCriticalPathProgressByDuration(); return asPercentage(rootTask.getCriticalPathProgressByDuration());
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
} }
public BigDecimal getTheoreticalProgressByDurationForCriticalPathUntilNow() { @Override
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); public BigDecimal getExpectedCriticalPathProgressByDuration() {
if (this.getRootTask() == null) { TaskGroup rootTask = (TaskGroup) getRootTask();
if (rootTask == null) {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByDurationForCriticalPathUntilNow(); return asPercentage(rootTask
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); .getTheoreticalProgressByDurationForCriticalPathUntilNow());
} }
/* Time KPI: Margin with deadline */ /* Time KPI: Margin with deadline */
@Override
public BigDecimal getMarginWithDeadLine() { public BigDecimal getMarginWithDeadLine() {
return this.marginWithDeadLine; return this.marginWithDeadLine;
} }
@ -207,7 +231,35 @@ public class DashboardModel implements IDashboardModel {
BigDecimal.ROUND_HALF_EVEN); BigDecimal.ROUND_HALF_EVEN);
} }
@Override
public Integer getAbsoluteMarginWithDeadLine() {
if (absoluteMarginWithDeadLine == null) {
calculateAbsoluteMarginWithDeadLine();
}
return absoluteMarginWithDeadLine;
}
private void calculateAbsoluteMarginWithDeadLine() {
TaskElement rootTask = getRootTask();
Date deadline = currentOrder.getDeadline();
if (rootTask == null) {
throw new RuntimeException("Root task is null");
}
if (deadline == null) {
this.absoluteMarginWithDeadLine = null;
return;
}
absoluteMarginWithDeadLine = daysBetween(rootTask.getEndAsLocalDate(),
LocalDate.fromDateFields(deadline));
}
private int daysBetween(LocalDate start, LocalDate end) {
return Days.daysBetween(start, end).getDays();
}
/* Time KPI: Estimation accuracy */ /* Time KPI: Estimation accuracy */
@Override
public List<Double> getFinishedTasksEstimationAccuracyHistogram() { public List<Double> getFinishedTasksEstimationAccuracyHistogram() {
return this.taskEstimationAccuracyHistogram; return this.taskEstimationAccuracyHistogram;
} }
@ -216,21 +268,19 @@ public class DashboardModel implements IDashboardModel {
if (this.getRootTask() == null) { if (this.getRootTask() == null) {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
CalculateFinishedTasksEstimationDeviationVisitor visitor = CalculateFinishedTasksEstimationDeviationVisitor visitor = new CalculateFinishedTasksEstimationDeviationVisitor();
new CalculateFinishedTasksEstimationDeviationVisitor();
TaskElement rootTask = getRootTask(); TaskElement rootTask = getRootTask();
rootTask.acceptVisitor(visitor); rootTask.acceptVisitor(visitor);
List<Double> deviations = visitor.getDeviations(); List<Double> deviations = visitor.getDeviations();
// [-100, -90), [-90, -80), ..., [190, 200), [200, inf) // [-100, -90), [-90, -80), ..., [190, 200), [200, inf)
this.taskEstimationAccuracyHistogram = createHistogram( this.taskEstimationAccuracyHistogram = createHistogram(
EA_STRETCHES_MIN_VALUE, EA_STRETCHES_MIN_VALUE, EA_STRETCHES_MAX_VALUE,
EA_STRETCHES_MAX_VALUE, EA_STRETCHES_PERCENTAGE_STEP, deviations);
EA_STRETCHES_PERCENTAGE_STEP,
deviations);
} }
/* Time KPI: Lead/Lag in task completion */ /* Time KPI: Lead/Lag in task completion */
@Override
public List<Double> getLagInTaskCompletionHistogram() { public List<Double> getLagInTaskCompletionHistogram() {
return this.lagInTaskCompletionHistogram; return this.lagInTaskCompletionHistogram;
} }
@ -239,8 +289,7 @@ public class DashboardModel implements IDashboardModel {
if (this.getRootTask() == null) { if (this.getRootTask() == null) {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
CalculateFinishedTasksLagInCompletionVisitor visitor = CalculateFinishedTasksLagInCompletionVisitor visitor = new CalculateFinishedTasksLagInCompletionVisitor();
new CalculateFinishedTasksLagInCompletionVisitor();
TaskElement rootTask = getRootTask(); TaskElement rootTask = getRootTask();
rootTask.acceptVisitor(visitor); rootTask.acceptVisitor(visitor);
List<Double> deviations = visitor.getDeviations(); List<Double> deviations = visitor.getDeviations();
@ -253,45 +302,228 @@ public class DashboardModel implements IDashboardModel {
LTC_STRETCHES_MAX_VALUE = Collections.max(deviations); LTC_STRETCHES_MAX_VALUE = Collections.max(deviations);
} }
LTC_STRETCHES_STEP = (LTC_STRETCHES_MAX_VALUE - LTC_STRETCHES_MIN_VALUE) LTC_STRETCHES_STEP = (LTC_STRETCHES_MAX_VALUE - LTC_STRETCHES_MIN_VALUE)
/LTC_NUMBER_OF_INTERVALS; / LTC_NUMBER_OF_INTERVALS;
this.lagInTaskCompletionHistogram = createHistogram( this.lagInTaskCompletionHistogram = createHistogram(
LTC_STRETCHES_MIN_VALUE, LTC_STRETCHES_MIN_VALUE, LTC_STRETCHES_MAX_VALUE,
LTC_STRETCHES_MAX_VALUE, LTC_STRETCHES_STEP, deviations);
LTC_STRETCHES_STEP,
deviations);
} }
private List<Double> createHistogram(double lowBound, double highBound, private List<Double> createHistogram(double lowBound, double highBound,
double intervalStep, List<Double> values) { double intervalStep, List<Double> values) {
double variableRange = highBound - lowBound; double variableRange = highBound - lowBound;
/* TODO: What if highBound == lowBound? */ /* TODO: What if highBound == lowBound? */
int numberOfClasses = (int)(variableRange/intervalStep); int numberOfClasses = (int) (variableRange / intervalStep);
int[] classes = new int[numberOfClasses+1]; int[] classes = new int[numberOfClasses + 1];
for(Double value: values) { for (Double value : values) {
int index; int index;
if (value >= highBound) { if (value >= highBound) {
index = numberOfClasses; index = numberOfClasses;
} else { } else {
index = (int)(numberOfClasses * index = (int) (numberOfClasses * (((value.doubleValue() - lowBound)) / variableRange));
(((value.doubleValue() - lowBound))/variableRange));
} }
classes[index]++; classes[index]++;
} }
List<Double> histogram = new ArrayList<Double>(); List<Double> histogram = new ArrayList<Double>();
int numberOfConsideredTasks = values.size(); int numberOfConsideredTasks = values.size();
for (int numberOfElementsInClass: classes) { for (int numberOfElementsInClass : classes) {
Double relativeCount = new Double(0.0); Double relativeCount = new Double(0.0);
if (numberOfConsideredTasks > 0) { if (numberOfConsideredTasks > 0) {
relativeCount = new Double(1.0*numberOfElementsInClass/ relativeCount = new Double(1.0 * numberOfElementsInClass
numberOfConsideredTasks); / numberOfConsideredTasks);
} }
histogram.add(relativeCount); histogram.add(relativeCount);
} }
return histogram; return histogram;
} }
/**
* Calculates the task completation deviations for the current order
*
* All the deviations are groups in Interval.MAX_INTERVALS intervals of
* equal size. If the order contains just one single task then, the upper
* limit will be the deviation of the task + 3, and the lower limit will be
* deviation of the task - 2
*
* Each {@link Interval} contains the number of tasks that fit in that
* interval
*
* @return
*/
@Override
public Map<Interval, Integer> calculateTaskCompletation() {
Map<Interval, Integer> result = new LinkedHashMap<Interval, Integer>();
Double max, min;
// Get deviations of finished tasks, calculate max, min and delta
List<Double> deviations = getTaskLagDeviations();
if (deviations.isEmpty()) {
return result;
}
if (deviations.size() == 1) {
max = deviations.get(0).doubleValue() + 3;
min = deviations.get(0).doubleValue() - 2;
} else {
max = Collections.max(deviations);
min = Collections.min(deviations);
}
double delta = (max - min) / Interval.MAX_INTERVALS;
// Create MAX_INTERVALS
double from = min;
for (int i = 0; i < Interval.MAX_INTERVALS; i++) {
result.put(Interval.create(from, from + delta), Integer.valueOf(0));
from = from + delta;
}
// Construct map with number of tasks for each interval
final Set<Interval> intervals = result.keySet();
for (Double each : deviations) {
Interval interval = Interval.containingValue(intervals, each);
if (interval != null) {
Integer value = result.get(interval);
result.put(interval, value + 1);
}
}
return result;
}
private List<Double> getTaskLagDeviations() {
if (this.getRootTask() == null) {
throw new RuntimeException("Root task is null");
}
CalculateFinishedTasksLagInCompletionVisitor visitor = new CalculateFinishedTasksLagInCompletionVisitor();
TaskElement rootTask = getRootTask();
rootTask.acceptVisitor(visitor);
return visitor.getDeviations();
}
/**
* Calculates the estimation accuracy deviations for the current order
*
* All the deviations are groups in Interval.MAX_INTERVALS intervals of
* equal size. If the order contains just one single task then, the upper
* limit will be the deviation of the task + 30, and the lower limit will be
* deviation of the task - 20
*
* Each {@link Interval} contains the number of tasks that fit in that
* interval
*
* @return
*/
@Override
public Map<Interval, Integer> calculateEstimationAccuracy() {
Map<Interval, Integer> result = new LinkedHashMap<Interval, Integer>();
Double max, min;
// Get deviations of finished tasks, calculate max, min and delta
List<Double> deviations = getEstimationAccuracyDeviations();
if (deviations.isEmpty()) {
return result;
}
if (deviations.size() == 1) {
max = deviations.get(0).doubleValue() + 30;
min = deviations.get(0).doubleValue() - 20;
} else {
max = Collections.max(deviations);
min = Collections.min(deviations);
}
double delta = (max - min) / Interval.MAX_INTERVALS;
// Create MAX_INTERVALS
double from = min;
for (int i = 0; i < Interval.MAX_INTERVALS; i++) {
result.put(Interval.create(from, from + delta), Integer.valueOf(0));
from = from + delta;
}
// Construct map with number of tasks for each interval
final Set<Interval> intervals = result.keySet();
for (Double each : deviations) {
Interval interval = Interval.containingValue(intervals, each);
if (interval != null) {
Integer value = result.get(interval);
result.put(interval, value + 1);
}
}
return result;
}
private List<Double> getEstimationAccuracyDeviations() {
if (this.getRootTask() == null) {
throw new RuntimeException("Root task is null");
}
CalculateFinishedTasksEstimationDeviationVisitor visitor = new CalculateFinishedTasksEstimationDeviationVisitor();
TaskElement rootTask = getRootTask();
rootTask.acceptVisitor(visitor);
return visitor.getDeviations();
}
/**
*
* @author Diego Pino García<dpino@igalia.com>
*
*/
static class Interval {
public static final double MAX_INTERVALS = 6;
private double min;
private double max;
private Interval() {
}
public static Interval create(double min, double max) {
return new Interval(min, max);
}
private Interval(double min, double max) {
this.min = min;
this.max = max;
}
public static Interval copy(Interval interval) {
return new Interval(interval.min, interval.max);
}
public static Interval containingValue(Collection<Interval> intervals,
Double value) {
for (Interval each : intervals) {
if (each.includes(value)) {
return each;
}
}
return null;
}
private boolean includes(double value) {
return (value >= min) && (value <= max);
}
@Override
public String toString() {
return String.format("[%d, %d]", (int) Math.ceil(min),
(int) Math.ceil(max));
}
}
@Override
public Map<TaskStatusEnum, Integer> calculateTaskStatus() {
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
TaskElement rootTask = getRootTask();
if (this.getRootTask() == null) {
throw new RuntimeException("Root task is null");
}
resetTasksStatusInGraph();
rootTask.acceptVisitor(visitor);
return visitor.getTaskStatusData();
}
private void calculateTaskStatusStatistics() { private void calculateTaskStatusStatistics() {
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor(); AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
TaskElement rootTask = getRootTask(); TaskElement rootTask = getRootTask();
@ -311,7 +543,8 @@ public class DashboardModel implements IDashboardModel {
throw new RuntimeException("Root task is null"); throw new RuntimeException("Root task is null");
} }
rootTask.acceptVisitor(visitor); rootTask.acceptVisitor(visitor);
Map<TaskDeadlineViolationStatusEnum, Integer> count = visitor.getTaskDeadlineViolationStatusData(); Map<TaskDeadlineViolationStatusEnum, Integer> count = visitor
.getTaskDeadlineViolationStatusData();
mapAbsoluteValuesToPercentages(count, taskDeadlineViolationStatusStats); mapAbsoluteValuesToPercentages(count, taskDeadlineViolationStatusStats);
} }
@ -342,8 +575,9 @@ public class DashboardModel implements IDashboardModel {
} }
private int countTasksInAResultMap(Map<? extends Object, Integer> map) { private int countTasksInAResultMap(Map<? extends Object, Integer> map) {
/* It's only needed to count the number of tasks once /*
* each time setOrder is called. * It's only needed to count the number of tasks once each time setOrder
* is called.
*/ */
if (this.taskCount != null) { if (this.taskCount != null) {
return this.taskCount.intValue(); return this.taskCount.intValue();
@ -356,6 +590,7 @@ public class DashboardModel implements IDashboardModel {
return sum; return sum;
} }
@Override
public boolean tasksAvailable() { public boolean tasksAvailable() {
return getRootTask() != null; return getRootTask() != null;
} }

View file

@ -0,0 +1,60 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2010-2012 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.web.dashboard;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.libreplan.business.orders.entities.Order;
/**
*
* @author Diego Pino García <dpino@igalia.com>
*
*/
interface ICostStatusModel {
// Actual Cost Work Performed (ACWP)
BigDecimal getActualCostWorkPerformedAt(LocalDate date);
// Budget At Completion (BAC)
BigDecimal getBudgetAtCompletion();
// Budgeted Cost Work Performed (BCWP)
BigDecimal getBudgetedCostWorkPerformedAt(LocalDate date);
// Cost Performance Index (CPI)
BigDecimal getCostPerformanceIndex(BigDecimal budgetedCost,
BigDecimal actualCost);
// Cost Variance (CV)
BigDecimal getCostVariance(BigDecimal budgetedCost, BigDecimal actualCost);
// Estimate at Completion (EAC)
BigDecimal getEstimateAtCompletion(BigDecimal budgetAtCompletion,
BigDecimal costPerformanceIndex);
// Variance at Completion (VAC)
BigDecimal getVarianceAtCompletion(BigDecimal budgetAtCompletion,
BigDecimal estimateAtCompletion);
void setCurrentOrder(Order order);
}

View file

@ -21,8 +21,11 @@ package org.libreplan.web.dashboard;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map;
import org.libreplan.business.orders.entities.Order; import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.planner.entities.TaskStatusEnum;
import org.libreplan.web.dashboard.DashboardModel.Interval;
interface IDashboardModel { interface IDashboardModel {
@ -49,22 +52,31 @@ interface IDashboardModel {
/* Progress KPI: "Global Progress of the Project" */ /* Progress KPI: "Global Progress of the Project" */
BigDecimal getAdvancePercentageByHours(); BigDecimal getAdvancePercentageByHours();
BigDecimal getTheoreticalAdvancePercentageByHoursUntilNow(); BigDecimal getExpectedAdvancePercentageByHours();
BigDecimal getCriticalPathProgressByNumHours(); BigDecimal getCriticalPathProgressByNumHours();
BigDecimal getTheoreticalProgressByNumHoursForCriticalPathUntilNow(); BigDecimal getExpectedCriticalPathProgressByNumHours();
BigDecimal getCriticalPathProgressByDuration(); BigDecimal getCriticalPathProgressByDuration();
BigDecimal getTheoreticalProgressByDurationForCriticalPathUntilNow(); BigDecimal getExpectedCriticalPathProgressByDuration();
/* Time KPI: "Margin with deadline" */ /* Time KPI: "Margin with deadline" */
BigDecimal getMarginWithDeadLine(); BigDecimal getMarginWithDeadLine();
Integer getAbsoluteMarginWithDeadLine();
/* Time KPI: "Estimation accuracy" */ /* Time KPI: "Estimation accuracy" */
List<Double> getFinishedTasksEstimationAccuracyHistogram(); List<Double> getFinishedTasksEstimationAccuracyHistogram();
/* Time KPI: "Lead/Lag in task completion" */ /* Time KPI: "Lead/Lag in task completion" */
List<Double> getLagInTaskCompletionHistogram(); List<Double> getLagInTaskCompletionHistogram();
Map<TaskStatusEnum, Integer> calculateTaskStatus();
Map<Interval, Integer> calculateTaskCompletation();
Map<Interval, Integer> calculateEstimationAccuracy();
} }

View file

@ -554,4 +554,9 @@ public class MaterialsController extends
} }
} }
} }
public String getMoneyFormat() {
return Util.getMoneyFormat();
}
} }

View file

@ -159,4 +159,8 @@ public class AssignedHoursToOrderElementController extends
} }
} }
public String getCurrencySymbol() {
return Util.getCurrencySymbol();
}
} }

View file

@ -67,4 +67,8 @@ public class DetailsOrderElementController extends
return !orderElementModel.getOrderElement().isLeaf(); return !orderElementModel.getOrderElement().isLeaf();
} }
public String getMoneyFormat() {
return Util.getMoneyFormat();
}
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -33,6 +33,7 @@ import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.orders.entities.Order; import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderLineGroup; import org.libreplan.business.orders.entities.OrderLineGroup;
import org.libreplan.business.planner.entities.PositionConstraintType;
import org.libreplan.business.qualityforms.entities.QualityForm; import org.libreplan.business.qualityforms.entities.QualityForm;
import org.libreplan.business.resources.entities.Criterion; import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.resources.entities.CriterionType; import org.libreplan.business.resources.entities.CriterionType;
@ -48,6 +49,7 @@ import org.zkoss.zk.ui.Desktop;
* *
* @author Óscar González Fernández <ogonzalez@igalia.com> * @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Diego Pino García <dpino@igalia.com> * @author Diego Pino García <dpino@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
public interface IOrderModel extends IIntegrationEntityModel { public interface IOrderModel extends IIntegrationEntityModel {
@ -139,4 +141,6 @@ public interface IOrderModel extends IIntegrationEntityModel {
boolean alreadyExistsRepeatedEndDate(Date value); boolean alreadyExistsRepeatedEndDate(Date value);
boolean isAnyTaskWithConstraint(PositionConstraintType type);
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -51,6 +51,7 @@ import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.Order.SchedulingMode; import org.libreplan.business.orders.entities.Order.SchedulingMode;
import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderStatusEnum; import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.planner.entities.PositionConstraintType;
import org.libreplan.business.templates.entities.OrderTemplate; import org.libreplan.business.templates.entities.OrderTemplate;
import org.libreplan.business.users.entities.UserRole; import org.libreplan.business.users.entities.UserRole;
import org.libreplan.web.common.IMessagesForUser; import org.libreplan.web.common.IMessagesForUser;
@ -93,6 +94,7 @@ import org.zkoss.zul.Comboitem;
import org.zkoss.zul.ComboitemRenderer; import org.zkoss.zul.ComboitemRenderer;
import org.zkoss.zul.Constraint; import org.zkoss.zul.Constraint;
import org.zkoss.zul.Datebox; import org.zkoss.zul.Datebox;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Grid; import org.zkoss.zul.Grid;
import org.zkoss.zul.Hbox; import org.zkoss.zul.Hbox;
import org.zkoss.zul.Label; import org.zkoss.zul.Label;
@ -116,6 +118,7 @@ import org.zkoss.zul.api.Window;
* *
* @author Óscar González Fernández <ogonzalez@igalia.com> * @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com> * @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
@org.springframework.stereotype.Component @org.springframework.stereotype.Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -398,11 +401,45 @@ public class OrderCRUDController extends GenericForwardComposer {
return result; return result;
} }
private void setConstraintsFor(SchedulingMode mode) { private void setConstraintsFor(final SchedulingMode mode) {
initDate.setConstraint(mode == SchedulingMode.FORWARD ? "no empty" initDate.setConstraint(new Constraint() {
: null);
deadline.setConstraint(mode == SchedulingMode.BACKWARDS ? "no empty" @Override
: null); public void validate(Component comp, Object value)
throws WrongValueException {
if (value == null) {
if (mode == SchedulingMode.FORWARD) {
throw new WrongValueException(
comp,
_("Starting date cannot be empty in forward mode"));
}
if (orderModel
.isAnyTaskWithConstraint(PositionConstraintType.AS_SOON_AS_POSSIBLE)) {
throw new WrongValueException(comp,
_("Starting date cannot be empty because there is a task with constraint \"as soon as possible\""));
}
}
}
});
deadline.setConstraint(new Constraint() {
@Override
public void validate(Component comp, Object value)
throws WrongValueException {
if (value == null) {
if (mode == SchedulingMode.BACKWARDS) {
throw new WrongValueException(
comp,
_("Deadline cannot be empty in backwards mode"));
}
if (orderModel
.isAnyTaskWithConstraint(PositionConstraintType.AS_LATE_AS_POSSIBLE)) {
throw new WrongValueException(comp,
_("Deadline cannot be empty because there is a task with constraint \"as late as possible\""));
}
}
}
});
} }
private void changeFocusAccordingTo(SchedulingMode chosen) { private void changeFocusAccordingTo(SchedulingMode chosen) {
@ -1187,7 +1224,7 @@ public class OrderCRUDController extends GenericForwardComposer {
appendDate(row, order.getInitDate()); appendDate(row, order.getInitDate());
appendDate(row, order.getDeadline()); appendDate(row, order.getDeadline());
appendCustomer(row, order.getCustomer()); appendCustomer(row, order.getCustomer());
appendObject(row, order.getTotalBudget()); appendObject(row, Util.addCurrencySymbol(order.getTotalBudget()));
appendObject(row, order.getTotalHours()); appendObject(row, order.getTotalHours());
appendObject(row, _(order.getState().toString())); appendObject(row, _(order.getState().toString()));
appendOperations(row, order); appendOperations(row, order);
@ -1306,8 +1343,8 @@ public class OrderCRUDController extends GenericForwardComposer {
return orderModel.gettooltipText(order); return orderModel.gettooltipText(order);
} }
public void reloadTotalBudget(Label txtTotalBudget) { public void reloadTotalBudget(Decimalbox decimalboxTotalBudget) {
Util.reloadBindings(txtTotalBudget); Util.reloadBindings(decimalboxTotalBudget);
} }
/** /**
@ -1685,4 +1722,8 @@ public class OrderCRUDController extends GenericForwardComposer {
reloadGridAskedEndDates(); reloadGridAskedEndDates();
} }
public String getMoneyFormat() {
return Util.getMoneyFormat();
}
} }

View file

@ -393,6 +393,7 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
IOrderElementModel model = orderModel IOrderElementModel model = orderModel
.getOrderElementModel(currentOrderElement); .getOrderElementModel(currentOrderElement);
orderElementController.openWindow(model); orderElementController.openWindow(model);
updateNameFor(currentOrderElement);
updateHoursFor(currentOrderElement); updateHoursFor(currentOrderElement);
updateBudgetFor(currentOrderElement); updateBudgetFor(currentOrderElement);
} }
@ -619,6 +620,7 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
public void refreshRow(Treeitem item) { public void refreshRow(Treeitem item) {
try { try {
getRenderer().updateNameFor((OrderElement) item.getValue());
getRenderer().updateHoursFor((OrderElement) item.getValue()); getRenderer().updateHoursFor((OrderElement) item.getValue());
getRenderer().updateBudgetFor((OrderElement) item.getValue()); getRenderer().updateBudgetFor((OrderElement) item.getValue());
getRenderer().render(item, item.getValue()); getRenderer().render(item, item.getValue());
@ -742,4 +744,16 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
}; };
} }
@Override
protected INameHandler<OrderElement> getNameHandler() {
return new INameHandler<OrderElement>() {
@Override
public String getNameFor(OrderElement element) {
return element.getName();
}
};
}
} }

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2012 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify it under * 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 * the terms of the GNU Affero General Public License as published by the Free
@ -59,6 +59,7 @@ import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderLineGroup; import org.libreplan.business.orders.entities.OrderLineGroup;
import org.libreplan.business.planner.entities.IMoneyCostCalculator; import org.libreplan.business.planner.entities.IMoneyCostCalculator;
import org.libreplan.business.planner.entities.PositionConstraintType;
import org.libreplan.business.qualityforms.daos.IQualityFormDAO; import org.libreplan.business.qualityforms.daos.IQualityFormDAO;
import org.libreplan.business.qualityforms.entities.QualityForm; import org.libreplan.business.qualityforms.entities.QualityForm;
import org.libreplan.business.requirements.entities.DirectCriterionRequirement; import org.libreplan.business.requirements.entities.DirectCriterionRequirement;
@ -909,4 +910,12 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
return false; return false;
} }
public boolean isAnyTaskWithConstraint(PositionConstraintType type) {
if ((planningState == null) || (planningState.getRootTask() == null)) {
return false;
}
return planningState.getRootTask().isAnyTaskWithConstraint(type);
}
} }

View file

@ -4,7 +4,7 @@
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* *
* Copyright (C) 2011 Igalia S.L * Copyright (C) 2011-2012 Igalia S.L
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -92,7 +92,11 @@ public abstract class TreeElementOperationsController<T> {
public void indentSelectedElement() { public void indentSelectedElement() {
if (tree.getSelectedCount() == 1) { if (tree.getSelectedCount() == 1) {
int page = tree.getActivePage();
indent(getSelectedElement()); indent(getSelectedElement());
if (tree.getPageCount() > page) {
tree.setActivePage(page);
}
} else { } else {
showSelectAnElementError(); showSelectAnElementError();
} }
@ -236,9 +240,9 @@ class OrderElementOperations extends TreeElementOperationsController<OrderElemen
private int showConfirmCreateTemplateDialog() { private int showConfirmCreateTemplateDialog() {
try { try {
return Messagebox return Messagebox
.show(_("Unsaved changes will be lost. Would you like to continue?", .show(_("Unsaved changes will be lost. Would you like to continue?"),
_("Confirm create template"), Messagebox.YES _("Confirm create template"), Messagebox.OK
| Messagebox.NO, Messagebox.QUESTION)); | Messagebox.CANCEL, Messagebox.QUESTION);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View file

@ -338,7 +338,8 @@ public abstract class AssignedMaterialsController<T, A> extends GenericForwardCo
Label lblName = new Label(materialCategory.getName()); Label lblName = new Label(materialCategory.getName());
Label lblUnits = new Label(getUnits(materialCategory).toString()); Label lblUnits = new Label(getUnits(materialCategory).toString());
Label lblPrice = new Label(getPrice(materialCategory).toString()); Label lblPrice = new Label(getPrice(materialCategory).toString()
+ getCurrencySymbol());
Treerow tr = null; Treerow tr = null;
ti.setValue(node); ti.setValue(node);
@ -573,4 +574,12 @@ public abstract class AssignedMaterialsController<T, A> extends GenericForwardCo
.getId().equals(material.getUnitType().getId()))); .getId().equals(material.getUnitType().getId())));
} }
public String getCurrencySymbol() {
return Util.getCurrencySymbol();
}
public String getMoneyFormat() {
return Util.getMoneyFormat();
}
} }

View file

@ -60,7 +60,6 @@ import org.libreplan.business.common.entities.ProgressType;
import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO; import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO;
import org.libreplan.business.labels.entities.Label; import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.orders.daos.IOrderElementDAO; import org.libreplan.business.orders.daos.IOrderElementDAO;
import org.libreplan.business.orders.daos.OrderElementDAO;
import org.libreplan.business.orders.entities.Order; import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderStatusEnum; import org.libreplan.business.orders.entities.OrderStatusEnum;
@ -90,6 +89,7 @@ import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.EffortDuration.IEffortFrom; import org.libreplan.business.workingday.EffortDuration.IEffortFrom;
import org.libreplan.business.workingday.IntraDayDate; import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.business.workingday.IntraDayDate.PartialDay; import org.libreplan.business.workingday.IntraDayDate.PartialDay;
import org.libreplan.web.common.Util;
import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState; import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
@ -118,41 +118,8 @@ public class TaskElementAdapter {
private static final Log LOG = LogFactory.getLog(TaskElementAdapter.class); private static final Log LOG = LogFactory.getLog(TaskElementAdapter.class);
private static TaskPositionConstraint getLeftMostFixedDateConstraintAmongChildren(
TaskGroup container) {
TaskPositionConstraint constraint = null;
for(TaskElement child : ((TaskGroup)container).getChildren()) {
TaskPositionConstraint currentConstraint = null;
if (child instanceof ITaskPositionConstrained) {
ITaskPositionConstrained task = (ITaskPositionConstrained) child;
currentConstraint = task.getPositionConstraint();
}
else if (child instanceof TaskGroup) {
currentConstraint = getLeftMostFixedDateConstraintAmongChildren(
(TaskGroup) child);
}
if(currentConstraint != null &&
currentConstraint.getConstraintType().equals(
PositionConstraintType.START_IN_FIXED_DATE) &&
(constraint == null || currentConstraint.getConstraintDate().
compareTo(constraint.getConstraintDate()) < 0)) {
constraint = currentConstraint;
}
}
return constraint;
}
public static List<Constraint<GanttDate>> getStartConstraintsFor( public static List<Constraint<GanttDate>> getStartConstraintsFor(
TaskElement taskElement, LocalDate orderInitDate) { TaskElement taskElement, LocalDate orderInitDate) {
if (taskElement instanceof TaskGroup) {
TaskPositionConstraint constraint =
getLeftMostFixedDateConstraintAmongChildren((TaskGroup) taskElement);
if(constraint == null) {
return Collections.emptyList();
}
return Collections.singletonList(equalTo(toGantt(
constraint.getConstraintDate())));
}
if (taskElement instanceof ITaskPositionConstrained) { if (taskElement instanceof ITaskPositionConstrained) {
ITaskPositionConstrained task = (ITaskPositionConstrained) taskElement; ITaskPositionConstrained task = (ITaskPositionConstrained) taskElement;
TaskPositionConstraint startConstraint = task TaskPositionConstraint startConstraint = task
@ -1067,13 +1034,13 @@ public class TaskElementAdapter {
if (taskElement.getOrderElement() instanceof Order) { if (taskElement.getOrderElement() instanceof Order) {
result.append(_("State") + ": ").append(getOrderState()); result.append(_("State") + ": ").append(getOrderState());
} else { } else {
String budget = Util.addCurrencySymbol(getBudget());
String moneyCost = Util.addCurrencySymbol(getMoneyCost());
result.append( result.append(
_("Budget: {0}€, Consumed: {1}€ ({2}%)", _("Budget: {0}, Consumed: {1} ({2}%)", budget,
getBudget(), moneyCost, getMoneyCostBarPercentage()
getMoneyCost(), .multiply(new BigDecimal(100))))
getMoneyCostBarPercentage().multiply( .append("<br/>");
new BigDecimal(100)))).append(
"<br/>");
} }
String labels = buildLabelsText(); String labels = buildLabelsText();

View file

@ -508,6 +508,12 @@ public abstract class ChartFiller implements IChartFiller {
return result; return result;
} }
protected SortedMap<LocalDate, BigDecimal> calculatedValueForEveryDay(
SortedMap<LocalDate, BigDecimal> values, Interval interval) {
return calculatedValueForEveryDay(values, interval.getStart(),
interval.getFinish());
}
protected SortedMap<LocalDate, BigDecimal> calculatedValueForEveryDay( protected SortedMap<LocalDate, BigDecimal> calculatedValueForEveryDay(
SortedMap<LocalDate, BigDecimal> map, Date start, Date finish) { SortedMap<LocalDate, BigDecimal> map, Date start, Date finish) {
return calculatedValueForEveryDay(map, new LocalDate(start), return calculatedValueForEveryDay(map, new LocalDate(start),

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -22,18 +22,13 @@
package org.libreplan.web.planner.chart; package org.libreplan.web.planner.chart;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.libreplan.web.I18nHelper; import org.libreplan.web.I18nHelper;
import org.zkforge.timeplot.Plotinfo; import org.zkforge.timeplot.Plotinfo;
@ -44,130 +39,24 @@ import org.zkoss.ganttz.util.Interval;
/** /**
* Abstract class with the common functionality for the earned value chart.
* *
* @author Manuel Rego Casasnovas <mrego@igalia.com> * @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
*
* Abstract class with the common functionality for the earned value
* chart.
*/ */
public abstract class EarnedValueChartFiller extends ChartFiller { public abstract class EarnedValueChartFiller extends ChartFiller {
public static <K, V> void forValuesAtSameKey(Map<K, V> a, Map<K, V> b,
IOperation<K, V> onSameKey) {
for (Entry<K, V> each : a.entrySet()) {
V aValue = each.getValue();
V bValue = b.get(each.getKey());
onSameKey.operate(each.getKey(), aValue, bValue);
}
}
public interface IOperation<K, V> {
public void operate(K key, V a, V b);
public void undefinedFor(K key);
}
protected static abstract class PreconditionChecker<K, V> implements
IOperation<K, V> {
private final IOperation<K, V> decorated;
protected PreconditionChecker(IOperation<K, V> decorated) {
this.decorated = decorated;
}
@Override
public void operate(K key, V a, V b) {
if (isOperationDefinedFor(key, a, b)) {
decorated.operate(key, a, b);
} else {
decorated.undefinedFor(key);
}
}
protected abstract boolean isOperationDefinedFor(K key, V a, V b);
@Override
public void undefinedFor(K key) {
decorated.undefinedFor(key);
}
}
public static <K, V> IOperation<K, V> notNullOperands(
final IOperation<K, V> operation) {
return new PreconditionChecker<K, V>(operation) {
@Override
protected boolean isOperationDefinedFor(K key, V a, V b) {
return a != null && b != null;
}
};
}
public static <K> IOperation<K, BigDecimal> secondOperandNotZero(
final IOperation<K, BigDecimal> operation) {
return new PreconditionChecker<K, BigDecimal>(operation) {
@Override
protected boolean isOperationDefinedFor(K key, BigDecimal a, BigDecimal b) {
return b.signum() != 0;
}
};
}
public static boolean includes(Interval interval, LocalDate date) { public static boolean includes(Interval interval, LocalDate date) {
LocalDate start = interval.getStart(); LocalDate start = interval.getStart();
LocalDate end = interval.getFinish(); LocalDate end = interval.getFinish();
return start.compareTo(date) <= 0 && date.compareTo(end) < 0; return start.compareTo(date) <= 0 && date.compareTo(end) < 0;
} }
public enum EarnedValueType {
BCWS(_("BCWS"), _("Budgeted Cost Work Scheduled"), "#0000FF"), ACWP(
_("ACWP"), _("Actual Cost Work Performed"), "#FF0000"), BCWP(
_("BCWP"), _("Budgeted Cost Work Performed"), "#00FF00"), CV(
_("CV"), _("Cost Variance"), "#FF8800"), SV(_("SV"),
_("Schedule Variance"), "#00FFFF"), BAC(_("BAC"),
_("Budget At Completion"), "#FF00FF"), EAC(_("EAC"),
_("Estimate At Completion"), "#880000"), VAC(_("VAC"),
_("Variance At Completion"), "#000088"), ETC(_("ETC"),
_("Estimate To Complete"), "#008800"), CPI(_("CPI"),
_("Cost Performance Index"), "#888800"), SPI(_("SPI"),
_("Schedule Performance Index"), "#008888")
;
/**
* Forces to mark the string as needing translation
*/
private static String _(String string) {
return string;
}
private String acronym;
private String name;
private String color;
private EarnedValueType(String acronym, String name, String color) {
this.acronym = acronym;
this.name = name;
this.color = color;
}
public String getAcronym() {
return I18nHelper._(acronym);
}
public String getName() {
return I18nHelper._(name);
}
public String getColor() {
return color;
}
}
protected Map<EarnedValueType, SortedMap<LocalDate, BigDecimal>> indicators = new HashMap<EarnedValueType, SortedMap<LocalDate, BigDecimal>>(); protected Map<EarnedValueType, SortedMap<LocalDate, BigDecimal>> indicators = new HashMap<EarnedValueType, SortedMap<LocalDate, BigDecimal>>();
private Interval indicatorsInterval;
protected abstract void calculateBudgetedCostWorkScheduled(Interval interval); private Interval indicatorsInterval;
protected abstract void calculateActualCostWorkPerformed(Interval interval);
protected abstract void calculateBudgetedCostWorkPerformed(Interval interval);
protected Plotinfo createPlotInfo(SortedMap<LocalDate, BigDecimal> map, protected Plotinfo createPlotInfo(SortedMap<LocalDate, BigDecimal> map,
Interval interval, String lineColor) { Interval interval, String lineColor) {
@ -203,167 +92,55 @@ public abstract class EarnedValueChartFiller extends ChartFiller {
calculateSchedulePerformanceIndex(); calculateSchedulePerformanceIndex();
} }
protected abstract void calculateBudgetedCostWorkScheduled(Interval interval);
protected abstract void calculateActualCostWorkPerformed(Interval interval);
protected abstract void calculateBudgetedCostWorkPerformed(Interval interval);
protected abstract void calculateCostVariance();
protected abstract void calculateScheduleVariance();
protected abstract void calculateBudgetAtCompletion();
protected abstract void calculateEstimateAtCompletion();
protected abstract void calculateVarianceAtCompletion();
protected abstract void calculateEstimatedToComplete();
protected abstract void calculateSchedulePerformanceIndex();
protected abstract void calculateCostPerformanceIndex();
protected abstract Set<EarnedValueType> getSelectedIndicators();
public SortedMap<LocalDate, BigDecimal> getIndicator(EarnedValueType indicator) {
return indicators.get(indicator);
}
public BigDecimal getIndicator(EarnedValueType indicator, LocalDate date) { public BigDecimal getIndicator(EarnedValueType indicator, LocalDate date) {
return indicators.get(indicator).get(date); return indicators.get(indicator).get(date);
} }
private void calculateCostVariance() { public void setIndicator(EarnedValueType type, SortedMap<LocalDate, BigDecimal> values) {
// CV = BCWP - ACWP indicators.put(type, values);
indicators.put(EarnedValueType.CV,
substract(EarnedValueType.BCWP, EarnedValueType.ACWP));
} }
private void calculateScheduleVariance() { public void setIndicatorInInterval(EarnedValueType type,
// SV = BCWP - BCWS Interval interval, SortedMap<LocalDate, BigDecimal> values) {
addZeroBeforeTheFirstValue(values);
indicators.put(EarnedValueType.SV, indicators.put(type, calculatedValueForEveryDay(values, interval));
substract(EarnedValueType.BCWP, EarnedValueType.BCWS));
} }
private void calculateBudgetAtCompletion() { protected void addZeroBeforeTheFirstValue(
// BAC = max (BCWS) SortedMap<LocalDate, BigDecimal> map) {
SortedMap<LocalDate, BigDecimal> bac = new TreeMap<LocalDate, BigDecimal>(); if (!map.isEmpty()) {
SortedMap<LocalDate, BigDecimal> bcws = indicators map.put(map.firstKey().minusDays(1), BigDecimal.ZERO);
.get(EarnedValueType.BCWS);
BigDecimal value = Collections.max(bcws.values());
for (LocalDate day : bcws.keySet()) {
bac.put(day, value);
} }
indicators.put(EarnedValueType.BAC, bac);
} }
private void calculateEstimateAtCompletion() {
// EAC = (ACWP/BCWP) * BAC
SortedMap<LocalDate, BigDecimal> dividend = divide(
EarnedValueType.ACWP, EarnedValueType.BCWP,
BigDecimal.ZERO);
SortedMap<LocalDate, BigDecimal> bac = indicators
.get(EarnedValueType.BAC);
indicators.put(EarnedValueType.EAC, multiply(dividend, bac));
}
private static SortedMap<LocalDate, BigDecimal> multiply(
Map<LocalDate, BigDecimal> firstFactor,
Map<LocalDate, BigDecimal> secondFactor) {
final SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
forValuesAtSameKey(firstFactor, secondFactor,
multiplicationOperation(result));
return result;
}
private static IOperation<LocalDate, BigDecimal> multiplicationOperation(
final SortedMap<LocalDate, BigDecimal> result) {
return notNullOperands(new IOperation<LocalDate, BigDecimal>() {
@Override
public void operate(LocalDate key, BigDecimal a,
BigDecimal b) {
result.put(key, a.multiply(b));
}
@Override
public void undefinedFor(LocalDate key) {
result.put(key, BigDecimal.ZERO);
}
});
}
private void calculateVarianceAtCompletion() {
indicators.put(EarnedValueType.VAC,
substract(EarnedValueType.BAC, EarnedValueType.EAC));
}
private void calculateEstimatedToComplete() {
// ETC = EAC - ACWP
indicators.put(EarnedValueType.ETC,
substract(EarnedValueType.EAC, EarnedValueType.ACWP));
}
private SortedMap<LocalDate, BigDecimal> substract(EarnedValueType minuend,
EarnedValueType subtrahend) {
return substract(indicators.get(minuend), indicators.get(subtrahend));
}
private static SortedMap<LocalDate, BigDecimal> substract(
Map<LocalDate, BigDecimal> minuend,
Map<LocalDate, BigDecimal> subtrahend) {
final SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
forValuesAtSameKey(minuend, subtrahend, substractionOperation(result));
return result;
}
private static IOperation<LocalDate, BigDecimal> substractionOperation(
final SortedMap<LocalDate, BigDecimal> result) {
return notNullOperands(new IOperation<LocalDate, BigDecimal>() {
@Override
public void operate(LocalDate key, BigDecimal minuedValue,
BigDecimal subtrahendValue) {
result.put(key,
minuedValue.subtract(subtrahendValue));
}
@Override
public void undefinedFor(LocalDate key) {
}
});
}
private void calculateCostPerformanceIndex() {
// CPI = BCWP / ACWP
indicators.put(EarnedValueType.CPI,
divide(EarnedValueType.BCWP, EarnedValueType.ACWP,
BigDecimal.ZERO));
}
private void calculateSchedulePerformanceIndex() {
// SPI = BCWP / BCWS
indicators.put(EarnedValueType.SPI,
divide(EarnedValueType.BCWP, EarnedValueType.BCWS,
BigDecimal.ZERO));
}
private SortedMap<LocalDate, BigDecimal> divide(EarnedValueType dividend,
EarnedValueType divisor, BigDecimal defaultIfNotComputable) {
Validate.notNull(indicators.get(dividend));
Validate.notNull(indicators.get(divisor));
return divide(indicators.get(dividend), indicators.get(divisor),
defaultIfNotComputable);
}
private static SortedMap<LocalDate, BigDecimal> divide(
Map<LocalDate, BigDecimal> dividend,
Map<LocalDate, BigDecimal> divisor,
final BigDecimal defaultIfNotComputable) {
final TreeMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
forValuesAtSameKey(dividend, divisor,
divisionOperation(result, defaultIfNotComputable));
return result;
}
private static IOperation<LocalDate, BigDecimal> divisionOperation(
final TreeMap<LocalDate, BigDecimal> result,
final BigDecimal defaultIfNotComputable) {
return notNullOperands(secondOperandNotZero(new IOperation<LocalDate, BigDecimal>() {
@Override
public void operate(LocalDate key, BigDecimal dividendValue,
BigDecimal divisorValue) {
result.put(key, dividendValue.divide(divisorValue,
RoundingMode.DOWN));
}
@Override
public void undefinedFor(LocalDate key) {
result.put(key, defaultIfNotComputable);
}
}));
}
protected abstract Set<EarnedValueType> getSelectedIndicators();
@Override @Override
public void fillChart(Timeplot chart, Interval interval, Integer size) { public void fillChart(Timeplot chart, Interval interval, Integer size) {
chart.getChildren().clear(); chart.getChildren().clear();
@ -411,11 +188,55 @@ public abstract class EarnedValueChartFiller extends ChartFiller {
return includes(chartInterval, today) ? today : chartInterval return includes(chartInterval, today) ? today : chartInterval
.getFinish().minusDays(1); .getFinish().minusDays(1);
} }
protected void addZeroBeforeTheFirstValue(
SortedMap<LocalDate, BigDecimal> map) { /**
if (!map.isEmpty()) { *
map.put(map.firstKey().minusDays(1), BigDecimal.ZERO); * @author Manuel Rego Casasnovas <mrego@igalia.com>
*
*/
public enum EarnedValueType {
BCWS(_("BCWS"), _("Budgeted Cost Work Scheduled"), "#0000FF"), ACWP(
_("ACWP"), _("Actual Cost Work Performed"), "#FF0000"), BCWP(
_("BCWP"), _("Budgeted Cost Work Performed"), "#00FF00"), CV(
_("CV"), _("Cost Variance"), "#FF8800"), SV(_("SV"),
_("Schedule Variance"), "#00FFFF"), BAC(_("BAC"),
_("Budget At Completion"), "#FF00FF"), EAC(_("EAC"),
_("Estimate At Completion"), "#880000"), VAC(_("VAC"),
_("Variance At Completion"), "#000088"), ETC(_("ETC"),
_("Estimate To Complete"), "#008800"), CPI(_("CPI"),
_("Cost Performance Index"), "#888800"), SPI(_("SPI"),
_("Schedule Performance Index"), "#008888")
;
/**
* Forces to mark the string as needing translation
*/
private static String _(String string) {
return string;
}
private String acronym;
private String name;
private String color;
private EarnedValueType(String acronym, String name, String color) {
this.acronym = acronym;
this.name = name;
this.color = color;
}
public String getAcronym() {
return I18nHelper._(acronym);
}
public String getName() {
return I18nHelper._(name);
}
public String getColor() {
return color;
} }
} }
} }

View file

@ -38,8 +38,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.libreplan.business.calendars.entities.AvailabilityTimeLine; import org.libreplan.business.calendars.entities.AvailabilityTimeLine;
@ -55,6 +53,7 @@ import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderStatusEnum; import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.planner.chart.ILoadChartData; import org.libreplan.business.planner.chart.ILoadChartData;
import org.libreplan.business.planner.chart.ResourceLoadChartData; import org.libreplan.business.planner.chart.ResourceLoadChartData;
import org.libreplan.business.planner.entities.ICompanyEarnedValueCalculator;
import org.libreplan.business.planner.entities.TaskElement; import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.planner.entities.TaskGroup; import org.libreplan.business.planner.entities.TaskGroup;
import org.libreplan.business.planner.entities.TaskMilestone; import org.libreplan.business.planner.entities.TaskMilestone;
@ -62,7 +61,6 @@ import org.libreplan.business.scenarios.IScenarioManager;
import org.libreplan.business.scenarios.entities.Scenario; import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.users.daos.IUserDAO; import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.entities.User; import org.libreplan.business.users.entities.User;
import org.libreplan.business.workreports.entities.WorkReportLine;
import org.libreplan.web.planner.TaskElementAdapter; import org.libreplan.web.planner.TaskElementAdapter;
import org.libreplan.web.planner.TaskGroupPredicate; import org.libreplan.web.planner.TaskGroupPredicate;
import org.libreplan.web.planner.chart.Chart; import org.libreplan.web.planner.chart.Chart;
@ -132,6 +130,9 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
@Autowired @Autowired
private IAdHocTransactionService transactionService; private IAdHocTransactionService transactionService;
@Autowired
private ICompanyEarnedValueCalculator earnedValueCalculator;
private List<IZoomLevelChangedListener> keepAliveZoomListeners = new ArrayList<IZoomLevelChangedListener>(); private List<IZoomLevelChangedListener> keepAliveZoomListeners = new ArrayList<IZoomLevelChangedListener>();
private List<Checkbox> earnedValueChartConfigurationCheckboxes = new ArrayList<Checkbox>(); private List<Checkbox> earnedValueChartConfigurationCheckboxes = new ArrayList<Checkbox>();
@ -275,6 +276,7 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
setupChart(chartLoadTimeplot, new CompanyLoadChartFiller(), planner); setupChart(chartLoadTimeplot, new CompanyLoadChartFiller(), planner);
chartComponent.getTabs().getLastChild().addEventListener(Events.ON_SELECT, new EventListener() { chartComponent.getTabs().getLastChild().addEventListener(Events.ON_SELECT, new EventListener() {
@Override
public void onEvent(Event event) throws Exception { public void onEvent(Event event) throws Exception {
createOnDemandEarnedValueTimePlot(chartComponent, planner); createOnDemandEarnedValueTimePlot(chartComponent, planner);
event.getTarget().removeEventListener(Events.ON_SELECT, this); event.getTarget().removeEventListener(Events.ON_SELECT, this);
@ -783,75 +785,101 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
} }
/**
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
*
* Calculates 'Earned Value' indicators and set them in the Company
* 'Earned Valued' chart
*
*/
private class CompanyEarnedValueChartFiller extends EarnedValueChartFiller { private class CompanyEarnedValueChartFiller extends EarnedValueChartFiller {
@Override
protected void calculateBudgetedCostWorkScheduled(Interval interval) { protected void calculateBudgetedCostWorkScheduled(Interval interval) {
Map<TaskElement, SortedMap<LocalDate, BigDecimal>> estimatedCostPerTask = setIndicatorInInterval(EarnedValueType.BCWS, interval,
databaseSnapshots.snapshotEstimatedCostPerTask(); earnedValueCalculator
Collection<TaskElement> list = filterTasksByDate( .calculateBudgetedCostWorkScheduled(getFilterInterval()));
estimatedCostPerTask.keySet(), getFilterInterval());
SortedMap<LocalDate, BigDecimal> estimatedCost = new TreeMap<LocalDate, BigDecimal>();
for (TaskElement taskElement : list) {
addCost(estimatedCost, estimatedCostPerTask.get(taskElement));
}
estimatedCost = accumulateResult(estimatedCost);
addZeroBeforeTheFirstValue(estimatedCost);
indicators.put(EarnedValueType.BCWS, calculatedValueForEveryDay(
estimatedCost, interval.getStart(), interval.getFinish()));
} }
@Override
protected void calculateActualCostWorkPerformed(Interval interval) { protected void calculateActualCostWorkPerformed(Interval interval) {
SortedMap<LocalDate, BigDecimal> workReportCost = getWorkReportCost(); setIndicatorInInterval(EarnedValueType.ACWP, interval,
earnedValueCalculator
workReportCost = accumulateResult(workReportCost); .calculateActualCostWorkPerformed(getFilterInterval()));
addZeroBeforeTheFirstValue(workReportCost);
indicators.put(EarnedValueType.ACWP, calculatedValueForEveryDay(
workReportCost, interval.getStart(), interval.getFinish()));
}
private SortedMap<LocalDate, BigDecimal> getWorkReportCost() {
SortedMap<LocalDate, BigDecimal> result = new TreeMap<LocalDate, BigDecimal>();
Collection<WorkReportLine> workReportLines = filterWorkReportLinesByDate(
databaseSnapshots.snapshotWorkReportLines(),
getFilterInterval());
if (workReportLines.isEmpty()) {
return result;
}
for (WorkReportLine workReportLine : workReportLines) {
LocalDate day = new LocalDate(workReportLine.getDate());
BigDecimal cost = workReportLine.getEffort()
.toHoursAsDecimalWithScale(2);
if (!result.containsKey(day)) {
result.put(day, BigDecimal.ZERO);
}
result.put(day, result.get(day).add(cost));
}
return result;
} }
@Override
protected void calculateBudgetedCostWorkPerformed(Interval interval) { protected void calculateBudgetedCostWorkPerformed(Interval interval) {
Map<TaskElement, SortedMap<LocalDate, BigDecimal>> advanceCostPerTask = setIndicatorInInterval(EarnedValueType.BCWP, interval,
databaseSnapshots.snapshotAdvanceCostPerTask(); earnedValueCalculator
Collection<TaskElement> list = filterTasksByDate( .calculateBudgetedCostWorkPerformed(getFilterInterval()));
advanceCostPerTask.keySet(), getFilterInterval()); }
SortedMap<LocalDate, BigDecimal> advanceCost = new TreeMap<LocalDate, BigDecimal>(); @Override
protected void calculateCostVariance() {
setIndicator(EarnedValueType.CV,
earnedValueCalculator.calculateCostVariance(
getIndicator(EarnedValueType.BCWP),
getIndicator(EarnedValueType.ACWP)));
}
for (TaskElement taskElement : list) { @Override
addCost(advanceCost, advanceCostPerTask.get(taskElement)); protected void calculateScheduleVariance() {
} setIndicator(EarnedValueType.SV,
earnedValueCalculator.calculateScheduleVariance(
getIndicator(EarnedValueType.BCWP),
getIndicator(EarnedValueType.BCWS)));
}
addZeroBeforeTheFirstValue(advanceCost); @Override
indicators.put(EarnedValueType.BCWP, calculatedValueForEveryDay( protected void calculateSchedulePerformanceIndex() {
advanceCost, interval.getStart(), interval.getFinish())); setIndicator(EarnedValueType.SPI,
earnedValueCalculator.calculateSchedulePerformanceIndex(
getIndicator(EarnedValueType.BCWP),
getIndicator(EarnedValueType.BCWS)));
}
@Override
protected void calculateBudgetAtCompletion() {
setIndicator(
EarnedValueType.BAC,
earnedValueCalculator
.calculateBudgetAtCompletion(getIndicator(EarnedValueType.BCWS)));
}
@Override
protected void calculateEstimateAtCompletion() {
setIndicator(EarnedValueType.EAC,
earnedValueCalculator.calculateEstimateAtCompletion(
getIndicator(EarnedValueType.ACWP),
getIndicator(EarnedValueType.BCWP),
getIndicator(EarnedValueType.BAC)));
}
@Override
protected void calculateVarianceAtCompletion() {
setIndicator(EarnedValueType.VAC,
earnedValueCalculator.calculateVarianceAtCompletion(
getIndicator(EarnedValueType.BAC),
getIndicator(EarnedValueType.EAC)));
}
@Override
protected void calculateEstimatedToComplete() {
setIndicator(EarnedValueType.ETC,
earnedValueCalculator.calculateEstimatedToComplete(
getIndicator(EarnedValueType.EAC),
getIndicator(EarnedValueType.ACWP)));
}
@Override
protected void calculateCostPerformanceIndex() {
setIndicator(EarnedValueType.CPI,
earnedValueCalculator.calculateCostPerformanceIndex(
getIndicator(EarnedValueType.BCWP),
getIndicator(EarnedValueType.ACWP)));
} }
@Override @Override
@ -859,33 +887,9 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
return getEarnedValueSelectedIndicators(); return getEarnedValueSelectedIndicators();
} }
private List<TaskElement> filterTasksByDate(
Collection<TaskElement> tasks,
AvailabilityTimeLine.Interval interval) {
List<TaskElement> result = new ArrayList<TaskElement>();
for(TaskElement task : tasks) {
if (interval.includes(task.getStartAsLocalDate())
|| interval.includes(task.getEndAsLocalDate())) {
result.add(task);
}
}
return result;
}
private List<WorkReportLine> filterWorkReportLinesByDate(
Collection<WorkReportLine> lines,
AvailabilityTimeLine.Interval interval) {
List<WorkReportLine> result = new ArrayList<WorkReportLine>();
for(WorkReportLine line: lines) {
if (interval.includes(line.getLocalDate())) {
result.add(line);
}
}
return result;
}
} }
@Override
@Transactional(readOnly=true) @Transactional(readOnly=true)
public ProgressType getProgressTypeFromConfiguration() { public ProgressType getProgressTypeFromConfiguration() {
return configurationDAO.getConfiguration().getProgressType(); return configurationDAO.getConfiguration().getProgressType();

View file

@ -3,7 +3,7 @@
* *
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia * Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L. * Copyright (C) 2010-2012 Igalia, S.L.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -57,7 +57,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.zkoss.ganttz.data.GanttDate;
import org.zkoss.ganttz.extensions.IContextWithPlannerTask; import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
/** /**
@ -152,7 +151,6 @@ public class AdvanceConsolidationModel implements IAdvanceConsolidationModel {
updateConsolidationInAdvanceIfIsNeeded(); updateConsolidationInAdvanceIfIsNeeded();
ganttTask.enforceDependenciesDueToPositionPotentiallyModified(); ganttTask.enforceDependenciesDueToPositionPotentiallyModified();
ganttTask.reloadResourcesText();
context.reloadCharts(); context.reloadCharts();
} }
} }

Some files were not shown because too many files have changed in this diff Show more