Merge branch 'master' into subcontracting
This commit is contained in:
commit
7364bb000d
245 changed files with 54491 additions and 3607 deletions
1
AUTHORS
1
AUTHORS
|
|
@ -42,6 +42,7 @@ Translators
|
|||
Diego Pino García <dpino@igalia.com>
|
||||
* [it] Giuseppe Zizza <gzizza@gmail.com>
|
||||
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
|
||||
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
|
||||
* [pt] Helena Grosso <lenagrosso@gmail.com>,
|
||||
Joaquim Rocha <jrocha@igalia.com>
|
||||
* [ru] Pavel Rudensky <prudensky@gmail.com>
|
||||
|
|
|
|||
38
HACKING
38
HACKING
|
|
@ -351,6 +351,44 @@ command. For example:
|
|||
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
|
||||
-----
|
||||
|
||||
|
|
|
|||
2
INSTALL
2
INSTALL
|
|
@ -46,7 +46,7 @@ Instructions:
|
|||
|
||||
* 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::
|
||||
|
||||
|
|
|
|||
173
NEWS
173
NEWS
|
|
@ -1,6 +1,179 @@
|
|||
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)
|
||||
---------------------------
|
||||
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
1.2.2
|
||||
1.2.3
|
||||
|
|
|
|||
6
debian/changelog
vendored
6
debian/changelog
vendored
|
|
@ -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
|
||||
|
||||
* Released LibrePlan 1.2.2
|
||||
|
|
|
|||
1
debian/libreplan.install
vendored
1
debian/libreplan.install
vendored
|
|
@ -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.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.3
|
||||
|
|
|
|||
3
debian/rules
vendored
3
debian/rules
vendored
|
|
@ -90,6 +90,9 @@ install:
|
|||
# Copy SQL upgrade script for version 1.2.2
|
||||
$(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)
|
||||
# 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
|
||||
$(call CMD,mkdir -p $(CURDIR)/debian/tmp/etc/tomcat6/policy.d)
|
||||
$(call CMD,cp $(CURDIR)/debian/51libreplan.policy \
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ a) Clone Git repository (recommended)::
|
|||
|
||||
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
|
||||
|
||||
You should review ``HACKING`` file to check that you have installed all the
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ Translators
|
|||
Diego Pino García <dpino@igalia.com>
|
||||
* [it] Giuseppe Zizza <gzizza@gmail.com>
|
||||
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
|
||||
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
|
||||
* [pt] Helena Grosso <lenagrosso@gmail.com>,
|
||||
Joaquim Rocha <jrocha@igalia.com>
|
||||
* [ru] Pavel Rudensky <prudensky@gmail.com>
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ Traductores
|
|||
Diego Pino García <dpino@igalia.com>
|
||||
* [it] Giuseppe Zizza <gzizza@gmail.com>
|
||||
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
|
||||
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
|
||||
* [pt] Helena Grosso <lenagrosso@gmail.com>,
|
||||
Joaquim Rocha <jrocha@igalia.com>
|
||||
* [ru] Pavel Rudensky <prudensky@gmail.com>
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ Traductores
|
|||
Diego Pino García <dpino@igalia.com>
|
||||
* [it] Giuseppe Zizza <gzizza@gmail.com>
|
||||
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
|
||||
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
|
||||
* [pt] Helena Grosso <lenagrosso@gmail.com>,
|
||||
Joaquim Rocha <jrocha@igalia.com>
|
||||
* [ru] Pavel Rudensky <prudensky@gmail.com>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.libreplan</groupId>
|
||||
<artifactId>libreplan</artifactId>
|
||||
<version>1.2.2</version>
|
||||
<version>1.2.3</version>
|
||||
</parent>
|
||||
<artifactId>ganttzk</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -388,18 +388,19 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
}
|
||||
});
|
||||
} catch (ParseException e) {
|
||||
getStartDateTextBox().setValue(
|
||||
dateFormat.format(task.getBeginDate()
|
||||
.toDayRoundedDate()));
|
||||
// Do nothing as textbox is rested in the next sentence
|
||||
}
|
||||
getStartDateTextBox().setValue(
|
||||
dateFormat.format(task.getBeginDate().toDayRoundedDate()));
|
||||
} else if (updatedComponent == getEndDateTextBox()) {
|
||||
try {
|
||||
Date newEnd = dateFormat.parse(getEndDateTextBox().getValue());
|
||||
task.resizeTo(LocalDate.fromDateFields(newEnd));
|
||||
} catch (ParseException e) {
|
||||
getEndDateTextBox().setValue(
|
||||
asString(task.getEndDate().toDayRoundedDate()));
|
||||
// Do nothing as textbox is rested in the next sentence
|
||||
}
|
||||
getEndDateTextBox().setValue(
|
||||
asString(task.getEndDate().toDayRoundedDate()));
|
||||
}
|
||||
planner.updateTooltips();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import org.zkoss.ganttz.data.GanttDiagramGraph.IDependenciesEnforcerHookFactory;
|
|||
import org.zkoss.ganttz.data.GanttDiagramGraph.INotificationAfterDependenciesEnforcement;
|
||||
import org.zkoss.ganttz.data.constraint.Constraint;
|
||||
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.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() {
|
||||
return fundamentalProperties.isSubcontracted();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,8 +86,8 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
|
|||
|
||||
private Listbox listZoomLevels;
|
||||
|
||||
private final String FILTER_RESOURCES = _("by resources");
|
||||
private final String FILTER_CRITERIA = _("by criteria");
|
||||
private final String FILTER_RESOURCES = _("Resources");
|
||||
private final String FILTER_CRITERIA = _("Generic allocation criteria");
|
||||
private String feedBackMessage;
|
||||
private Boolean filterbyResources;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
# Manuel Rego Casasnovas <rego@igalia.com>, 2010, 2011, 2012.
|
||||
msgid ""
|
||||
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"
|
||||
"POT-Creation-Date: 2012-01-13 16:49+0100\n"
|
||||
"PO-Revision-Date: 2012-01-13 16:00+0000\n"
|
||||
"POT-Creation-Date: 2012-04-11 08:32+0200\n"
|
||||
"PO-Revision-Date: 2012-04-11 08:35+0000\n"
|
||||
"Last-Translator: Manuel Rego Casasnovas <rego@igalia.com>\n"
|
||||
"Language-Team: Español\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -22,12 +22,12 @@ msgstr ""
|
|||
"Language: es\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:234
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
|
||||
msgid "Erase"
|
||||
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"
|
||||
msgstr "Añadir dependencia"
|
||||
|
||||
|
|
@ -35,11 +35,15 @@ msgstr "Añadir dependencia"
|
|||
msgid "Worker"
|
||||
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
|
||||
msgid "Start"
|
||||
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"
|
||||
msgstr "Mostrar horas reportadas"
|
||||
|
||||
|
|
@ -64,7 +68,7 @@ msgstr "Recursos limitantes"
|
|||
msgid "The specified dependency is not allowed"
|
||||
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"
|
||||
msgstr "Definir Fin-Fin"
|
||||
|
||||
|
|
@ -88,6 +92,10 @@ msgstr "esfuerzo disponible: {0}, esfuerzo asignado: {1}"
|
|||
msgid "Criterion"
|
||||
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
|
||||
msgid "Print"
|
||||
msgstr "Imprimir"
|
||||
|
|
@ -116,6 +124,10 @@ msgstr "Fin"
|
|||
msgid "changing 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
|
||||
msgid "Quarter"
|
||||
msgstr "Trimestre"
|
||||
|
|
@ -141,7 +153,7 @@ msgstr "Nombre"
|
|||
msgid "Name filter"
|
||||
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"
|
||||
msgstr "Mostrar progreso"
|
||||
|
||||
|
|
@ -153,14 +165,14 @@ msgstr "Expandir/Plegar todo"
|
|||
msgid "Show/Hide critical path"
|
||||
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
|
||||
msgid "showing criteria"
|
||||
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
|
||||
msgid "Month"
|
||||
msgstr "Mes"
|
||||
|
|
@ -169,15 +181,15 @@ msgstr "Mes"
|
|||
msgid "Show/Hide resources"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
msgstr "Ocultar camino crítico"
|
||||
|
||||
|
|
@ -185,7 +197,7 @@ msgstr "Ocultar camino crítico"
|
|||
msgid "Day"
|
||||
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"
|
||||
msgstr "Ocultar horas reportadas"
|
||||
|
||||
|
|
@ -206,11 +218,11 @@ msgid "Hour"
|
|||
msgstr "Hora"
|
||||
|
||||
#: 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"
|
||||
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"
|
||||
msgstr "Definir Inicio-Inicio"
|
||||
|
||||
|
|
@ -218,7 +230,7 @@ msgstr "Definir Inicio-Inicio"
|
|||
msgid "See resource allocation"
|
||||
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"
|
||||
msgstr "aumentando zoom"
|
||||
|
||||
|
|
@ -234,10 +246,10 @@ msgstr "Todos"
|
|||
msgid "Refresh"
|
||||
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"
|
||||
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"
|
||||
msgstr "Ocultar progreso"
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
# Philippe Poumaroux <philippe.poumaroux@free.fr>, 2012.
|
||||
msgid ""
|
||||
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"
|
||||
"POT-Creation-Date: 2012-01-13 16:49+0100\n"
|
||||
"PO-Revision-Date: 2012-01-23 12:36+0000\n"
|
||||
"POT-Creation-Date: 2012-04-11 08:32+0200\n"
|
||||
"PO-Revision-Date: 2012-04-11 12:30+0000\n"
|
||||
"Last-Translator: Philippe Poumaroux <philippe.poumaroux@free.fr>\n"
|
||||
"Language-Team: Français\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -20,12 +20,12 @@ msgstr ""
|
|||
"Language: fr\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:234
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
|
||||
msgid "Erase"
|
||||
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"
|
||||
msgstr "Ajouter une dépendance"
|
||||
|
||||
|
|
@ -33,11 +33,15 @@ msgstr "Ajouter une dépendance"
|
|||
msgid "Worker"
|
||||
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
|
||||
msgid "Start"
|
||||
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"
|
||||
msgstr "Afficher les heures comptabilisées"
|
||||
|
||||
|
|
@ -62,7 +66,7 @@ msgstr "Ressources bloquantes"
|
|||
msgid "The specified dependency is not allowed"
|
||||
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"
|
||||
msgstr "Faire correspondre les achèvements"
|
||||
|
||||
|
|
@ -86,6 +90,10 @@ msgstr "investissement disponible: {0}, investissement affecté: {1}"
|
|||
msgid "Criterion"
|
||||
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
|
||||
msgid "Print"
|
||||
msgstr "Imprimer"
|
||||
|
|
@ -114,6 +122,10 @@ msgstr "Fin"
|
|||
msgid "changing 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
|
||||
msgid "Quarter"
|
||||
msgstr "Trimestre"
|
||||
|
|
@ -139,7 +151,7 @@ msgstr "Nom"
|
|||
msgid "Name filter"
|
||||
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"
|
||||
msgstr "Monter l'avancement"
|
||||
|
||||
|
|
@ -151,14 +163,14 @@ msgstr "Déplier/Replier tout"
|
|||
msgid "Show/Hide critical path"
|
||||
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
|
||||
msgid "showing criteria"
|
||||
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
|
||||
msgid "Month"
|
||||
msgstr "Mois"
|
||||
|
|
@ -167,15 +179,15 @@ msgstr "Mois"
|
|||
msgid "Show/Hide resources"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
msgstr "Cacher le chemin critique"
|
||||
|
||||
|
|
@ -183,7 +195,7 @@ msgstr "Cacher le chemin critique"
|
|||
msgid "Day"
|
||||
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"
|
||||
msgstr "Cacher les heures comptabilisées"
|
||||
|
||||
|
|
@ -204,11 +216,11 @@ msgid "Hour"
|
|||
msgstr "Heure"
|
||||
|
||||
#: 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"
|
||||
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"
|
||||
msgstr "Ajuster sur le début"
|
||||
|
||||
|
|
@ -216,7 +228,7 @@ msgstr "Ajuster sur le début"
|
|||
msgid "See resource allocation"
|
||||
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"
|
||||
msgstr "augmenter le zoom"
|
||||
|
||||
|
|
@ -232,10 +244,10 @@ msgstr "Tout"
|
|||
msgid "Refresh"
|
||||
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"
|
||||
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"
|
||||
msgstr "Cacher l'avancement"
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@
|
|||
# Manuel Rego Casasnovas <rego@igalia.com>, 2010, 2011, 2012.
|
||||
msgid ""
|
||||
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"
|
||||
"POT-Creation-Date: 2012-01-13 16:49+0100\n"
|
||||
"PO-Revision-Date: 2012-01-13 16:01+0000\n"
|
||||
"Last-Translator: Manuel Rego Casasnovas<rego@igalia.com>\n"
|
||||
"POT-Creation-Date: 2012-04-11 08:32+0200\n"
|
||||
"PO-Revision-Date: 2012-04-11 08:34+0000\n"
|
||||
"Last-Translator: Manuel Rego Casasnovas <rego@igalia.com>\n"
|
||||
"Language-Team: Galego\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
|
@ -22,12 +22,12 @@ msgstr ""
|
|||
"Language: gl\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:234
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
|
||||
msgid "Erase"
|
||||
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"
|
||||
msgstr "Engadir dependencia"
|
||||
|
||||
|
|
@ -35,11 +35,15 @@ msgstr "Engadir dependencia"
|
|||
msgid "Worker"
|
||||
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
|
||||
msgid "Start"
|
||||
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"
|
||||
msgstr "Mostrar horas reportadas"
|
||||
|
||||
|
|
@ -64,7 +68,7 @@ msgstr "Recursos limitantes"
|
|||
msgid "The specified dependency is not allowed"
|
||||
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"
|
||||
msgstr "Definir Fin-Fin"
|
||||
|
||||
|
|
@ -88,6 +92,10 @@ msgstr "esforzo dispoñible: {0}, esforzo asignado: {1}"
|
|||
msgid "Criterion"
|
||||
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
|
||||
msgid "Print"
|
||||
msgstr "Imprimir"
|
||||
|
|
@ -116,6 +124,10 @@ msgstr "Fin"
|
|||
msgid "changing 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
|
||||
msgid "Quarter"
|
||||
msgstr "Trimestre"
|
||||
|
|
@ -141,7 +153,7 @@ msgstr "Nome"
|
|||
msgid "Name filter"
|
||||
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"
|
||||
msgstr "Mostrar progreso"
|
||||
|
||||
|
|
@ -153,14 +165,14 @@ msgstr "Expandir/Pregar todo"
|
|||
msgid "Show/Hide critical path"
|
||||
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
|
||||
msgid "showing criteria"
|
||||
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
|
||||
msgid "Month"
|
||||
msgstr "Mes"
|
||||
|
|
@ -169,15 +181,15 @@ msgstr "Mes"
|
|||
msgid "Show/Hide resources"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
msgstr "Ocultar camiño crítico"
|
||||
|
||||
|
|
@ -185,7 +197,7 @@ msgstr "Ocultar camiño crítico"
|
|||
msgid "Day"
|
||||
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"
|
||||
msgstr "Ocultar horas reportadas"
|
||||
|
||||
|
|
@ -206,11 +218,11 @@ msgid "Hour"
|
|||
msgstr "Hora"
|
||||
|
||||
#: 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"
|
||||
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"
|
||||
msgstr "Definir Inicio-Inicio"
|
||||
|
||||
|
|
@ -218,7 +230,7 @@ msgstr "Definir Inicio-Inicio"
|
|||
msgid "See resource allocation"
|
||||
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"
|
||||
msgstr "aumentando zoom"
|
||||
|
||||
|
|
@ -234,10 +246,10 @@ msgstr "Todos"
|
|||
msgid "Refresh"
|
||||
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"
|
||||
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"
|
||||
msgstr "Ocultar progreso"
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
# Giuseppe Zizza <gzizza@gmail.com>, 2012.
|
||||
msgid ""
|
||||
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"
|
||||
"POT-Creation-Date: 2012-01-13 16:49+0100\n"
|
||||
"PO-Revision-Date: 2012-01-13 16:09+0000\n"
|
||||
"POT-Creation-Date: 2012-04-11 08:32+0200\n"
|
||||
"PO-Revision-Date: 2012-04-11 08:05+0000\n"
|
||||
"Last-Translator: Giuseppe Zizza <gzizza@gmail.com>\n"
|
||||
"Language-Team: Italiano\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -20,12 +20,12 @@ msgstr ""
|
|||
"Language: it\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:234
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
|
||||
msgid "Erase"
|
||||
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"
|
||||
msgstr "Aggiungi dipendenza"
|
||||
|
||||
|
|
@ -33,11 +33,15 @@ msgstr "Aggiungi dipendenza"
|
|||
msgid "Worker"
|
||||
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
|
||||
msgid "Start"
|
||||
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"
|
||||
msgstr "Mostra le ore riportate"
|
||||
|
||||
|
|
@ -62,7 +66,7 @@ msgstr "Risorse limitanti"
|
|||
msgid "The specified dependency is not allowed"
|
||||
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"
|
||||
msgstr "Imposta Fine-Fine"
|
||||
|
||||
|
|
@ -86,6 +90,10 @@ msgstr "Forza disponbile: {0}, forza assegnata: {1}"
|
|||
msgid "Criterion"
|
||||
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
|
||||
msgid "Print"
|
||||
msgstr "Stampa"
|
||||
|
|
@ -114,6 +122,10 @@ msgstr "Fine"
|
|||
msgid "changing zoom"
|
||||
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
|
||||
msgid "Quarter"
|
||||
msgstr "Quarto"
|
||||
|
|
@ -139,7 +151,7 @@ msgstr "Nome"
|
|||
msgid "Name filter"
|
||||
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"
|
||||
msgstr "Mostra progresso"
|
||||
|
||||
|
|
@ -151,14 +163,14 @@ msgstr "Espandi/Riduci tutti"
|
|||
msgid "Show/Hide critical path"
|
||||
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
|
||||
msgid "showing criteria"
|
||||
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
|
||||
msgid "Month"
|
||||
msgstr "Mese"
|
||||
|
|
@ -167,15 +179,15 @@ msgstr "Mese"
|
|||
msgid "Show/Hide resources"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
msgstr "Nascondi percorso critico"
|
||||
|
||||
|
|
@ -183,7 +195,7 @@ msgstr "Nascondi percorso critico"
|
|||
msgid "Day"
|
||||
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"
|
||||
msgstr "Nascondi ore riportate"
|
||||
|
||||
|
|
@ -204,11 +216,11 @@ msgid "Hour"
|
|||
msgstr "Ora"
|
||||
|
||||
#: 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"
|
||||
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"
|
||||
msgstr "Imposta Inizio-Inizio"
|
||||
|
||||
|
|
@ -216,7 +228,7 @@ msgstr "Imposta Inizio-Inizio"
|
|||
msgid "See resource allocation"
|
||||
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"
|
||||
msgstr "Aumento l'ingrandimento"
|
||||
|
||||
|
|
@ -232,10 +244,10 @@ msgstr "Tutti"
|
|||
msgid "Refresh"
|
||||
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"
|
||||
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"
|
||||
msgstr "Nascondi progresso"
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1.2.2\n"
|
||||
"Project-Id-Version: libreplan-1.2.3\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"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -31,11 +31,15 @@ msgstr ""
|
|||
msgid "Worker"
|
||||
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
|
||||
msgid "Start"
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -84,6 +88,10 @@ msgstr ""
|
|||
msgid "Criterion"
|
||||
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
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
|
@ -112,6 +120,10 @@ msgstr ""
|
|||
msgid "changing zoom"
|
||||
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
|
||||
msgid "Quarter"
|
||||
msgstr ""
|
||||
|
|
@ -137,7 +149,7 @@ msgstr ""
|
|||
msgid "Name filter"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:615
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
|
||||
msgid "Show progress"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -149,14 +161,14 @@ msgstr ""
|
|||
msgid "Show/Hide critical path"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
|
||||
msgid "Year"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
|
||||
msgid "showing criteria"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
|
||||
msgid "Year"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
|
||||
msgid "Month"
|
||||
msgstr ""
|
||||
|
|
@ -169,11 +181,11 @@ msgstr ""
|
|||
msgid "Set End-Start"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:297
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
|
||||
msgid "decreasing zoom"
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -181,7 +193,7 @@ msgstr ""
|
|||
msgid "Day"
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -202,7 +214,7 @@ msgid "Hour"
|
|||
msgstr ""
|
||||
|
||||
#: 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"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -214,7 +226,7 @@ msgstr ""
|
|||
msgid "See resource allocation"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:280
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
|
||||
msgid "increasing zoom"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -230,10 +242,10 @@ msgstr ""
|
|||
msgid "Refresh"
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
|
||||
msgid "Hide progress"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
# Jeroen Baten <jeroen@jeroenbaten.nl>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: LibrePlan\n"
|
||||
"Project-Id-Version: libreplan-1.2.3\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
|
||||
"POT-Creation-Date: 2012-02-24 09:08+0100\n"
|
||||
"PO-Revision-Date: 2012-02-29 19:53+0000\n"
|
||||
"POT-Creation-Date: 2012-04-11 08:32+0200\n"
|
||||
"PO-Revision-Date: 2012-04-13 14:30+0000\n"
|
||||
"Last-Translator: Jeroen Baten <jeroen@jeroenbaten.nl>\n"
|
||||
"Language-Team: Nederlands\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -33,11 +33,15 @@ msgstr "Voeg afhankelijkheid toe"
|
|||
msgid "Worker"
|
||||
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
|
||||
msgid "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"
|
||||
msgstr "Toon gerapporteerde uren"
|
||||
|
||||
|
|
@ -86,6 +90,10 @@ msgstr "Beschikbare inspanning: {0}, toegewezen inspanning: {1}"
|
|||
msgid "Criterion"
|
||||
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
|
||||
msgid "Print"
|
||||
msgstr "Afdrukken"
|
||||
|
|
@ -114,6 +122,10 @@ msgstr "Einde"
|
|||
msgid "changing 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
|
||||
msgid "Quarter"
|
||||
msgstr "Kwartaal"
|
||||
|
|
@ -139,7 +151,7 @@ msgstr "Naam"
|
|||
msgid "Name 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"
|
||||
msgstr "Toon voortgang"
|
||||
|
||||
|
|
@ -151,14 +163,14 @@ msgstr "Inklappen/Uitklappen alles"
|
|||
msgid "Show/Hide critical path"
|
||||
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
|
||||
msgid "showing 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
|
||||
msgid "Month"
|
||||
msgstr "Maand"
|
||||
|
|
@ -171,11 +183,11 @@ msgstr "Toon/Verberg resources"
|
|||
msgid "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"
|
||||
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"
|
||||
msgstr "Verberg kritieke pad"
|
||||
|
||||
|
|
@ -183,7 +195,7 @@ msgstr "Verberg kritieke pad"
|
|||
msgid "Day"
|
||||
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"
|
||||
msgstr "Verberg gerapporteerde uren"
|
||||
|
||||
|
|
@ -204,7 +216,7 @@ msgid "Hour"
|
|||
msgstr "Uur"
|
||||
|
||||
#: 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"
|
||||
msgstr "Graphics"
|
||||
|
||||
|
|
@ -216,7 +228,7 @@ msgstr "Set Start-Start"
|
|||
msgid "See 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"
|
||||
msgstr "Inzoomen"
|
||||
|
||||
|
|
@ -232,10 +244,10 @@ msgstr "Alle"
|
|||
msgid "Refresh"
|
||||
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"
|
||||
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"
|
||||
msgstr "Verberg voortgang"
|
||||
|
|
|
|||
253
ganttzk/src/main/resources/i18n/pl.po
Normal file
253
ganttzk/src/main/resources/i18n/pl.po
Normal 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"
|
||||
|
|
@ -40,17 +40,17 @@ resourcesLoadPanel = self;
|
|||
<separator/>
|
||||
<hbox id="additionalFilterInsertionPoint1" />
|
||||
<separator/>
|
||||
${ganttzk_i18n:_('Show')}:
|
||||
<listbox id="listFilters" mold="select" rows="1" width="100px"
|
||||
<label id="filterByNameLabel">${ganttzk_i18n:_('Page')}:</label>
|
||||
<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}"
|
||||
selectedIndex="0"
|
||||
onSelect="resourcesLoadPanel.setFilter(self.selectedItem.value);">
|
||||
</listbox>
|
||||
<separator/>
|
||||
<label id="filterByNameLabel">${ganttzk_i18n:_('Name filter')}:</label>
|
||||
<combobox id="filterByNameCombo" width="50px"
|
||||
onChange="resourcesLoadPanel.onSelectFilterByName(self)" />
|
||||
<separator/>
|
||||
<hbox id="additionalFilterInsertionPoint2" />
|
||||
</hbox>
|
||||
</north>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.libreplan</groupId>
|
||||
<artifactId>libreplan</artifactId>
|
||||
<version>1.2.2</version>
|
||||
<version>1.2.3</version>
|
||||
</parent>
|
||||
<artifactId>libreplan-business</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
<plugin>
|
||||
<groupId>org.liquibase</groupId>
|
||||
<artifactId>liquibase-maven-plugin</artifactId>
|
||||
<version>2.0-rc7</version>
|
||||
<version>2.0.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-resources</phase>
|
||||
|
|
@ -162,7 +162,7 @@
|
|||
<plugin>
|
||||
<groupId>org.liquibase</groupId>
|
||||
<artifactId>liquibase-maven-plugin</artifactId>
|
||||
<version>2.0-rc7</version>
|
||||
<version>2.0.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-resources</phase>
|
||||
|
|
@ -205,7 +205,7 @@
|
|||
<pluginExecutionFilter>
|
||||
<groupId>org.liquibase</groupId>
|
||||
<artifactId>liquibase-maven-plugin</artifactId>
|
||||
<versionRange>[2.0-rc7,)</versionRange>
|
||||
<versionRange>[2.0.4,)</versionRange>
|
||||
<goals>
|
||||
<goal>update</goal>
|
||||
</goals>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
* This file is part of LibrePlan
|
||||
*
|
||||
* 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
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
|
@ -19,24 +20,29 @@
|
|||
|
||||
package org.libreplan.business.common;
|
||||
|
||||
import org.libreplan.business.common.daos.IConfigurationDAO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.apache.commons.lang.BooleanUtils;
|
||||
|
||||
|
||||
/**
|
||||
* It contains the compiling option to disable the warning changing default
|
||||
* password and implements of singleton pattern.
|
||||
* This is a singleton that contains the compilation options passed from Maven.
|
||||
*
|
||||
* 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 Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public class Configuration {
|
||||
|
||||
private static final Configuration singleton = new Configuration();
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
||||
private Boolean defaultPasswordsControl;
|
||||
|
||||
private Boolean exampleUsersDisabled;
|
||||
|
||||
private Configuration() {
|
||||
}
|
||||
|
||||
|
|
@ -61,4 +67,19 @@ public class Configuration {
|
|||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -91,6 +91,12 @@ public class Configuration extends BaseEntity {
|
|||
|
||||
private Boolean allowToGatherUsageStatsEnabled = false;
|
||||
|
||||
/**
|
||||
* Currency code according to ISO-4217 (3 letters)
|
||||
*/
|
||||
private String currencyCode = "EUR";
|
||||
private String currencySymbol = "€";
|
||||
|
||||
public void setDefaultCalendar(BaseCalendar defaultCalendar) {
|
||||
this.defaultCalendar = defaultCalendar;
|
||||
}
|
||||
|
|
@ -363,4 +369,22 @@ public class Configuration extends BaseEntity {
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ import org.hibernate.validator.NotEmpty;
|
|||
*/
|
||||
public class InfoComponent {
|
||||
|
||||
private String code;
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
|
@ -36,15 +34,6 @@ public class 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) {
|
||||
this.name = name;
|
||||
}
|
||||
|
|
@ -64,7 +53,6 @@ public class InfoComponent {
|
|||
|
||||
public InfoComponent copy() {
|
||||
InfoComponent result = new InfoComponent();
|
||||
result.setCode(getCode());
|
||||
result.setName(getName());
|
||||
result.setDescription(getDescription());
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ import org.libreplan.business.workreports.entities.WorkReportLine;
|
|||
public abstract class OrderElement extends IntegrationEntity implements
|
||||
ICriterionRequirable, ITreeNode<OrderElement> {
|
||||
|
||||
protected InfoComponent infoComponent = new InfoComponent();
|
||||
protected InfoComponentWithCode infoComponent = new InfoComponentWithCode();
|
||||
|
||||
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
|
||||
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
|
||||
.addAll(synchronizationForSchedulingPoint(schedulingDataForVersion));
|
||||
} else if (isSuperElementPartialOrCompletelyScheduled()) {
|
||||
|
|
@ -304,6 +314,15 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
if (wasASchedulingPoint()) {
|
||||
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
|
||||
.add(synchronizationForSuperelement(schedulingDataForVersion));
|
||||
} else if (schedulingState.isNoScheduled()) {
|
||||
|
|
@ -331,6 +350,10 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
.getSchedulingStateType();
|
||||
}
|
||||
|
||||
protected boolean currentTaskSourceIsNotTheSame() {
|
||||
return getOnDBTaskSource() != getTaskSource();
|
||||
}
|
||||
|
||||
private List<TaskSourceSynchronization> childrenSynchronizations() {
|
||||
List<TaskSourceSynchronization> childrenOfGroup = new ArrayList<TaskSourceSynchronization>();
|
||||
for (OrderElement orderElement : getSomewhatScheduledOrderElements()) {
|
||||
|
|
@ -1267,9 +1290,9 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
}
|
||||
|
||||
@Valid
|
||||
public InfoComponent getInfoComponent() {
|
||||
public InfoComponentWithCode getInfoComponent() {
|
||||
if (infoComponent == null) {
|
||||
infoComponent = new InfoComponent();
|
||||
infoComponent = new InfoComponentWithCode();
|
||||
}
|
||||
return infoComponent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -209,9 +209,40 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
|
||||
public static AllocationsSpecified allocating(
|
||||
List<ResourcesPerDayModification> resourceAllocations) {
|
||||
sortResourceAllocations(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,
|
||||
IntraDayDate endExclusive) {
|
||||
Validate.isTrue(startInclusive.compareTo(endExclusive) <= 0,
|
||||
|
|
@ -2123,7 +2154,7 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
getDayAssignmentsState().detachAssignments();
|
||||
}
|
||||
|
||||
void associateAssignmentsToResource() {
|
||||
public void associateAssignmentsToResource() {
|
||||
for (DayAssignment dayAssignment : getAssignments()) {
|
||||
dayAssignment.associateToResource();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -73,6 +73,7 @@ import org.libreplan.business.workingday.ResourcesPerDay;
|
|||
|
||||
/**
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public class Task extends TaskElement implements ITaskPositionConstrained {
|
||||
|
||||
|
|
@ -1218,4 +1219,10 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
|
|||
public void resetStatus() {
|
||||
this.currentStatus = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyTaskWithConstraint(PositionConstraintType type) {
|
||||
return getPositionConstraint().getConstraintType().equals(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -63,6 +63,7 @@ import org.libreplan.business.workingday.ResourcesPerDay;
|
|||
|
||||
/**
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public abstract class TaskElement extends BaseEntity {
|
||||
|
||||
|
|
@ -769,4 +770,6 @@ public abstract class TaskElement extends BaseEntity {
|
|||
return null;
|
||||
}
|
||||
|
||||
public abstract boolean isAnyTaskWithConstraint(PositionConstraintType type);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -44,6 +44,7 @@ import org.libreplan.business.workingday.IntraDayDate;
|
|||
/**
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public class TaskGroup extends TaskElement {
|
||||
|
||||
|
|
@ -376,4 +377,15 @@ public class TaskGroup extends TaskElement {
|
|||
public void resetStatus() {
|
||||
this.isFinished = this.isInProgress = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyTaskWithConstraint(PositionConstraintType type) {
|
||||
for (TaskElement taskElement : getChildren()) {
|
||||
if (taskElement.isAnyTaskWithConstraint(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -43,6 +43,7 @@ import org.libreplan.business.workingday.IntraDayDate;
|
|||
/**
|
||||
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public class TaskMilestone extends TaskElement implements ITaskPositionConstrained {
|
||||
|
||||
|
|
@ -225,4 +226,9 @@ public class TaskMilestone extends TaskElement implements ITaskPositionConstrain
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyTaskWithConstraint(PositionConstraintType type) {
|
||||
return getPositionConstraint().getConstraintType().equals(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,11 @@ public abstract class ResourcesPerDayModification extends
|
|||
return genericAllocation.createEffortDistributor(getResources());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecific() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class OnSpecificAllocation extends
|
||||
|
|
@ -194,6 +199,11 @@ public abstract class ResourcesPerDayModification extends
|
|||
return resourceAllocation.createEffortDistributor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecific() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static ResourcesPerDayModification create(
|
||||
|
|
@ -319,4 +329,6 @@ public abstract class ResourcesPerDayModification extends
|
|||
getBeingModified().getNonConsolidatedResourcePerDay());
|
||||
}
|
||||
|
||||
public abstract boolean isSpecific();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
|
|
@ -89,8 +88,19 @@ public abstract class UntilFillingHoursAllocator {
|
|||
IntraDayDate candidate = untilAllocating(dateFromWhichToAllocate,
|
||||
each.allocation, each.duration);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -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(
|
||||
Entry<ResourcesPerDayModification, List<DayAssignment>> entry,
|
||||
ResourcesPerDayModification resourcesPerDayModification,
|
||||
IntraDayDate resultDate) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ResourceAllocation<T> allocation = (ResourceAllocation<T>) entry
|
||||
.getKey().getBeingModified();
|
||||
ResourcesPerDay resourcesPerDay = entry.getKey().getGoal();
|
||||
ResourceAllocation<T> allocation = (ResourceAllocation<T>) resourcesPerDayModification
|
||||
.getBeingModified();
|
||||
ResourcesPerDay resourcesPerDay = resourcesPerDayModification.getGoal();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<T> value = (List<T>) entry.getValue();
|
||||
List<T> value = (List<T>) resultAssignments
|
||||
.get(resourcesPerDayModification);
|
||||
setNewDataForAllocation(allocation, resultDate, resourcesPerDay,
|
||||
value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ public class HoursWorkedPerResourceDTO implements Comparable {
|
|||
|
||||
private Date date;
|
||||
|
||||
private LocalTime clockStart;
|
||||
private String clockStart;
|
||||
|
||||
private LocalTime clockFinish;
|
||||
private String clockFinish;
|
||||
|
||||
private EffortDuration effort;
|
||||
|
||||
|
|
@ -59,8 +59,12 @@ public class HoursWorkedPerResourceDTO implements Comparable {
|
|||
|
||||
this.workerName = resource.getName();
|
||||
this.date = workReportLine.getDate();
|
||||
this.clockStart = workReportLine.getClockStart();
|
||||
this.clockFinish = workReportLine.getClockFinish();
|
||||
LocalTime clockStart = workReportLine.getClockStart();
|
||||
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.orderElementCode = workReportLine.getOrderElement().getCode();
|
||||
this.orderElementName = workReportLine.getOrderElement().getName();
|
||||
|
|
@ -98,19 +102,19 @@ public class HoursWorkedPerResourceDTO implements Comparable {
|
|||
this.effort = effort;
|
||||
}
|
||||
|
||||
public LocalTime getClockStart() {
|
||||
public String getClockStart() {
|
||||
return clockStart;
|
||||
}
|
||||
|
||||
public void setClockStart(LocalTime clockStart) {
|
||||
public void setClockStart(String clockStart) {
|
||||
this.clockStart = clockStart;
|
||||
}
|
||||
|
||||
public LocalTime getClockFinish() {
|
||||
public String getClockFinish() {
|
||||
return clockFinish;
|
||||
}
|
||||
|
||||
public void setClockFinish(LocalTime clockFinish) {
|
||||
public void setClockFinish(String clockFinish) {
|
||||
this.clockFinish = clockFinish;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
* This file is part of LibrePlan
|
||||
*
|
||||
* Copyright (C) 2011 ComtecSF, S.L.
|
||||
* 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
|
||||
|
|
@ -28,6 +29,7 @@ import java.util.Locale;
|
|||
*
|
||||
* @author Cristina Alavarino Perez <cristina.alvarino@comtecsf.es>
|
||||
* @author Ignacio Diaz Teijido <ignacio.diaz@comtecsf.es>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public enum Language {
|
||||
|
||||
|
|
@ -39,7 +41,8 @@ public enum Language {
|
|||
PORTUGUESE_LANGUAGE("Português", new Locale("pt")),
|
||||
ITALIAN_LANGUAGE("Italiano", new Locale("it")),
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -354,14 +354,6 @@ public abstract class OrderElementTemplate extends BaseEntity implements
|
|||
this.deadlineAsDaysFromBeginning = days;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return getInfoComponent().getCode();
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
getInfoComponent().setCode(code);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return getInfoComponent().getDescription();
|
||||
}
|
||||
|
|
@ -384,7 +376,6 @@ public abstract class OrderElementTemplate extends BaseEntity implements
|
|||
}
|
||||
|
||||
protected void copyTo(OrderElementTemplate result) {
|
||||
result.setCode(getCode());
|
||||
result.setName(getName());
|
||||
result.setDescription(getDescription());
|
||||
result.setDeadlineAsDaysFromBeginning(getDeadlineAsDaysFromBeginning());
|
||||
|
|
|
|||
|
|
@ -186,12 +186,14 @@
|
|||
columnDataType="BOOLEAN" />
|
||||
</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>
|
||||
<modifyDataType tableName="order_element" columnName="description" newDataType="TEXT" />
|
||||
</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>
|
||||
<modifyDataType tableName="order_element_template" columnName="description" newDataType="TEXT" />
|
||||
</changeSet>
|
||||
|
|
@ -223,6 +225,18 @@
|
|||
<renameTable oldTableName="end_date_communication_to_customer" newTableName="end_date_communication" />
|
||||
</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">
|
||||
<comment>add budget column to order_line</comment>
|
||||
<addColumn tableName="order_line">
|
||||
|
|
@ -318,4 +332,31 @@
|
|||
<dropColumn tableName="order_element" columnName="sum_charged_effort_id"/>
|
||||
</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>
|
||||
|
|
|
|||
|
|
@ -144,7 +144,10 @@
|
|||
factory-method="getInstance"
|
||||
lazy-init="false">
|
||||
<property name="defaultPasswordsControl">
|
||||
<value>${default.passwordsControl}</value>
|
||||
<value>${default.passwordsControl}</value>
|
||||
</property>
|
||||
<property name="exampleUsersDisabled">
|
||||
<value>${default.exampleUsersDisabled}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@
|
|||
<property name="scenariosVisible" not-null="true"
|
||||
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">
|
||||
<property name="ldapHost" column="ldap_Host"/>
|
||||
<property name="ldapPort" column="ldap_port"/>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
</generator>
|
||||
</id>
|
||||
<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="description" access="field" type="text" />
|
||||
<property name="code" access="field" unique="true" />
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
<component name="infoComponent" class="org.libreplan.business.orders.entities.InfoComponent">
|
||||
<property name="name" access="field" />
|
||||
<property name="description" access="field" type="text" />
|
||||
<property name="code" access="field"/>
|
||||
</component>
|
||||
<property name="startAsDaysFromBeginning"
|
||||
column="start_as_days_from_beginning" />
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
package org.libreplan.business.test.planner.entities;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.getCurrentArguments;
|
||||
import static org.easymock.EasyMock.isA;
|
||||
|
|
@ -778,7 +777,7 @@ public class GenericResourceAllocationTest {
|
|||
givenGenericResourceAllocationForTask(task);
|
||||
givenWorkersWithLoads(8, 6, 2);
|
||||
IntraDayDate end = ResourceAllocation.allocating(
|
||||
singletonList(ResourcesPerDayModification.create(
|
||||
Arrays.asList(ResourcesPerDayModification.create(
|
||||
genericResourceAllocation,
|
||||
ResourcesPerDay.amount(new BigDecimal(1)), workers)))
|
||||
.untilAllocating(hours(12));
|
||||
|
|
@ -798,7 +797,7 @@ public class GenericResourceAllocationTest {
|
|||
givenGenericResourceAllocationForTask(task);
|
||||
givenWorkersWithLoads(8, 2, 6);
|
||||
IntraDayDate end = ResourceAllocation.allocating(
|
||||
singletonList(ResourcesPerDayModification.create(
|
||||
Arrays.asList(ResourcesPerDayModification.create(
|
||||
genericResourceAllocation, ResourcesPerDay.amount(1),
|
||||
workers))).untilAllocating(hours(16));
|
||||
assertThat(end.getDate(), equalTo(start.plusDays(2)));
|
||||
|
|
|
|||
|
|
@ -412,12 +412,11 @@ public class UntilFillingHoursAllocatorTest {
|
|||
givenSpecificAllocations(ResourcesPerDay.amount(1), ResourcesPerDay
|
||||
.amount(1));
|
||||
ResourceAllocation.allocating(allocations).untilAllocating(hours(64));
|
||||
ResourceAllocation<?> generic = allocations.get(0)
|
||||
ResourceAllocation<?> firstSpecific = allocations.get(0)
|
||||
.getBeingModified();
|
||||
ResourceAllocation<?> firstSpecific = allocations.get(1)
|
||||
.getBeingModified();
|
||||
ResourceAllocation<?> secondSpecific = allocations.get(2)
|
||||
ResourceAllocation<?> secondSpecific = allocations.get(1)
|
||||
.getBeingModified();
|
||||
ResourceAllocation<?> generic = allocations.get(2).getBeingModified();
|
||||
assertThat(generic.getAssignments(), haveHours(16, 16));
|
||||
assertThat(firstSpecific.getAssignments(), haveHours(8, 8));
|
||||
assertThat(secondSpecific.getAssignments(), haveHours(8, 8));
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.libreplan</groupId>
|
||||
<artifactId>libreplan</artifactId>
|
||||
<version>1.2.2</version>
|
||||
<version>1.2.3</version>
|
||||
</parent>
|
||||
<artifactId>libreplan-webapp</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
|
@ -126,6 +126,9 @@
|
|||
<copy todir="src/main/webapp/help/nl" failonerror="false">
|
||||
<fileset dir="../doc/src/user/en/html"/>
|
||||
</copy>
|
||||
<copy todir="src/main/webapp/help/pl" failonerror="false">
|
||||
<fileset dir="../doc/src/user/en/html"/>
|
||||
</copy>
|
||||
</tasks>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
|
@ -434,5 +437,10 @@
|
|||
<groupId>org.jgrapht</groupId>
|
||||
<artifactId>jgrapht-jdk1.5</artifactId>
|
||||
</dependency>
|
||||
<!-- jqPlot -->
|
||||
<dependency>
|
||||
<groupId>br.com.digilabs.jqplot</groupId>
|
||||
<artifactId>jqplot4java</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -9,8 +9,8 @@
|
|||
<parameter name="labels" class="java.lang.String"/>
|
||||
<field name="workerName" class="java.lang.String"/>
|
||||
<field name="date" class="java.util.Date"/>
|
||||
<field name="clockStart" class="java.util.Date"/>
|
||||
<field name="clockFinish" class="java.util.Date"/>
|
||||
<field name="clockStart" class="java.lang.String"/>
|
||||
<field name="clockFinish" class="java.lang.String"/>
|
||||
<field name="self" class="org.libreplan.business.reports.dtos.HoursWorkedPerResourceDTO"/>
|
||||
<field name="effort" class="org.libreplan.business.workingday.EffortDuration"/>
|
||||
<field name="orderElementCode" class="java.lang.String"/>
|
||||
|
|
@ -343,7 +343,7 @@
|
|||
<rightPen lineWidth="1.0"/>
|
||||
</box>
|
||||
<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 isBlankWhenNull="true">
|
||||
<reportElement x="116" y="0" width="70" height="30"/>
|
||||
|
|
@ -355,7 +355,7 @@
|
|||
<rightPen lineWidth="1.0"/>
|
||||
</box>
|
||||
<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 isBlankWhenNull="true">
|
||||
<reportElement x="0" y="0" width="116" height="15"/>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -7,10 +7,9 @@
|
|||
<parameter name="logo" class="java.lang.String"/>
|
||||
<parameter name="criteria" 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="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="orderElementCode" class="java.lang.String"/>
|
||||
<field name="descriptionValues" class="java.lang.String"/>
|
||||
|
|
@ -90,12 +89,12 @@
|
|||
</textElement>
|
||||
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumTotalHours}]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField pattern="###0.00 €;-###0.00 €">
|
||||
<textField>
|
||||
<reportElement x="422" y="2" width="119" height="20"/>
|
||||
<textElement textAlignment="Right" verticalAlignment="Middle">
|
||||
<font isBold="true"/>
|
||||
</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>
|
||||
</band>
|
||||
</groupFooter>
|
||||
|
|
@ -137,10 +136,10 @@
|
|||
<textElement textAlignment="Right" verticalAlignment="Middle"/>
|
||||
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumHoursPerTask}]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true">
|
||||
<textField isBlankWhenNull="true">
|
||||
<reportElement x="422" y="2" width="119" height="20"/>
|
||||
<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>
|
||||
</band>
|
||||
</groupFooter>
|
||||
|
|
@ -230,10 +229,10 @@
|
|||
</groupHeader>
|
||||
<groupFooter>
|
||||
<band height="28">
|
||||
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true">
|
||||
<textField isBlankWhenNull="true">
|
||||
<reportElement x="422" y="2" width="119" height="20"/>
|
||||
<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>
|
||||
<reportElement x="71" y="2" width="258" height="20"/>
|
||||
|
|
@ -266,20 +265,20 @@
|
|||
</groupHeader>
|
||||
<groupFooter>
|
||||
<band height="15">
|
||||
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true">
|
||||
<textField isBlankWhenNull="true">
|
||||
<reportElement x="423" y="0" width="119" height="14"/>
|
||||
<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 pattern="###0.00 h">
|
||||
<reportElement x="330" y="0" width="93" height="14"/>
|
||||
<textElement textAlignment="Right" verticalAlignment="Middle"/>
|
||||
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumHoursPerWorkerandCost}]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField pattern="###0.00 €/h;-###0.00 €/h" isBlankWhenNull="true">
|
||||
<textField isBlankWhenNull="true">
|
||||
<reportElement x="252" y="0" width="78" height="14"/>
|
||||
<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 isBlankWhenNull="true">
|
||||
<reportElement x="110" y="0" width="141" height="14"/>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
# Locale for ordersCostPerResourcesReport.jrxml
|
||||
title = Project report
|
||||
subtitle = Costs by Resource
|
||||
date.start = Starting date:
|
||||
date.end = Ending date:
|
||||
criteria = Criteria :
|
||||
labels = Labels :
|
||||
headers.column1 = Type of hours
|
||||
headers.column2 = Date
|
||||
headers.column3 = Salary
|
||||
headers.column4 = Hours
|
||||
headers.column5 = Costs
|
||||
total.task = Total per task:
|
||||
total.worker = Total per worker:
|
||||
total = Project Total:
|
||||
page = page
|
||||
of = of
|
||||
title = Informe del proyecto
|
||||
subtitle = Costes por recurso
|
||||
date.start = Fecha de inicio:
|
||||
date.end = Fecha de fin:
|
||||
criteria = Criterios:
|
||||
labels = Etiquetas:
|
||||
headers.column1 = Tipo de horas
|
||||
headers.column2 = Fecha
|
||||
headers.column3 = Salario
|
||||
headers.column4 = Horas
|
||||
headers.column5 = Costes
|
||||
total.task = Total por tarea:
|
||||
total.worker = Total por trabajador:
|
||||
total = Total por proyecto:
|
||||
page = página
|
||||
of = de
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
<parameter name="endingDate" class="java.util.Date"/>
|
||||
<parameter name="status" 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="code" class="java.lang.String"/>
|
||||
<field name="name" class="java.lang.String"/>
|
||||
|
|
@ -156,7 +157,7 @@
|
|||
<textField isBlankWhenNull="true">
|
||||
<reportElement x="434" y="14" width="72" height="15"/>
|
||||
<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>
|
||||
</band>
|
||||
</groupFooter>
|
||||
|
|
@ -291,7 +292,7 @@
|
|||
<rightPen lineWidth="1.0"/>
|
||||
</box>
|
||||
<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 isBlankWhenNull="true">
|
||||
<reportElement x="390" y="0" width="65" height="73"/>
|
||||
|
|
@ -303,7 +304,7 @@
|
|||
<rightPen lineWidth="1.0"/>
|
||||
</box>
|
||||
<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 isBlankWhenNull="true">
|
||||
<reportElement x="520" y="0" width="60" height="73">
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -836,4 +836,28 @@ public class ConfigurationController extends GenericForwardComposer {
|
|||
.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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -25,12 +25,16 @@ import static org.libreplan.web.I18nHelper._;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Currency;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
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.entities.BaseCalendar;
|
||||
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 static Map<String, String> currencies = getAllCurrencies();
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
||||
|
|
@ -557,4 +563,39 @@ public class ConfigurationModel implements IConfigurationModel {
|
|||
.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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
package org.libreplan.web.common;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.libreplan.business.calendars.entities.BaseCalendar;
|
||||
import org.libreplan.business.common.entities.EntityNameEnum;
|
||||
|
|
@ -153,4 +154,13 @@ public interface IConfigurationModel {
|
|||
|
||||
void setAllowToGatherUsageStatsEnabled(
|
||||
boolean allowToGatherUsageStatsEnabled);
|
||||
|
||||
Set<String> getCurrencies();
|
||||
|
||||
String getCurrencySymbol(String currencyCode);
|
||||
|
||||
String getCurrencyCode();
|
||||
|
||||
void setCurrency(String currencyCode);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ package org.libreplan.web.common;
|
|||
import static org.libreplan.web.I18nHelper._;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
|
@ -125,9 +124,4 @@ public abstract class IntegrationEntityModel implements IIntegrationEntityModel
|
|||
return entitySequenceDAO;
|
||||
}
|
||||
|
||||
public Date getCurrentExpiringDate() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -482,7 +482,11 @@ public class TemplateModel implements ITemplateModel {
|
|||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public boolean isUserAdmin() {
|
||||
return UserUtil.getUserFromSession().isAdministrator();
|
||||
User user = UserUtil.getUserFromSession();
|
||||
if(user == null) {
|
||||
return false;
|
||||
}
|
||||
return user.isAdministrator();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ package org.libreplan.web.common;
|
|||
import static org.libreplan.web.I18nHelper._;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
|
|
@ -31,6 +32,9 @@ import java.util.List;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
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.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
|
|
@ -62,6 +66,12 @@ public class Util {
|
|||
|
||||
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() {
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -53,9 +53,15 @@ import org.zkoss.zul.SimpleListModel;
|
|||
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 Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class BandboxMultipleSearch extends HtmlMacroComponent {
|
||||
|
||||
|
|
@ -168,6 +174,7 @@ public class BandboxMultipleSearch extends HtmlMacroComponent {
|
|||
}
|
||||
}
|
||||
bandbox.close();
|
||||
Events.postEvent(Events.ON_CHANGE, this, null);
|
||||
}
|
||||
|
||||
private void searchMultipleFilters() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -35,11 +35,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
|
||||
/**
|
||||
* Implements all the methods needed to search the criterion to filter the
|
||||
* resources. Provides multiples criterions to filter like {@link Criterion},
|
||||
* {@link Category} or filter by name or nif.
|
||||
* resources. Provides multiples criteria to filter like {@link Criterion} or
|
||||
* {@link CostCategory}.
|
||||
*
|
||||
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
|
||||
*/
|
||||
|
||||
public class ResourcesMultipleFiltersFinder extends MultipleFiltersFinder {
|
||||
|
||||
@Autowired
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public abstract class TemplateFinder<T extends OrderElementTemplate> extends
|
|||
}
|
||||
|
||||
protected String extractStringFor(T template) {
|
||||
return template.getName() + " (" + template.getCode() + ")";
|
||||
return template.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -92,7 +92,6 @@ public abstract class TemplateFinder<T extends OrderElementTemplate> extends
|
|||
|
||||
protected void generateColumnsForRenderer(Listitem item, T template) {
|
||||
final Listcell codeCell = new Listcell();
|
||||
codeCell.setLabel(template.getCode());
|
||||
codeCell.setParent(item);
|
||||
codeCell.setStyle("width:200px");
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -38,10 +38,8 @@ import org.libreplan.business.costcategories.entities.CostCategory;
|
|||
import org.libreplan.business.costcategories.entities.HourCost;
|
||||
import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
|
||||
import org.libreplan.web.common.BaseCRUDController;
|
||||
import org.libreplan.web.common.ConstraintChecker;
|
||||
import org.libreplan.web.common.Level;
|
||||
import org.libreplan.web.common.Util;
|
||||
import org.libreplan.web.util.ValidationExceptionPrinter;
|
||||
import org.libreplan.web.workreports.WorkReportCRUDController;
|
||||
import org.zkoss.ganttz.util.ComponentsFinder;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
|
|
@ -305,6 +303,7 @@ public class CostCategoryCRUDController extends BaseCRUDController<CostCategory>
|
|||
Decimalbox boxCost = new Decimalbox();
|
||||
bindDecimalboxCost(boxCost, (HourCost) row.getValue());
|
||||
boxCost.setConstraint("no empty:" + _("cannot be null or empty"));
|
||||
boxCost.setFormat(Util.getMoneyFormat());
|
||||
row.appendChild(boxCost);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,4 +141,13 @@ public class TypeOfWorkHoursCRUDController extends BaseCRUDController<TypeOfWork
|
|||
protected boolean beforeDeleting(TypeOfWorkHours typeOfWorkHours) {
|
||||
return !isReferencedByOtherEntities(typeOfWorkHours);
|
||||
}
|
||||
|
||||
public String getCurrencySymbol() {
|
||||
return Util.getCurrencySymbol();
|
||||
}
|
||||
|
||||
public String getMoneyFormat() {
|
||||
return Util.getMoneyFormat();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,29 +21,40 @@ package org.libreplan.web.dashboard;
|
|||
|
||||
import static org.libreplan.web.I18nHelper._;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
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.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.planner.entities.TaskStatusEnum;
|
||||
import org.libreplan.web.common.Util;
|
||||
import org.libreplan.web.dashboard.DashboardModel.Interval;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.zkoss.zk.ui.util.Clients;
|
||||
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.PieModel;
|
||||
import org.zkoss.zul.SimpleCategoryModel;
|
||||
import org.zkoss.zul.SimplePieModel;
|
||||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Label;
|
||||
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 Diego Pino García <dpino@igalia.com>
|
||||
*
|
||||
* Controller for dashboardfororder view
|
||||
*/
|
||||
@Component
|
||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
|
|
@ -53,12 +64,10 @@ public class DashboardController extends GenericForwardComposer {
|
|||
|
||||
private Window dashboardWindow;
|
||||
|
||||
private Chart progressKPIglobalProgressChart;
|
||||
private Chart progressKPItaskStatusChart;
|
||||
private Chart progressKPItaskDeadlineViolationStatusChart;
|
||||
private Chart timeKPImarginWithDeadlineChart;
|
||||
private Chart timeKPIEstimationAccuracyChart;
|
||||
private Chart timeKPILagInTaskCompletionChart;
|
||||
private Grid gridTasksSummary;
|
||||
private Grid gridMarginWithDeadline;
|
||||
|
||||
private org.zkoss.zk.ui.Component costStatus;
|
||||
|
||||
private Div projectDashboardChartsDiv;
|
||||
private Div projectDashboardNoTasksWarningDiv;
|
||||
|
|
@ -69,171 +78,415 @@ public class DashboardController extends GenericForwardComposer {
|
|||
@Override
|
||||
public void doAfterCompose(org.zkoss.zk.ui.Component comp) throws Exception {
|
||||
super.doAfterCompose(comp);
|
||||
this.dashboardWindow = (Window)comp;
|
||||
this.dashboardWindow = (Window) comp;
|
||||
self.setAttribute("controller", this);
|
||||
Util.createBindingsFor(this.dashboardWindow);
|
||||
}
|
||||
|
||||
public void setCurrentOrder(Order order) {
|
||||
dashboardModel.setCurrentOrder(order);
|
||||
if(dashboardModel.tasksAvailable()) {
|
||||
this.reloadCharts();
|
||||
if (dashboardModel.tasksAvailable()) {
|
||||
showCharts();
|
||||
} else {
|
||||
this.hideChartsAndShowWarningMessage();
|
||||
hideCharts();
|
||||
}
|
||||
if (this.dashboardWindow != null) {
|
||||
Util.reloadBindings(this.dashboardWindow);
|
||||
renderGlobalProgress();
|
||||
renderTaskStatus();
|
||||
renderTaskCompletationLag();
|
||||
renderTasksSummary();
|
||||
renderDeadlineViolation();
|
||||
renderMarginWithDeadline();
|
||||
renderEstimationAccuracy();
|
||||
renderCostStatus(order);
|
||||
}
|
||||
}
|
||||
|
||||
private void reloadCharts() {
|
||||
generateProgressKPIglobalProgressChart();
|
||||
generateProgressKPItaskStatusChart();
|
||||
generateProgressKPItaskDeadlineViolationStatusChart();
|
||||
generateTimeKPImarginWithDeadlineChart();
|
||||
generateTimeKPIEstimationAccuracyChart();
|
||||
generateTimeKPILagInTaskCompletionChart();
|
||||
private void renderCostStatus(Order order) {
|
||||
CostStatusController costStatusController = getCostStatusController();
|
||||
costStatusController.setOrder(order);
|
||||
costStatusController.render();
|
||||
}
|
||||
|
||||
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);
|
||||
projectDashboardNoTasksWarningDiv.setVisible(true);
|
||||
}
|
||||
|
||||
private void generateTimeKPILagInTaskCompletionChart() {
|
||||
CategoryModel categoryModel;
|
||||
categoryModel = refreshTimeKPILagInTaskCompletionCategoryModel();
|
||||
Font labelFont = new Font("serif", Font.PLAIN, 10);
|
||||
timeKPILagInTaskCompletionChart.setXAxisTickFont(labelFont);
|
||||
Color[] seriesColorMappings = {Color.BLUE};
|
||||
timeKPILagInTaskCompletionChart.setAttribute("series-color-mappings",
|
||||
seriesColorMappings);
|
||||
timeKPILagInTaskCompletionChart.setModel(categoryModel);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
*
|
||||
*/
|
||||
static class GlobalProgress {
|
||||
|
||||
private void generateTimeKPIEstimationAccuracyChart() {
|
||||
CategoryModel categoryModel;
|
||||
categoryModel = refreshTimeKPIEstimationAccuracyCategoryModel();
|
||||
Font labelFont = new Font("serif", Font.PLAIN, 10);
|
||||
timeKPIEstimationAccuracyChart.setXAxisTickFont(labelFont);
|
||||
Color[] seriesColorMappings = {Color.BLUE};
|
||||
timeKPIEstimationAccuracyChart.setAttribute("series-color-mappings",
|
||||
seriesColorMappings);
|
||||
timeKPIEstimationAccuracyChart.setModel(categoryModel);
|
||||
}
|
||||
public static final String ALL_TASKS_HOURS = _("All tasks (hours)");
|
||||
|
||||
public static final String CRITICAL_PATH_HOURS = _("Critical path (hours)");
|
||||
|
||||
public static final String CRITICAL_PATH_DURATION = _("Critical path (duration)");
|
||||
|
||||
private final Map<String, BigDecimal> current = new LinkedHashMap<String, BigDecimal>();
|
||||
|
||||
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));
|
||||
timeKPImarginWithDeadlineChart.setAttribute("range-axis-upper-bound",
|
||||
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;
|
||||
|
||||
public void current(String key, BigDecimal value) {
|
||||
current.put(key, value);
|
||||
}
|
||||
timeKPImarginWithDeadlineChart.setAttribute("series-color-mappings",
|
||||
seriesColorMappings);
|
||||
timeKPImarginWithDeadlineChart.setModel(categoryModel);
|
||||
}
|
||||
|
||||
private void generateProgressKPItaskStatusChart() {
|
||||
PieModel model = refreshProgressKPItaskStatusPieModel();
|
||||
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);
|
||||
public void expected(String key, BigDecimal value) {
|
||||
expected.put(key, value);
|
||||
}
|
||||
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();
|
||||
Iterator<Double> it = values.iterator();
|
||||
for(int ii= DashboardModel.EA_STRETCHES_MIN_VALUE;
|
||||
ii < DashboardModel.EA_STRETCHES_MAX_VALUE;
|
||||
ii += DashboardModel.EA_STRETCHES_PERCENTAGE_STEP) {
|
||||
result.setValue(_("None"), _(String.valueOf(ii)), it.next());
|
||||
/**
|
||||
*
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
*
|
||||
*/
|
||||
static class Series {
|
||||
|
||||
private String label;
|
||||
|
||||
private String color;
|
||||
|
||||
private Series() {
|
||||
|
||||
}
|
||||
result.setValue(_("None"),
|
||||
_(">"+DashboardModel.EA_STRETCHES_MAX_VALUE),
|
||||
it.next());
|
||||
return result;
|
||||
|
||||
public static Series create(String label) {
|
||||
Series series = new Series();
|
||||
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();
|
||||
Iterator<Double> it = values.iterator();
|
||||
for(double ii= DashboardModel.LTC_STRETCHES_MIN_VALUE;
|
||||
ii < DashboardModel.LTC_STRETCHES_MAX_VALUE;
|
||||
ii += DashboardModel.LTC_STRETCHES_STEP) {
|
||||
result.setValue(_("None"), _(String.valueOf(ii)), it.next());
|
||||
/**
|
||||
*
|
||||
* @author Diego Pino García<dpino@igalia.com>
|
||||
*
|
||||
*/
|
||||
static class TaskCompletationData {
|
||||
|
||||
private final IDashboardModel dashboardModel;
|
||||
|
||||
private Map<Interval, Integer> taskCompletationData;
|
||||
|
||||
private TaskCompletationData(IDashboardModel dashboardModel) {
|
||||
this.dashboardModel = dashboardModel;
|
||||
}
|
||||
result.setValue(_("None"),
|
||||
_(">"+DashboardModel.LTC_STRETCHES_MAX_VALUE),
|
||||
it.next());
|
||||
return result;
|
||||
|
||||
public static TaskCompletationData create(IDashboardModel dashboardModel) {
|
||||
return new TaskCompletationData(dashboardModel);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,14 @@ package org.libreplan.web.dashboard;
|
|||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.Days;
|
||||
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_MAX_VALUE = 0;
|
||||
|
||||
|
||||
private Order currentOrder;
|
||||
private Integer taskCount = null;
|
||||
|
||||
private Map<TaskStatusEnum, BigDecimal> taskStatusStats;
|
||||
private Map<TaskDeadlineViolationStatusEnum, BigDecimal> taskDeadlineViolationStatusStats;
|
||||
private final Map<TaskStatusEnum, BigDecimal> taskStatusStats;
|
||||
private final Map<TaskDeadlineViolationStatusEnum, BigDecimal> taskDeadlineViolationStatusStats;
|
||||
private List<Double> taskEstimationAccuracyHistogram;
|
||||
private BigDecimal marginWithDeadLine;
|
||||
private Integer absoluteMarginWithDeadLine;
|
||||
private List<Double> lagInTaskCompletionHistogram;
|
||||
|
||||
public DashboardModel() {
|
||||
|
|
@ -81,10 +85,11 @@ public class DashboardModel implements IDashboardModel {
|
|||
TaskDeadlineViolationStatusEnum.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentOrder(Order order) {
|
||||
this.currentOrder = order;
|
||||
this.taskCount = null;
|
||||
if(tasksAvailable()) {
|
||||
if (tasksAvailable()) {
|
||||
this.calculateTaskStatusStatistics();
|
||||
this.calculateTaskViolationStatusStatistics();
|
||||
this.calculateMarginWithDeadLine();
|
||||
|
|
@ -94,91 +99,110 @@ public class DashboardModel implements IDashboardModel {
|
|||
}
|
||||
|
||||
/* Progress KPI: "Number of tasks by status" */
|
||||
@Override
|
||||
public BigDecimal getPercentageOfFinishedTasks() {
|
||||
return taskStatusStats.get(TaskStatusEnum.FINISHED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getPercentageOfInProgressTasks() {
|
||||
return taskStatusStats.get(TaskStatusEnum.IN_PROGRESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getPercentageOfReadyToStartTasks() {
|
||||
return taskStatusStats.get(TaskStatusEnum.READY_TO_START);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getPercentageOfBlockedTasks() {
|
||||
return taskStatusStats.get(TaskStatusEnum.BLOCKED);
|
||||
}
|
||||
|
||||
/* Progress KPI: "Deadline violation" */
|
||||
@Override
|
||||
public BigDecimal getPercentageOfOnScheduleTasks() {
|
||||
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.ON_SCHEDULE);
|
||||
return taskDeadlineViolationStatusStats
|
||||
.get(TaskDeadlineViolationStatusEnum.ON_SCHEDULE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getPercentageOfTasksWithViolatedDeadline() {
|
||||
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED);
|
||||
return taskDeadlineViolationStatusStats
|
||||
.get(TaskDeadlineViolationStatusEnum.DEADLINE_VIOLATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getPercentageOfTasksWithNoDeadline() {
|
||||
return taskDeadlineViolationStatusStats.get(TaskDeadlineViolationStatusEnum.NO_DEADLINE);
|
||||
return taskDeadlineViolationStatusStats
|
||||
.get(TaskDeadlineViolationStatusEnum.NO_DEADLINE);
|
||||
}
|
||||
|
||||
/* Progress KPI: "Global Progress of the Project" */
|
||||
public BigDecimal getAdvancePercentageByHours(){
|
||||
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
@Override
|
||||
public BigDecimal getAdvancePercentageByHours() {
|
||||
TaskGroup rootTask = (TaskGroup) getRootTask();
|
||||
if (rootTask == null) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
BigDecimal ratio = rootAsTaskGroup.getProgressAllByNumHours();
|
||||
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
|
||||
return asPercentage(rootTask.getProgressAllByNumHours());
|
||||
}
|
||||
|
||||
public BigDecimal getTheoreticalAdvancePercentageByHoursUntilNow(){
|
||||
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
private BigDecimal asPercentage(BigDecimal value) {
|
||||
return value != null ? value.multiply(BigDecimal.valueOf(100))
|
||||
: BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getExpectedAdvancePercentageByHours() {
|
||||
TaskGroup rootTask = (TaskGroup) getRootTask();
|
||||
if (rootTask == null) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByNumHoursForAllTasksUntilNow();
|
||||
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
|
||||
return asPercentage(rootTask
|
||||
.getTheoreticalProgressByNumHoursForAllTasksUntilNow());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getCriticalPathProgressByNumHours() {
|
||||
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
TaskGroup rootTask = (TaskGroup) getRootTask();
|
||||
if (rootTask == null) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
BigDecimal ratio = rootAsTaskGroup.getCriticalPathProgressByNumHours();
|
||||
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
|
||||
return asPercentage(rootTask.getCriticalPathProgressByNumHours());
|
||||
}
|
||||
|
||||
public BigDecimal getTheoreticalProgressByNumHoursForCriticalPathUntilNow() {
|
||||
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
@Override
|
||||
public BigDecimal getExpectedCriticalPathProgressByNumHours() {
|
||||
TaskGroup rootTask = (TaskGroup) getRootTask();
|
||||
if (rootTask == null) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByNumHoursForCriticalPathUntilNow();
|
||||
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
|
||||
return asPercentage(rootTask
|
||||
.getTheoreticalProgressByNumHoursForCriticalPathUntilNow());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getCriticalPathProgressByDuration() {
|
||||
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
TaskGroup rootTask = (TaskGroup) getRootTask();
|
||||
if (rootTask == null) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
BigDecimal ratio = rootAsTaskGroup.getCriticalPathProgressByDuration();
|
||||
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
|
||||
return asPercentage(rootTask.getCriticalPathProgressByDuration());
|
||||
}
|
||||
|
||||
public BigDecimal getTheoreticalProgressByDurationForCriticalPathUntilNow() {
|
||||
TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask();
|
||||
if (this.getRootTask() == null) {
|
||||
@Override
|
||||
public BigDecimal getExpectedCriticalPathProgressByDuration() {
|
||||
TaskGroup rootTask = (TaskGroup) getRootTask();
|
||||
if (rootTask == null) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByDurationForCriticalPathUntilNow();
|
||||
return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN);
|
||||
return asPercentage(rootTask
|
||||
.getTheoreticalProgressByDurationForCriticalPathUntilNow());
|
||||
}
|
||||
|
||||
/* Time KPI: Margin with deadline */
|
||||
@Override
|
||||
public BigDecimal getMarginWithDeadLine() {
|
||||
return this.marginWithDeadLine;
|
||||
}
|
||||
|
|
@ -207,7 +231,35 @@ public class DashboardModel implements IDashboardModel {
|
|||
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 */
|
||||
@Override
|
||||
public List<Double> getFinishedTasksEstimationAccuracyHistogram() {
|
||||
return this.taskEstimationAccuracyHistogram;
|
||||
}
|
||||
|
|
@ -216,21 +268,19 @@ public class DashboardModel implements IDashboardModel {
|
|||
if (this.getRootTask() == null) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
CalculateFinishedTasksEstimationDeviationVisitor visitor =
|
||||
new CalculateFinishedTasksEstimationDeviationVisitor();
|
||||
CalculateFinishedTasksEstimationDeviationVisitor visitor = new CalculateFinishedTasksEstimationDeviationVisitor();
|
||||
TaskElement rootTask = getRootTask();
|
||||
rootTask.acceptVisitor(visitor);
|
||||
List<Double> deviations = visitor.getDeviations();
|
||||
|
||||
// [-100, -90), [-90, -80), ..., [190, 200), [200, inf)
|
||||
this.taskEstimationAccuracyHistogram = createHistogram(
|
||||
EA_STRETCHES_MIN_VALUE,
|
||||
EA_STRETCHES_MAX_VALUE,
|
||||
EA_STRETCHES_PERCENTAGE_STEP,
|
||||
deviations);
|
||||
EA_STRETCHES_MIN_VALUE, EA_STRETCHES_MAX_VALUE,
|
||||
EA_STRETCHES_PERCENTAGE_STEP, deviations);
|
||||
}
|
||||
|
||||
/* Time KPI: Lead/Lag in task completion */
|
||||
@Override
|
||||
public List<Double> getLagInTaskCompletionHistogram() {
|
||||
return this.lagInTaskCompletionHistogram;
|
||||
}
|
||||
|
|
@ -239,8 +289,7 @@ public class DashboardModel implements IDashboardModel {
|
|||
if (this.getRootTask() == null) {
|
||||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
CalculateFinishedTasksLagInCompletionVisitor visitor =
|
||||
new CalculateFinishedTasksLagInCompletionVisitor();
|
||||
CalculateFinishedTasksLagInCompletionVisitor visitor = new CalculateFinishedTasksLagInCompletionVisitor();
|
||||
TaskElement rootTask = getRootTask();
|
||||
rootTask.acceptVisitor(visitor);
|
||||
List<Double> deviations = visitor.getDeviations();
|
||||
|
|
@ -253,45 +302,228 @@ public class DashboardModel implements IDashboardModel {
|
|||
LTC_STRETCHES_MAX_VALUE = Collections.max(deviations);
|
||||
}
|
||||
LTC_STRETCHES_STEP = (LTC_STRETCHES_MAX_VALUE - LTC_STRETCHES_MIN_VALUE)
|
||||
/LTC_NUMBER_OF_INTERVALS;
|
||||
/ LTC_NUMBER_OF_INTERVALS;
|
||||
this.lagInTaskCompletionHistogram = createHistogram(
|
||||
LTC_STRETCHES_MIN_VALUE,
|
||||
LTC_STRETCHES_MAX_VALUE,
|
||||
LTC_STRETCHES_STEP,
|
||||
deviations);
|
||||
LTC_STRETCHES_MIN_VALUE, LTC_STRETCHES_MAX_VALUE,
|
||||
LTC_STRETCHES_STEP, deviations);
|
||||
}
|
||||
|
||||
private List<Double> createHistogram(double lowBound, double highBound,
|
||||
double intervalStep, List<Double> values) {
|
||||
double variableRange = highBound - lowBound;
|
||||
/* TODO: What if highBound == lowBound? */
|
||||
int numberOfClasses = (int)(variableRange/intervalStep);
|
||||
int[] classes = new int[numberOfClasses+1];
|
||||
int numberOfClasses = (int) (variableRange / intervalStep);
|
||||
int[] classes = new int[numberOfClasses + 1];
|
||||
|
||||
for(Double value: values) {
|
||||
for (Double value : values) {
|
||||
int index;
|
||||
if (value >= highBound) {
|
||||
index = numberOfClasses;
|
||||
} else {
|
||||
index = (int)(numberOfClasses *
|
||||
(((value.doubleValue() - lowBound))/variableRange));
|
||||
index = (int) (numberOfClasses * (((value.doubleValue() - lowBound)) / variableRange));
|
||||
}
|
||||
classes[index]++;
|
||||
}
|
||||
|
||||
List<Double> histogram = new ArrayList<Double>();
|
||||
int numberOfConsideredTasks = values.size();
|
||||
for (int numberOfElementsInClass: classes) {
|
||||
for (int numberOfElementsInClass : classes) {
|
||||
Double relativeCount = new Double(0.0);
|
||||
if (numberOfConsideredTasks > 0) {
|
||||
relativeCount = new Double(1.0*numberOfElementsInClass/
|
||||
numberOfConsideredTasks);
|
||||
relativeCount = new Double(1.0 * numberOfElementsInClass
|
||||
/ numberOfConsideredTasks);
|
||||
}
|
||||
histogram.add(relativeCount);
|
||||
}
|
||||
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() {
|
||||
AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor();
|
||||
TaskElement rootTask = getRootTask();
|
||||
|
|
@ -311,7 +543,8 @@ public class DashboardModel implements IDashboardModel {
|
|||
throw new RuntimeException("Root task is null");
|
||||
}
|
||||
rootTask.acceptVisitor(visitor);
|
||||
Map<TaskDeadlineViolationStatusEnum, Integer> count = visitor.getTaskDeadlineViolationStatusData();
|
||||
Map<TaskDeadlineViolationStatusEnum, Integer> count = visitor
|
||||
.getTaskDeadlineViolationStatusData();
|
||||
mapAbsoluteValuesToPercentages(count, taskDeadlineViolationStatusStats);
|
||||
}
|
||||
|
||||
|
|
@ -342,8 +575,9 @@ public class DashboardModel implements IDashboardModel {
|
|||
}
|
||||
|
||||
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) {
|
||||
return this.taskCount.intValue();
|
||||
|
|
@ -356,6 +590,7 @@ public class DashboardModel implements IDashboardModel {
|
|||
return sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tasksAvailable() {
|
||||
return getRootTask() != null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -21,8 +21,11 @@ package org.libreplan.web.dashboard;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.planner.entities.TaskStatusEnum;
|
||||
import org.libreplan.web.dashboard.DashboardModel.Interval;
|
||||
|
||||
interface IDashboardModel {
|
||||
|
||||
|
|
@ -49,22 +52,31 @@ interface IDashboardModel {
|
|||
/* Progress KPI: "Global Progress of the Project" */
|
||||
BigDecimal getAdvancePercentageByHours();
|
||||
|
||||
BigDecimal getTheoreticalAdvancePercentageByHoursUntilNow();
|
||||
BigDecimal getExpectedAdvancePercentageByHours();
|
||||
|
||||
BigDecimal getCriticalPathProgressByNumHours();
|
||||
|
||||
BigDecimal getTheoreticalProgressByNumHoursForCriticalPathUntilNow();
|
||||
BigDecimal getExpectedCriticalPathProgressByNumHours();
|
||||
|
||||
BigDecimal getCriticalPathProgressByDuration();
|
||||
|
||||
BigDecimal getTheoreticalProgressByDurationForCriticalPathUntilNow();
|
||||
BigDecimal getExpectedCriticalPathProgressByDuration();
|
||||
|
||||
/* Time KPI: "Margin with deadline" */
|
||||
BigDecimal getMarginWithDeadLine();
|
||||
|
||||
Integer getAbsoluteMarginWithDeadLine();
|
||||
|
||||
/* Time KPI: "Estimation accuracy" */
|
||||
List<Double> getFinishedTasksEstimationAccuracyHistogram();
|
||||
|
||||
/* Time KPI: "Lead/Lag in task completion" */
|
||||
List<Double> getLagInTaskCompletionHistogram();
|
||||
|
||||
Map<TaskStatusEnum, Integer> calculateTaskStatus();
|
||||
|
||||
Map<Interval, Integer> calculateTaskCompletation();
|
||||
|
||||
Map<Interval, Integer> calculateEstimationAccuracy();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -554,4 +554,9 @@ public class MaterialsController extends
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getMoneyFormat() {
|
||||
return Util.getMoneyFormat();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,4 +159,8 @@ public class AssignedHoursToOrderElementController extends
|
|||
}
|
||||
}
|
||||
|
||||
public String getCurrencySymbol() {
|
||||
return Util.getCurrencySymbol();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,4 +67,8 @@ public class DetailsOrderElementController extends
|
|||
return !orderElementModel.getOrderElement().isLeaf();
|
||||
}
|
||||
|
||||
public String getMoneyFormat() {
|
||||
return Util.getMoneyFormat();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -33,6 +33,7 @@ import org.libreplan.business.labels.entities.Label;
|
|||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.orders.entities.OrderLineGroup;
|
||||
import org.libreplan.business.planner.entities.PositionConstraintType;
|
||||
import org.libreplan.business.qualityforms.entities.QualityForm;
|
||||
import org.libreplan.business.resources.entities.Criterion;
|
||||
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 Diego Pino García <dpino@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public interface IOrderModel extends IIntegrationEntityModel {
|
||||
|
||||
|
|
@ -139,4 +141,6 @@ public interface IOrderModel extends IIntegrationEntityModel {
|
|||
|
||||
boolean alreadyExistsRepeatedEndDate(Date value);
|
||||
|
||||
boolean isAnyTaskWithConstraint(PositionConstraintType type);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -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.OrderElement;
|
||||
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.users.entities.UserRole;
|
||||
import org.libreplan.web.common.IMessagesForUser;
|
||||
|
|
@ -93,6 +94,7 @@ import org.zkoss.zul.Comboitem;
|
|||
import org.zkoss.zul.ComboitemRenderer;
|
||||
import org.zkoss.zul.Constraint;
|
||||
import org.zkoss.zul.Datebox;
|
||||
import org.zkoss.zul.Decimalbox;
|
||||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Hbox;
|
||||
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 Lorenzo Tilve Álvaro <ltilve@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
@org.springframework.stereotype.Component
|
||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
|
|
@ -398,11 +401,45 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
return result;
|
||||
}
|
||||
|
||||
private void setConstraintsFor(SchedulingMode mode) {
|
||||
initDate.setConstraint(mode == SchedulingMode.FORWARD ? "no empty"
|
||||
: null);
|
||||
deadline.setConstraint(mode == SchedulingMode.BACKWARDS ? "no empty"
|
||||
: null);
|
||||
private void setConstraintsFor(final SchedulingMode mode) {
|
||||
initDate.setConstraint(new Constraint() {
|
||||
|
||||
@Override
|
||||
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) {
|
||||
|
|
@ -1187,7 +1224,7 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
appendDate(row, order.getInitDate());
|
||||
appendDate(row, order.getDeadline());
|
||||
appendCustomer(row, order.getCustomer());
|
||||
appendObject(row, order.getTotalBudget());
|
||||
appendObject(row, Util.addCurrencySymbol(order.getTotalBudget()));
|
||||
appendObject(row, order.getTotalHours());
|
||||
appendObject(row, _(order.getState().toString()));
|
||||
appendOperations(row, order);
|
||||
|
|
@ -1306,8 +1343,8 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
return orderModel.gettooltipText(order);
|
||||
}
|
||||
|
||||
public void reloadTotalBudget(Label txtTotalBudget) {
|
||||
Util.reloadBindings(txtTotalBudget);
|
||||
public void reloadTotalBudget(Decimalbox decimalboxTotalBudget) {
|
||||
Util.reloadBindings(decimalboxTotalBudget);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1685,4 +1722,8 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
reloadGridAskedEndDates();
|
||||
}
|
||||
|
||||
public String getMoneyFormat() {
|
||||
return Util.getMoneyFormat();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -393,6 +393,7 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
|
|||
IOrderElementModel model = orderModel
|
||||
.getOrderElementModel(currentOrderElement);
|
||||
orderElementController.openWindow(model);
|
||||
updateNameFor(currentOrderElement);
|
||||
updateHoursFor(currentOrderElement);
|
||||
updateBudgetFor(currentOrderElement);
|
||||
}
|
||||
|
|
@ -619,6 +620,7 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
|
|||
|
||||
public void refreshRow(Treeitem item) {
|
||||
try {
|
||||
getRenderer().updateNameFor((OrderElement) item.getValue());
|
||||
getRenderer().updateHoursFor((OrderElement) item.getValue());
|
||||
getRenderer().updateBudgetFor((OrderElement) 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();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* 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
|
||||
* 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.OrderLineGroup;
|
||||
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.entities.QualityForm;
|
||||
import org.libreplan.business.requirements.entities.DirectCriterionRequirement;
|
||||
|
|
@ -909,4 +910,12 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isAnyTaskWithConstraint(PositionConstraintType type) {
|
||||
if ((planningState == null) || (planningState.getRootTask() == null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return planningState.getRootTask().isAnyTaskWithConstraint(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* 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
|
||||
* 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() {
|
||||
if (tree.getSelectedCount() == 1) {
|
||||
int page = tree.getActivePage();
|
||||
indent(getSelectedElement());
|
||||
if (tree.getPageCount() > page) {
|
||||
tree.setActivePage(page);
|
||||
}
|
||||
} else {
|
||||
showSelectAnElementError();
|
||||
}
|
||||
|
|
@ -236,9 +240,9 @@ class OrderElementOperations extends TreeElementOperationsController<OrderElemen
|
|||
private int showConfirmCreateTemplateDialog() {
|
||||
try {
|
||||
return Messagebox
|
||||
.show(_("Unsaved changes will be lost. Would you like to continue?",
|
||||
_("Confirm create template"), Messagebox.YES
|
||||
| Messagebox.NO, Messagebox.QUESTION));
|
||||
.show(_("Unsaved changes will be lost. Would you like to continue?"),
|
||||
_("Confirm create template"), Messagebox.OK
|
||||
| Messagebox.CANCEL, Messagebox.QUESTION);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -338,7 +338,8 @@ public abstract class AssignedMaterialsController<T, A> extends GenericForwardCo
|
|||
|
||||
Label lblName = new Label(materialCategory.getName());
|
||||
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;
|
||||
ti.setValue(node);
|
||||
|
|
@ -573,4 +574,12 @@ public abstract class AssignedMaterialsController<T, A> extends GenericForwardCo
|
|||
.getId().equals(material.getUnitType().getId())));
|
||||
}
|
||||
|
||||
public String getCurrencySymbol() {
|
||||
return Util.getCurrencySymbol();
|
||||
}
|
||||
|
||||
public String getMoneyFormat() {
|
||||
return Util.getMoneyFormat();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ import org.libreplan.business.common.entities.ProgressType;
|
|||
import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO;
|
||||
import org.libreplan.business.labels.entities.Label;
|
||||
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.OrderElement;
|
||||
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.IntraDayDate;
|
||||
import org.libreplan.business.workingday.IntraDayDate.PartialDay;
|
||||
import org.libreplan.web.common.Util;
|
||||
import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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 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(
|
||||
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) {
|
||||
ITaskPositionConstrained task = (ITaskPositionConstrained) taskElement;
|
||||
TaskPositionConstraint startConstraint = task
|
||||
|
|
@ -1067,13 +1034,13 @@ public class TaskElementAdapter {
|
|||
if (taskElement.getOrderElement() instanceof Order) {
|
||||
result.append(_("State") + ": ").append(getOrderState());
|
||||
} else {
|
||||
String budget = Util.addCurrencySymbol(getBudget());
|
||||
String moneyCost = Util.addCurrencySymbol(getMoneyCost());
|
||||
result.append(
|
||||
_("Budget: {0}€, Consumed: {1}€ ({2}%)",
|
||||
getBudget(),
|
||||
getMoneyCost(),
|
||||
getMoneyCostBarPercentage().multiply(
|
||||
new BigDecimal(100)))).append(
|
||||
"<br/>");
|
||||
_("Budget: {0}, Consumed: {1} ({2}%)", budget,
|
||||
moneyCost, getMoneyCostBarPercentage()
|
||||
.multiply(new BigDecimal(100))))
|
||||
.append("<br/>");
|
||||
}
|
||||
|
||||
String labels = buildLabelsText();
|
||||
|
|
|
|||
|
|
@ -508,6 +508,12 @@ public abstract class ChartFiller implements IChartFiller {
|
|||
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(
|
||||
SortedMap<LocalDate, BigDecimal> map, Date start, Date finish) {
|
||||
return calculatedValueForEveryDay(map, new LocalDate(start),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -22,18 +22,13 @@
|
|||
package org.libreplan.web.planner.chart;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.web.I18nHelper;
|
||||
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 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 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) {
|
||||
LocalDate start = interval.getStart();
|
||||
LocalDate end = interval.getFinish();
|
||||
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>>();
|
||||
private Interval indicatorsInterval;
|
||||
|
||||
protected abstract void calculateBudgetedCostWorkScheduled(Interval interval);
|
||||
protected abstract void calculateActualCostWorkPerformed(Interval interval);
|
||||
protected abstract void calculateBudgetedCostWorkPerformed(Interval interval);
|
||||
private Interval indicatorsInterval;
|
||||
|
||||
protected Plotinfo createPlotInfo(SortedMap<LocalDate, BigDecimal> map,
|
||||
Interval interval, String lineColor) {
|
||||
|
|
@ -203,167 +92,55 @@ public abstract class EarnedValueChartFiller extends ChartFiller {
|
|||
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) {
|
||||
return indicators.get(indicator).get(date);
|
||||
}
|
||||
|
||||
private void calculateCostVariance() {
|
||||
// CV = BCWP - ACWP
|
||||
indicators.put(EarnedValueType.CV,
|
||||
substract(EarnedValueType.BCWP, EarnedValueType.ACWP));
|
||||
public void setIndicator(EarnedValueType type, SortedMap<LocalDate, BigDecimal> values) {
|
||||
indicators.put(type, values);
|
||||
}
|
||||
|
||||
private void calculateScheduleVariance() {
|
||||
// SV = BCWP - BCWS
|
||||
|
||||
indicators.put(EarnedValueType.SV,
|
||||
substract(EarnedValueType.BCWP, EarnedValueType.BCWS));
|
||||
public void setIndicatorInInterval(EarnedValueType type,
|
||||
Interval interval, SortedMap<LocalDate, BigDecimal> values) {
|
||||
addZeroBeforeTheFirstValue(values);
|
||||
indicators.put(type, calculatedValueForEveryDay(values, interval));
|
||||
}
|
||||
|
||||
private void calculateBudgetAtCompletion() {
|
||||
// BAC = max (BCWS)
|
||||
SortedMap<LocalDate, BigDecimal> bac = new TreeMap<LocalDate, BigDecimal>();
|
||||
SortedMap<LocalDate, BigDecimal> bcws = indicators
|
||||
.get(EarnedValueType.BCWS);
|
||||
|
||||
BigDecimal value = Collections.max(bcws.values());
|
||||
for (LocalDate day : bcws.keySet()) {
|
||||
bac.put(day, value);
|
||||
protected void addZeroBeforeTheFirstValue(
|
||||
SortedMap<LocalDate, BigDecimal> map) {
|
||||
if (!map.isEmpty()) {
|
||||
map.put(map.firstKey().minusDays(1), BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
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
|
||||
public void fillChart(Timeplot chart, Interval interval, Integer size) {
|
||||
chart.getChildren().clear();
|
||||
|
|
@ -411,11 +188,55 @@ public abstract class EarnedValueChartFiller extends ChartFiller {
|
|||
return includes(chartInterval, today) ? today : chartInterval
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -38,8 +38,6 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
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.planner.chart.ILoadChartData;
|
||||
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.TaskGroup;
|
||||
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.users.daos.IUserDAO;
|
||||
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.TaskGroupPredicate;
|
||||
import org.libreplan.web.planner.chart.Chart;
|
||||
|
|
@ -132,6 +130,9 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
|
|||
@Autowired
|
||||
private IAdHocTransactionService transactionService;
|
||||
|
||||
@Autowired
|
||||
private ICompanyEarnedValueCalculator earnedValueCalculator;
|
||||
|
||||
private List<IZoomLevelChangedListener> keepAliveZoomListeners = new ArrayList<IZoomLevelChangedListener>();
|
||||
|
||||
private List<Checkbox> earnedValueChartConfigurationCheckboxes = new ArrayList<Checkbox>();
|
||||
|
|
@ -275,6 +276,7 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
|
|||
setupChart(chartLoadTimeplot, new CompanyLoadChartFiller(), planner);
|
||||
|
||||
chartComponent.getTabs().getLastChild().addEventListener(Events.ON_SELECT, new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
createOnDemandEarnedValueTimePlot(chartComponent, planner);
|
||||
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 {
|
||||
|
||||
@Override
|
||||
protected void calculateBudgetedCostWorkScheduled(Interval interval) {
|
||||
Map<TaskElement, SortedMap<LocalDate, BigDecimal>> estimatedCostPerTask =
|
||||
databaseSnapshots.snapshotEstimatedCostPerTask();
|
||||
Collection<TaskElement> list = filterTasksByDate(
|
||||
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()));
|
||||
setIndicatorInInterval(EarnedValueType.BCWS, interval,
|
||||
earnedValueCalculator
|
||||
.calculateBudgetedCostWorkScheduled(getFilterInterval()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void calculateActualCostWorkPerformed(Interval interval) {
|
||||
SortedMap<LocalDate, BigDecimal> workReportCost = getWorkReportCost();
|
||||
|
||||
workReportCost = accumulateResult(workReportCost);
|
||||
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;
|
||||
setIndicatorInInterval(EarnedValueType.ACWP, interval,
|
||||
earnedValueCalculator
|
||||
.calculateActualCostWorkPerformed(getFilterInterval()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void calculateBudgetedCostWorkPerformed(Interval interval) {
|
||||
Map<TaskElement, SortedMap<LocalDate, BigDecimal>> advanceCostPerTask =
|
||||
databaseSnapshots.snapshotAdvanceCostPerTask();
|
||||
Collection<TaskElement> list = filterTasksByDate(
|
||||
advanceCostPerTask.keySet(), getFilterInterval());
|
||||
setIndicatorInInterval(EarnedValueType.BCWP, interval,
|
||||
earnedValueCalculator
|
||||
.calculateBudgetedCostWorkPerformed(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) {
|
||||
addCost(advanceCost, advanceCostPerTask.get(taskElement));
|
||||
}
|
||||
@Override
|
||||
protected void calculateScheduleVariance() {
|
||||
setIndicator(EarnedValueType.SV,
|
||||
earnedValueCalculator.calculateScheduleVariance(
|
||||
getIndicator(EarnedValueType.BCWP),
|
||||
getIndicator(EarnedValueType.BCWS)));
|
||||
}
|
||||
|
||||
addZeroBeforeTheFirstValue(advanceCost);
|
||||
indicators.put(EarnedValueType.BCWP, calculatedValueForEveryDay(
|
||||
advanceCost, interval.getStart(), interval.getFinish()));
|
||||
@Override
|
||||
protected void calculateSchedulePerformanceIndex() {
|
||||
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
|
||||
|
|
@ -859,33 +887,9 @@ public class CompanyPlanningModel implements ICompanyPlanningModel {
|
|||
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)
|
||||
public ProgressType getProgressTypeFromConfiguration() {
|
||||
return configurationDAO.getConfiguration().getProgressType();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
* Copyright (C) 2010-2011 Igalia, S.L.
|
||||
* Copyright (C) 2010-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
|
||||
|
|
@ -57,7 +57,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
|||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.zkoss.ganttz.data.GanttDate;
|
||||
import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
|
||||
|
||||
/**
|
||||
|
|
@ -152,7 +151,6 @@ public class AdvanceConsolidationModel implements IAdvanceConsolidationModel {
|
|||
updateConsolidationInAdvanceIfIsNeeded();
|
||||
|
||||
ganttTask.enforceDependenciesDueToPositionPotentiallyModified();
|
||||
ganttTask.reloadResourcesText();
|
||||
context.reloadCharts();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue