Merge branch 'master' into mpxj-import
Conflicts: libreplan-business/src/main/java/org/libreplan/business/orders/entities/Order.java libreplan-business/src/main/resources/db.changelog-1.3.xml
This commit is contained in:
commit
909eab9f52
472 changed files with 51874 additions and 17189 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -20,3 +20,12 @@ libreplan-webapp/*.log.????-??-??
|
|||
#ignore backup files
|
||||
*~
|
||||
\#*\#
|
||||
|
||||
# ignore documentation auto-generated files
|
||||
doc/src/user/en/html/
|
||||
doc/src/user/en/index.rst
|
||||
doc/src/user/es/html/
|
||||
doc/src/user/es/index.rst
|
||||
doc/src/user/gl/html/
|
||||
doc/src/user/gl/index.rst
|
||||
libreplan-webapp/src/main/webapp/help/
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ Previous Team Members
|
|||
Translators
|
||||
-----------
|
||||
|
||||
* [ca] Daniel Díaz Sañudo <gurnan@gmail.com>
|
||||
* [cs] Zbyněk Schwarz <zbynek.schwarz@gmail.com>
|
||||
* [de] Joern Knechtel <j.knechtel@gmx.de>,
|
||||
Michael Taxis <mxtaxis@gmx.de>
|
||||
|
|
@ -46,9 +47,11 @@ Translators
|
|||
* [it] Giuseppe Zizza <gzizza@gmail.com>
|
||||
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
|
||||
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
|
||||
* [pt] Helena Grosso <lenagrosso@gmail.com>,
|
||||
* [pt] Thiago Cangussu <cangussu.br@gmail.com>,
|
||||
Helena Grosso <lenagrosso@gmail.com>,
|
||||
Joaquim Rocha <jrocha@igalia.com>
|
||||
* [ru] Pavel Rudensky <prudensky@gmail.com>
|
||||
* [zh] Swanson Chan <lacidophilin@yahoo.com>
|
||||
|
||||
|
||||
Contributors
|
||||
|
|
@ -39,10 +39,6 @@ Compilation requirements
|
|||
|
||||
Used for i18n support in the project
|
||||
|
||||
* *GNU FreeFont* - Freefont Serif, Sans and Mono Truetype fonts
|
||||
|
||||
Font family used in reports
|
||||
|
||||
* *CutyCapt* - Utility to capture WebKit's rendering of a web page
|
||||
|
||||
Required for printing
|
||||
|
|
@ -56,7 +52,7 @@ Debian/Ubuntu
|
|||
|
||||
* Install requirements::
|
||||
|
||||
# apt-get install git-core maven2 openjdk-6-jdk postgresql postgresql-client python-docutils make gettext ttf-freefont cutycapt
|
||||
# apt-get install git-core maven2 openjdk-6-jdk postgresql postgresql-client python-docutils make gettext cutycapt
|
||||
|
||||
* Connect to database::
|
||||
|
||||
|
|
@ -72,7 +68,7 @@ Debian/Ubuntu
|
|||
|
||||
* Download source code::
|
||||
|
||||
$ git clone git://libreplan.git.sourceforge.net/gitroot/libreplan/libreplan
|
||||
$ git clone git://github.com/Igalia/libreplan.git
|
||||
|
||||
* Compile project::
|
||||
|
||||
|
|
@ -91,10 +87,19 @@ Fedora
|
|||
|
||||
* Install requirements::
|
||||
|
||||
# yum install git maven java-1.7.0-openjdk-devel postgresql postgresql-server python-docutils make gettext gnu-free-fonts-compat
|
||||
|
||||
.. WARNING:: Use the following command in Fedora 16 or below::
|
||||
|
||||
# yum install git maven java-1.6.0-openjdk postgresql postgresql-server python-docutils make gettext gnu-free-fonts-compat
|
||||
|
||||
* Start database service::
|
||||
|
||||
# su - postgres -c "PGDATA=/var/lib/pgsql/data initdb"
|
||||
# systemctl start postgresql.service
|
||||
|
||||
.. WARNING:: Use the following commands in Fedora 16 or below::
|
||||
|
||||
# service postgresql initdb
|
||||
# service postgresql start
|
||||
|
||||
|
|
@ -114,15 +119,17 @@ Fedora
|
|||
|
||||
ALTER USER postgres WITH PASSWORD 'postgres';
|
||||
|
||||
* Edit ``/var/lib/pgsql/data/pg_hba.conf`` and replace ``ident`` by ``md5``
|
||||
.. WARNING:: These steps are only for Fedora 16 and below:
|
||||
|
||||
* Reload database configuration::
|
||||
* Edit ``/var/lib/pgsql/data/pg_hba.conf`` and replace ``ident`` by ``md5``
|
||||
|
||||
* Reload database configuration::
|
||||
|
||||
# service postgresql reload
|
||||
|
||||
* Download source code::
|
||||
|
||||
$ git clone git://libreplan.git.sourceforge.net/gitroot/libreplan/libreplan
|
||||
$ git clone git://github.com/Igalia/libreplan.git
|
||||
|
||||
* Compile project::
|
||||
|
||||
|
|
@ -141,7 +148,7 @@ openSUSE
|
|||
|
||||
* Install requirements::
|
||||
|
||||
# zypper install git-core java-1_6_0-openjdk-devel postgresql-server postgresql docutils make gettext-tools freefont
|
||||
# zypper install git-core java-1_6_0-openjdk-devel postgresql-server postgresql docutils make gettext-tools
|
||||
|
||||
* Install Maven::
|
||||
|
||||
|
|
@ -183,7 +190,7 @@ openSUSE
|
|||
|
||||
* Download source code::
|
||||
|
||||
$ git clone git://libreplan.git.sourceforge.net/gitroot/libreplan/libreplan
|
||||
$ git clone git://github.com/Igalia/libreplan.git
|
||||
|
||||
* Compile project::
|
||||
|
||||
|
|
@ -65,23 +65,40 @@ Instructions:
|
|||
|
||||
If you have memory problems review the section `Fix memory errors`_.
|
||||
|
||||
Fedora and openSUSE OBS (openSUSE Build Service)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Fedora, CentOS and openSUSE OBS (openSUSE Build Service)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Instructions depending on the distribution:
|
||||
|
||||
* Fedora 17::
|
||||
|
||||
# cd /etc/yum.repos.d
|
||||
# wget download.opensuse.org/repositories/home:/jsuarezr:/LibrePlan/Fedora_17/home:jsuarezr:LibrePlan.repo
|
||||
# yum install libreplan
|
||||
|
||||
Follow the instructions in /usr/share/doc/libreplan-1.3.0/README.Fedora afterwards.
|
||||
|
||||
* Fedora 16::
|
||||
|
||||
# cd /etc/yum.repos.d
|
||||
# wget download.opensuse.org/repositories/home:/jsuarezr:/LibrePlan/Fedora_16/home:jsuarezr:LibrePlan.repo
|
||||
# yum install libreplan
|
||||
|
||||
* Fedora 15::
|
||||
Follow the instructions in /usr/share/doc/libreplan-1.3.0/README.Fedora afterwards.
|
||||
|
||||
* CentOS 6::
|
||||
|
||||
# cd /etc/yum.repos.d
|
||||
# wget download.opensuse.org/repositories/home:/jsuarezr:/LibrePlan/Fedora_15/home:jsuarezr:LibrePlan.repo
|
||||
# wget download.opensuse.org/repositories/home:/jsuarezr:/LibrePlan/CentOS_CentOS-6/home:jsuarezr:LibrePlan.repo
|
||||
# yum install libreplan
|
||||
|
||||
* openSUSE Factory::
|
||||
|
||||
# cd /etc/zypp/repos.d
|
||||
# wget download.opensuse.org/repositories/home:/jsuarezr:/LibrePlan/openSUSE_Factory/home:jsuarezr:LibrePlan.repo
|
||||
# zypper ref
|
||||
# zypper install libreplan
|
||||
|
||||
* openSUSE 12.1::
|
||||
|
||||
# cd /etc/zypp/repos.d
|
||||
|
|
@ -106,6 +123,8 @@ RPM Packages
|
|||
There are several LibrePlan RPM packages available in the following URL:
|
||||
http://download.opensuse.org/repositories/home:/jsuarezr:/LibrePlan/
|
||||
|
||||
Follow the instructions in the corresponding README file to finish the installation.
|
||||
|
||||
.. WARNING::
|
||||
|
||||
If you have memory problems review the section `Fix memory errors`_.
|
||||
|
|
@ -119,7 +138,7 @@ Debian/Ubuntu
|
|||
|
||||
* Install requirements::
|
||||
|
||||
# apt-get install openjdk-6-jre postgresql postgresql-client tomcat6 libpg-java ttf-freefont cutycapt xvfb
|
||||
# apt-get install openjdk-6-jre postgresql postgresql-client tomcat6 libpg-java cutycapt xvfb
|
||||
|
||||
* Connect to database::
|
||||
|
||||
|
|
@ -213,7 +232,7 @@ openSUSE
|
|||
|
||||
* Install requirements::
|
||||
|
||||
# zypper install java-1_6_0-openjdk postgresql-server postgresql tomcat6 freefont xorg-x11-server
|
||||
# zypper install java-1_6_0-openjdk postgresql-server postgresql tomcat6 xorg-x11-server
|
||||
|
||||
* JDBC Driver manual installation::
|
||||
|
||||
|
|
@ -308,6 +327,26 @@ folder under ``/var/log/tomcat6/`` with ``.war`` name. For example:
|
|||
Inside this new directory there will be two files (``libreplan.log`` and
|
||||
``libreplan-error.log``) that will be rotated every day.
|
||||
|
||||
Configure log directory
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Anyway if you want to set manually LibrePlan log path you will have to
|
||||
configure ``JAVA_OPTS`` variable in your server. This variable is configured in
|
||||
different files depending on the distribution:
|
||||
|
||||
* Debian or Ubuntu: ``/etc/default/tomcat6``
|
||||
* Fedora or openSUSE: ``/etc/tomcat6/tomcat6.conf``
|
||||
|
||||
Where you will need to add the next line::
|
||||
|
||||
# Configure LibrePlan log directory
|
||||
JAVA_OPTS="${JAVA_OPTS} -Dlibreplan-log-directory=/my/path/to/libreplan/log/"
|
||||
|
||||
.. WARNING::
|
||||
|
||||
You have to be sure that the user running Tomcat (usually ``tomcat6``) has
|
||||
permissions to write in the specified directory.
|
||||
|
||||
|
||||
Fix printing in Debian Squeeze
|
||||
------------------------------
|
||||
557
NEWS → NEWS.rst
557
NEWS → NEWS.rst
|
|
@ -1,6 +1,563 @@
|
|||
NEWS
|
||||
====
|
||||
|
||||
Version 1.3.3 (21 Dec 2012)
|
||||
---------------------------
|
||||
|
||||
Summary
|
||||
~~~~~~~
|
||||
|
||||
A new minor version of LibrePlan including all the fixes done since previous
|
||||
version and some new features that have been developed lately.
|
||||
|
||||
Highlights:
|
||||
|
||||
* A custom Mobile Application has been developed. This is a tool to allow
|
||||
LibrePlan users to access the tasks they are assigned to, from any project,
|
||||
report worked hours and check their progresses from a mobile device.
|
||||
http://www.libreplan.com/download/mobile-application/
|
||||
You can download this application for free to any of the currently supported
|
||||
platforms, and configure it to connect to your LibrePlan installation to start
|
||||
using it.
|
||||
|
||||
Apart from this. Several changes have also been made on LibrePlan, of which the
|
||||
most remarkable are:
|
||||
|
||||
* Performance improvements on the project listing window (specially when
|
||||
working with a lot of projects), and on the project creation and WBS
|
||||
manipulation.
|
||||
|
||||
* We have changed the internals of the custom JavaScript files inside LibrePlan,
|
||||
to avoid some problems due to the caching of those files, and creating issues
|
||||
that forced manual cache refresh when upgrading LibrePlan installations.
|
||||
|
||||
* An informative message has been added to the installation package to suggest
|
||||
Java configuration tunning, in order to avoid Memory problems.
|
||||
|
||||
* The visibility of the projects on the company view has been modified, to show
|
||||
by default all projects but CANCELLED and STORED.
|
||||
|
||||
Notes
|
||||
~~~~~
|
||||
|
||||
If you are upgrading from 1.3.1 version without using the Debian package,
|
||||
you will need to manually execute on your database the SQL sentences from file:
|
||||
``scripts/database/upgrade_1.3.2.sql``.
|
||||
|
||||
If you are upgrading from 1.3.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.3.1.sql`` and
|
||||
``scripts/database/upgrade_1.3.2.sql``.
|
||||
|
||||
If you are upgrading from a previous version without using the Debian package,
|
||||
review the *Notes* section for version 1.3.0.
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Thanks to all the contributors to this new version:
|
||||
|
||||
* Óscar González Fernández
|
||||
* Manuel Rego Casasnovas
|
||||
* Juan A. Suarez Romero
|
||||
* Lorenzo Tilve Álvaro
|
||||
|
||||
Translators
|
||||
~~~~~~~~~~~
|
||||
|
||||
Thanks to all the translators in this new version:
|
||||
|
||||
* [ca] Daniel Díaz Sañudo
|
||||
* [es] Manuel Rego Casasnovas
|
||||
* [gl] Manuel Rego Casasnovas
|
||||
* [nl] Jeroen Baten
|
||||
* [pt] Thiago Cangussu
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
* Update RPM package for LibrePlan 1.3.3
|
||||
* Update Debian package for LibrePlan 1.3.3
|
||||
* debian: Use echo to show information as db_info is causing problems
|
||||
* Fix typo in Labels tab in project details view
|
||||
* i18n: Update Portuguese translation
|
||||
* i18n: Mark some missing strings to be translated
|
||||
* i18n: Mark some missing strings to be translated
|
||||
* Bug #1600: Fix issue creating bindings on open resource allocation pop-up
|
||||
* Use for company view filtering all projects with status different to STORED or CANCELLED
|
||||
* Bug #1598: Fix empty labels bandbox creating bindings for tab on open
|
||||
* Bug #1579: Add autodisable to save-and-exit button on all standard CRUD forms
|
||||
* Make more readable date constraint component on taskdetails
|
||||
* Fix vertical alignment problems on component to add new resource allocations
|
||||
* Make more compact advanced search criteria filter tree
|
||||
* Fix left padding issue on company view project names
|
||||
* Add first input focus-element behaviour to BaseCRUDController subclasses
|
||||
* Bug #1418: Focused worker firstname on creation
|
||||
* Fix extra vertical padding issue on WBS tree rows
|
||||
* Add support to BaseCRUDController for automatically focusing first .focus-element component
|
||||
* Improved task name style inside gantt view popup
|
||||
* Replaced comma separator on Task resourcesText as it was already used on each resource
|
||||
* Bug #1584: Fix corner case issue filling the advanced assignment pagination intervals
|
||||
* i18n: Mark some missing strings to be translated
|
||||
* Bug #1596: Disable confirm close message if user uses back button
|
||||
* i18n: Update Catalan translation
|
||||
* i18n: Update Dutch translation
|
||||
* i18n: Update Spanish and Galician translations
|
||||
* Modify .gitignore to ignore documentation auto-generated files
|
||||
* Set version for JavaScript modules in lang-addon.xml files
|
||||
* Bug #1592: Fix problem not showing the tab if it is already being shown
|
||||
* Bug #1592: Save Order before showing it
|
||||
* Bug #1590: Avoid repeated calls to goToOrdersList
|
||||
* Avoid some redundant loads of bindings in the same request
|
||||
* Revert "Bug #1590: Fix problem calling several times the same method in OrderModel"
|
||||
* Revert "Bug #1592: Fix problem not showing the tab if it is already being shown"
|
||||
* Bug #1594: Fix issue opening transaction at DAO if needed
|
||||
* Bug #1593: Fix issue translating the options while rendering
|
||||
* debian: Add information about common issues in LibrePlan installation
|
||||
* Bug #1592: Fix problem not showing the tab if it is already being shown
|
||||
* i18n: Update keys.pot files
|
||||
* Bug #1590: Simplify Util.createBindingsFor
|
||||
* Bug #1590: Avoid go to projects list when creating a project
|
||||
* Bug #1590: Fix problem calling several times the same method in OrderModel
|
||||
* Bug #1589: Fix issue using orderVersion for all the elements to be updated or added
|
||||
* Bug #1586: Fix issue reseting list of checkboxes before adding them
|
||||
* Bug #1583: If assignment function is not configurable keep button disabled
|
||||
* Bug #1587: Fix issue only resetting index of progress combo if it has items
|
||||
* Bug 1581: Avoid exception in LongOperationFeedback if desktop is not ready
|
||||
* Update RPM spec file
|
||||
|
||||
|
||||
Version 1.3.2 (30 Nov 2012)
|
||||
---------------------------
|
||||
|
||||
Summary
|
||||
~~~~~~~
|
||||
|
||||
A new minor version of LibrePlan including all the fixes done since previous
|
||||
version and some new features that have been developed lately. It also includes
|
||||
some of the tasks done during the 1st LibrePlan Hackfest arranged in A Coruña
|
||||
the 8th of November.
|
||||
|
||||
Highlights:
|
||||
|
||||
* Improvements in "Project Status" report:
|
||||
|
||||
* New columns showing information about costs.
|
||||
* Included filter by criteria and labels.
|
||||
* Some data are written in red when the planning (or estimation) is not
|
||||
enough.
|
||||
|
||||
* Planning adjustment according to timesheets: New feature providing the
|
||||
possibility to adapt the Gantt view to reflect the reality with the data
|
||||
extracted from the timesheets. Moreover, it includes the option to mark a task
|
||||
as finished in the timesheets. On adjusting the planning acoording to
|
||||
timesheets if one task has been marked as finished in the timesheets then,
|
||||
additionally, a new progress type of type timesheets with a 100% measurement.
|
||||
|
||||
* New DELETE operation in order elements web service: The new web service
|
||||
operation allows to remove whole projects or individual tasks on top of the
|
||||
current functionality to import/update projects or tasks.
|
||||
|
||||
* New bound resources web service operations: 3 new web services have been
|
||||
implemented related to bound resources. They provide the list of assigned
|
||||
tasks, get the personal timesheets of a task and update the personal
|
||||
timesheets data for a bound user.
|
||||
|
||||
* Other:
|
||||
|
||||
* Compatibility issues with OpenJDK 7 fixed. This solves the problems with the
|
||||
latest Ubuntu and Fedora versions.
|
||||
|
||||
* The project planning persectives have been protected in order to avoid
|
||||
leaving them without saving. There is a new configuration variable to define
|
||||
the number of seconds since the last saving in order to activate a warning
|
||||
when the user leaves the planning views. Several users have reported
|
||||
inconvenient data losses due to abandoning the project edition without
|
||||
saving. With this warning this situation is fixed. By default the number of
|
||||
seconds is configured to 30 and if you set it to 0 you disable the warning.
|
||||
|
||||
* Option to edit manually if a user is a database or LDAP user.
|
||||
|
||||
* By clicking on the project name in the left side part of the projects
|
||||
planning perspective (home page), the user is able to enter directly into
|
||||
the project planning edition.
|
||||
|
||||
* The list of project states has been reviewed and expanded. The final list is
|
||||
composed by: PRE-SALES, OFFERED, OUTSOURCED, ACCEPTED, STARTED, ON HOLD,
|
||||
FINISHED, CANCELLED and STORED.
|
||||
|
||||
Notes
|
||||
~~~~~
|
||||
|
||||
.. WARNING::
|
||||
|
||||
Remove web browser cache to avoid any problem with changes in JavaScript
|
||||
resources.
|
||||
|
||||
If you are upgrading from 1.3.1 version without using the Debian package,
|
||||
you will need to manually execute on your database the SQL sentences from file:
|
||||
``scripts/database/upgrade_1.3.2.sql``.
|
||||
|
||||
If you are upgrading from 1.3.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.3.1.sql`` and
|
||||
``scripts/database/upgrade_1.3.2.sql``.
|
||||
|
||||
If you are upgrading from a previous version without using the Debian package,
|
||||
review the *Notes* section for version 1.3.0.
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Thanks to all the contributors to this new version:
|
||||
|
||||
* Jacobo Aragunde Pérez
|
||||
* Manuel Rego Casasnovas
|
||||
* Lorenzo Tilve Álvaro
|
||||
|
||||
Translators
|
||||
~~~~~~~~~~~
|
||||
|
||||
Thanks to all the translators in this new version:
|
||||
|
||||
* [ca] Daniel Díaz Sañudo
|
||||
* [es] Manuel Rego Casasnovas
|
||||
* [fr] Philippe Poumaroux
|
||||
* [gl] Manuel Rego Casasnovas
|
||||
* [nl] Jeroen Baten
|
||||
* [pt] Thiago Cangussu
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
* Update RPM package for LibrePlan 1.3.2
|
||||
* Update Debian package for LibrePlan 1.3.2
|
||||
* Update database scripts for LibrePlan 1.3.2
|
||||
* Only use ConfirmCloseUtil when saving if you are in the UI (not from web services)
|
||||
* Avoid confirm close warning when you get a concurrent modification exception
|
||||
* Fix issue deleting a project from the webservice
|
||||
* Update installation instructions for RPM based distros.
|
||||
* Fedora17 requires JDK 1.7
|
||||
* Fixed effect which caused previously clicked menu elements to be shown underlined
|
||||
* Fix printing due to change in entry points that now use code instead of id
|
||||
* Fixed NPE when deleting nodes too fast on project or template WBS trees
|
||||
* Bug #1562: Fix issue filtering properly resources according to their activation periods
|
||||
* doc: Add .rst extension to web services README
|
||||
* doc: Add documentation about the new bound users web services
|
||||
* Increased opacity of markers for first and last day with reported hours
|
||||
* Shifted right the last reported day marker
|
||||
* Changed cursor over gantt bars with fixed properties
|
||||
* Revamped appearance of markers for first and last reported progress dates
|
||||
* Replaced browser-prefixed border-radius elements from CSS files
|
||||
* Bug 1581: Avoid exception when desktop is not alive in LongOperationFeedback
|
||||
* doc: Add .rst extension to documentation files to take advantage of GitHub rendering for RST files
|
||||
* Change links to repository from sourceforge to github
|
||||
* doc: Added Thiago Cangussu as new Portuguese translator
|
||||
* i18n: Update Portuguese translation
|
||||
* i18n: Update French translation
|
||||
* i18n: Update Dutch translation
|
||||
* i18n: Update Catalan translation
|
||||
* i18n: Update Galician translation
|
||||
* i18n: Update Spanish translation
|
||||
* Fix Bug 1580: Force position recalculation after accepting task properties pop-up
|
||||
* Made explicit focused elements on main menu
|
||||
* Fixed side-effect of clickable-rows:hover effect on grids
|
||||
* Bug #1571: Fixed style on timetracker sencond level width causing a disaligment of 1px per element
|
||||
* Bug #1436: Fix issue setting recommended allocation resources per day to 1
|
||||
* Add new field to configure seconds for planning warning
|
||||
* Fixed permissions in order to set confirm close dialogue properly
|
||||
* Moved repeated code to ConfirmCloseUtil class
|
||||
* When executing saveCommand the timer on confirmClose is resetted
|
||||
* Internationalized warn message when leaving the planning
|
||||
* Removed confirmClose warning when leaving project planning after Save Command
|
||||
* Attached listener to call confirmClose notification
|
||||
* Added confirmClose method to give the user a warning when leaving the order edition mode
|
||||
* Added onClick listener to project names on company view to enter into the planning
|
||||
* Exposed project and tasks codes from fundamental properties to generate entry point URLs
|
||||
* Bug #1546: Force recalculation of critical path progresses on saving project
|
||||
* Bug #1541: Fix issue reseting selected element when progress is hidden
|
||||
* Bug #1570: Fix issue updating the EV chart legend instead of creating it from scratch
|
||||
* i18n: Update keys.pot files
|
||||
* Add event to close popup with ENTER over effort or finished inputs
|
||||
* Add checkbox to mark task as finished in personal timesheets popup
|
||||
* Fix bug in adapt planning command if Gantt has milestones
|
||||
* Add popup to fill personal timesheets in each day
|
||||
* Bug #1566: Do not launch exception in MonteCarlo view is critical path is only a milestone
|
||||
* Bug #1568: Allow to move a task before start date if it does not have consolidations
|
||||
* Bug #1553: Fixed test due to change in behavior
|
||||
* Bug #1553, #1554: Remove unique constraint in DB for OrderElement codes
|
||||
* Bug #1553: Fix issue modifying methods toLeaf and toContainer
|
||||
* Calculate progress and hours bars always proportionally to task size
|
||||
* Fix problems in service to import personal timesheets
|
||||
* Remove TIMESHEETS progress in tasks that are not updated from timesheets
|
||||
* Fix typo in "according"
|
||||
* Bug #1556: Allow to choose between database or LDAP in user creation
|
||||
* Bug #1556: Fix problems with i18n of the new enum
|
||||
* Bug #1556: Allow changing the value of UserAuthenticationType field in user edition screen.
|
||||
* Bug #1556: Use a combo box to show the value of UserAuthenticationType field.
|
||||
* Bug #1556: Use an enum to express the value of UserAuthenticationType field.
|
||||
* doc: Update INSTALL file with instructions to configure log directory
|
||||
* Prevent NPE in TemplateController if logged user is null
|
||||
* Change style of tasks that cannot be moved in the Gantt
|
||||
* Update dates on left part of Gantt view after adapt the planning
|
||||
* Merge branch 'libreplan-1.3' into adapt-planning-according-timesheets
|
||||
* Sort timesheet entries descending by date in bound users service
|
||||
* Include project code in tasks list service for bound users
|
||||
* Bug #1561: Upgrade AspectJ dependency to the latest version.
|
||||
* Show marks from timesheet dates in tasks when showing reported hours bar
|
||||
* Bug #1560: Fire property change for task dates after closing allocation pop-up
|
||||
* Bug #1559: Remove WorkReportLines with zero effort in personal timesheets
|
||||
* Add feedback message for user while adapting planning
|
||||
* Only adapt task leafs according to timesheets
|
||||
* Invalidate planner in order to repaint dependencies after updating tasks in Gantt
|
||||
* Update tasks in Gantt after adapting start and end date of all tasks
|
||||
* Remove assignments after end date for tasks marked as finished in the timesheets
|
||||
* Disable drag & drop for tasks updated from timesheets in the WBS
|
||||
* Disable new, new from template, up, down, indent and unindent buttons in WBS
|
||||
* Remove unused code in TreeController
|
||||
* Prevent tasks updated from timesheets to be reassigned
|
||||
* Disable advanced allocation window for tasks updated from timesheets
|
||||
* Disable tasks movement for tasks updated from timesheets
|
||||
* Disable resource allocation pop-up for tasks updated from timesheets
|
||||
* Bug #1517: Select the parent row in the WBS when it's transformed into a container.
|
||||
* Rename SUBCONTRACTED_PENDING_ORDER to OUTSOURCED
|
||||
* Configure default project status as PRE-SALES
|
||||
* Update order state in database due to new status added to the enum
|
||||
* Add new status in OrderStatusEnum: PRE-SALES and ON HOLD
|
||||
* Updated HACKING instructions for Fedora 17 and above.
|
||||
* Fix visibility issues in OpenJDK 1.7.
|
||||
* Add example scripts to import personal timesheets data
|
||||
* Add new service to import personal timesheets data
|
||||
* Add example script to test the service returning timsheets data for a task
|
||||
* New web service returning the personal timesheets data for a task of a bound user
|
||||
* Add example script for service that returns tasks of a bound user
|
||||
* New web service returning the assigned tasks of a user
|
||||
* Disable change of scheduling state point in WBS for tasks updated from timesheets
|
||||
* Disable constraints combo in tasks updated from timesheets
|
||||
* Set properly task position for tasks updated from timesheets even if dependencies have priority
|
||||
* Fix remove order elements service test in MySQL
|
||||
* Wrap concurrent modification exceptions in the web services inside a proper DTO
|
||||
* Add missing class ErrorDTO used in commit 7306b124deafa60a701b236eb9c9176a40733ed4
|
||||
* Implement main operations in adapt planning command
|
||||
* Bug #1555: Fix issue adding condition in both UI and web service
|
||||
* Add test for new delete order elements service
|
||||
* Update web services documentation with the new delete service
|
||||
* Fix example removal scripts reusing generic code
|
||||
* Include validations in the new service to remove order elements
|
||||
* Remove properly order element using OrderModel class
|
||||
* Convert parent in leaf if the element removed was the only child
|
||||
* Basic implementation of DELETE operation in order elements web service
|
||||
* Add new button to adapt planning according to timesheets
|
||||
* Add new field updatedFromTimesheets to TaskElement
|
||||
* Use code instead of id for ResourceHoursService
|
||||
* Fix parameters order in import example rest scripts
|
||||
* Add implementation to calculate if a task is finished according to timesheets
|
||||
* Add new attribute finishedTimesheets in SumChargedEffort
|
||||
* Disable finished checkbox in work reports UI if the task is already finished
|
||||
* Implement constraint to check that only one WorkReportLine per task is finished
|
||||
* Add checkbox in work reports standard edition UI
|
||||
* Add new attribute finished to WorkReportLine
|
||||
* Create new default progress type TIMESHEETS
|
||||
* Calculate first/last timesheets dates when saving/editing/deleting a timesheet
|
||||
* Calculate first/last timesheet dates when recalculating a SumChargedEffortDAO
|
||||
* Add new columns in SumChargedEffort for first and last timesheet date
|
||||
* Bug #1549: Avoid exception avoiding checking lines resource if there are no lines
|
||||
* Add filter by order authorizations in project status report
|
||||
* Merge branch 'master' into project-status-report
|
||||
* Reset MoneyCostCalculator before generating project status report
|
||||
* Add hours and cost mark in status report header too
|
||||
* Sort order elements by code in OrderElementDAO.findByLabelsAndCriteria
|
||||
* Add query to get OrderElements filtered by labels and criteria
|
||||
* Marking with red color special cases in project status report
|
||||
* Add exclamation mark in status report if hours or cost exceed the expected value
|
||||
* Add information about filter in project status report header if no project is selected
|
||||
* Avoid project in status report header if not selected
|
||||
* Add project name in tasks when no project is selected in status report
|
||||
* Add option to do not filter by project if you are filtering by labels or criteria
|
||||
* Bug #1551: Added FIXME notes to two tests that are causing trouble.
|
||||
* Fix CriterionSatisfactionDAOTest when run individually.
|
||||
* Fix ResourceDAOTest when run individually.
|
||||
* Fix criteria filtering discounting children with invalidated criteria
|
||||
* Implement filtering by criteria
|
||||
* Add UI to filter by criteria
|
||||
* Add filter by labels to project status report
|
||||
* Modify project status report to include new data
|
||||
* Modify project status report layout to include information about costs
|
||||
* Add transactional readonly in findCode to avoid bug introduced in previous patch
|
||||
* Use code to go to entry points when possible
|
||||
* Bug #1547: Allow user with role SUPERUSER to create new projects
|
||||
|
||||
|
||||
Version 1.3.1 (15 Oct 2012)
|
||||
---------------------------
|
||||
|
||||
Summary
|
||||
~~~~~~~
|
||||
|
||||
New minor version of LibrePlan including all the bugfixes done since 1.3.0 and
|
||||
also some new small features included in this version.
|
||||
|
||||
We would like to highlight the following changes:
|
||||
|
||||
* Allow to administrate the roles and profiles for the users imported from the
|
||||
LDAP.
|
||||
|
||||
* New language supported, this time Catalan thanks to Daniel Díaz Sañudo.
|
||||
Making the full list of languages fully supported to grow up to 6, apart from
|
||||
English: Catalan, Dutch, French, Galician, Italian and Spanish. Moreover,
|
||||
German and Polish are gradually approaching. Thanks to all our translators for
|
||||
their hard work.
|
||||
|
||||
* New option in work reports web service. Included the possibility to remove a
|
||||
work report or work report line from the web service.
|
||||
|
||||
* Added option to configure personal timesheets periodicity, the possible values
|
||||
are: weekly, twice-monthly and monthly.
|
||||
|
||||
* Improvements in reports:
|
||||
|
||||
* Fixed font styles in generated PDF.
|
||||
* Created a new report called "Project Status" with the list of tasks from the
|
||||
WBS and using a new layout.
|
||||
|
||||
* Fixed date formats in the whole application (reports included). Now they
|
||||
follow the user locale conventions.
|
||||
|
||||
Notes
|
||||
~~~~~
|
||||
|
||||
If you are upgrading from 1.3.0 version without using the Debian package,
|
||||
you will need to manually execute on your database the SQL sentences from file:
|
||||
``scripts/database/upgrade_1.3.1.sql``.
|
||||
|
||||
If you are upgrading from a previous version without using the Debian package,
|
||||
review the *Notes* section for version 1.3.0.
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Thanks to all the contributors to this new version:
|
||||
|
||||
* Jacobo Aragunde Pérez
|
||||
* Javier Moran Rua
|
||||
* Manuel Rego Casasnovas
|
||||
|
||||
Translators
|
||||
~~~~~~~~~~~
|
||||
|
||||
Thanks to all the translators in this new version:
|
||||
|
||||
* [ca] Daniel Díaz Sañudo
|
||||
* [cs] Zbyněk Schwarz
|
||||
* [de] Michael Taxis
|
||||
* [es] Manuel Rego Casasnovas
|
||||
* [fr] Philippe Poumaroux
|
||||
* [gl] Manuel Rego Casasnovas
|
||||
* [it] Giuseppe Zizza
|
||||
* [nl] Jeroen Baten
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
* Update RPM package for LibrePlan 1.3.1
|
||||
* Update Debian package for LibrePlan 1.3.1
|
||||
* Update database scripts for LibrePlan 1.3.1
|
||||
* Bug #1542: Fix problem with deadline indicator when project finish right at the deadline
|
||||
* Bug #1542: Fix bug getting project end date from children tasks
|
||||
* Prevent NPE in SecurityUtils::isSuperuserOrRolePlanningOrHasAnyAuthorization
|
||||
* i18n: Mark label show in project status report to be translated
|
||||
* i18n: Update Czech translation
|
||||
* i18n: Update German translation
|
||||
* i18n: Update Spanish translation
|
||||
* i18n: Update Italian translation
|
||||
* i18n: Update Galician translation
|
||||
* i18n: Update French translation
|
||||
* i18n: Update Dutch translation
|
||||
* i18n: Update Catalan translation
|
||||
* doc: Update TODO file with the results of the roadmap meeting
|
||||
* Revert "Bug #1320: Fix issue changing methods to get constraints for a task"
|
||||
* Revert "Bug #1320: Recalculate position of siblings closing task properties pop-up"
|
||||
* Revert "Bug #1320: Recalculate position of siblings when moving a task"
|
||||
* doc: Update documentation about Active Directory configuration
|
||||
* Bug #1539: Do not reassociate with session resource bound to current user
|
||||
* Trying to fix broken test in Jenkins
|
||||
* Fix tests broken in commit b940c7882697833b696e54de5330a634e62ca701
|
||||
* i18n: Update keys.pot files
|
||||
* Fix typo in previous commit in message about maximum limit exceeded
|
||||
* Add restrictions by number of users and resources
|
||||
* Bug #1538: Detect inconsistent states on unsaved scheduling points.
|
||||
* Bug #1537: Fix issue getting allocations from memory and not from database
|
||||
* Simplify the way to calculate the length of money cost bars on the tasks in the Gantt diagram.
|
||||
* Allow codes of 2 digits for LibrePlan entities
|
||||
* Bug #1536: Do not regenerate project code when creating from template
|
||||
* Bug #1320: Recalculate position of siblings when moving a task
|
||||
* Bug #1320: Recalculate position of siblings closing task properties pop-up
|
||||
* Bug #1320: Fix issue changing methods to get constraints for a task
|
||||
* Bug #1534: Fix query to get info about expenses associated to an order
|
||||
* Bug #1529: Avoid exception in Cost tab in project details
|
||||
* Bug #1533: Change date format in reports footer to FULL instead of LONG
|
||||
* Fix error in labels page in menu
|
||||
* Configure properly file for Hibernate cache log
|
||||
* Using debug method for logging some messages that are meant for debugging
|
||||
* Fix unused id in bandbox_search.zul
|
||||
* Set level INFO for Hibernate cache logging
|
||||
* Bug #1533: Fix date formats in reports
|
||||
* Bug #1533: Avoid hard-coding date formats
|
||||
* Remove dependency to DejaVu fonts as are already included in jasperreport-fonts
|
||||
* Update name of zul for project status report
|
||||
* Increase size of prefix in tasks indentation
|
||||
* Add information about total estimated, planned and imputed hours
|
||||
* Indent tasks in project status report
|
||||
* Implement first version of project status report
|
||||
* Add basic report structure
|
||||
* Add basic controller and zul for budget report
|
||||
* Add option in menu and new role for new project status report
|
||||
* doc: Update guide to create a report with the changes in the last commits
|
||||
* Update documentation files and packages to add the dependency with DejaVu fonts
|
||||
* Using DejaVu Sans font in reports to avoid problems with PDFs
|
||||
* Add dependency to JasperReports fonts package
|
||||
* Bump JasperReports version to 4.7.0
|
||||
* Change method getOrder in IOrderModel to return an Order
|
||||
* Merge branch 'personal-timesheets-periodicity'
|
||||
* Use INTEGER instead of INT in Liquibase changelog
|
||||
* Fix the remaining bits where periodicity was not taken into account
|
||||
* Refactor source code to use personal timesheet instead of monthly timesheet
|
||||
* Improve representation of personal timesheets including month and year information
|
||||
* Improve documentation of new methods in PersonalTimesheetsPeriodicityEnum
|
||||
* Implement navigation between personal timesheets depending on periodicity
|
||||
* Update representation of personal timesheets in the UI depending on periodicity
|
||||
* Change the basic methods related to personal timesheets to take into account the periodicity
|
||||
* Refactoring code moving to methods in PersonalTimesheetsPeriodicityEnum
|
||||
* Modify the list of personal timehseets depending on the periodicity
|
||||
* doc: Fix typo "value gained" is "earned value"
|
||||
* Disable personal timesheets periodicity in configuration window if any personal timesheet was already saved
|
||||
* Add option to set personal timesheets periodicity in configuration window
|
||||
* Add new field in Configuration class to store the timesheets periodicity
|
||||
* Update name of personal timesheets work report type
|
||||
* Rename monthly timesheets to personal timesheets in the UI
|
||||
* Update web services documentation with information about the new delete services
|
||||
* Add method to remove a work report line from the web service
|
||||
* Add new method to delete a work report from the web service
|
||||
* Simplify code of WorkReportServiceREST using beforeSaving method
|
||||
* Prevent losing precision in TaskElementAdapter.calculateLimitDateByHours()
|
||||
* Use EffortDuration.zero() properly instead of more complex alternatives.
|
||||
* Bug #1528: Fix field TaskElement.notes in MySQL.
|
||||
* Add method getAuthenticationType() to avoid problems in edit window
|
||||
* doc: Update AUTHORS file info about new Catalan translator
|
||||
* i18n: Add Catalan language to enum and modify pom.xml to use Spanish userguide
|
||||
* i18n: Add Catalan translation
|
||||
* Does the users list sortable by user type (LDAP or Database).
|
||||
* Bug: Fixes sorting in both users and profiles list.
|
||||
* Bug: Configures right ascending sorting in companies list.
|
||||
* Bug #1527: Several interface disabling configurations modified.
|
||||
* Bug #1528: Check if name is null before truncating it.
|
||||
* Bug #1528: Change datatype for field TaskElement.notes to TEXT, which has no lenght limit.
|
||||
* Bug #1528: Trucate too long task names so they don't cause problems on save.
|
||||
* Small code refactor.
|
||||
* Bug #1523: Fix NPE in company view returning zero if progress is null
|
||||
* Fix parsing errors in NEWS file
|
||||
|
||||
|
||||
Version 1.3.0 (26 Jul 2012)
|
||||
---------------------------
|
||||
|
||||
|
|
@ -105,10 +105,6 @@ Requirements
|
|||
|
||||
To connect application with *PostgreSQL* database in *Tomcat*
|
||||
|
||||
* *GNU FreeFont* - Freefont Serif, Sans and Mono Truetype fonts
|
||||
|
||||
Font family used in reports
|
||||
|
||||
* *CutyCapt* - Utility to capture WebKit's rendering of a web page
|
||||
|
||||
Required for printing
|
||||
|
|
@ -126,7 +122,7 @@ Availability
|
|||
------------
|
||||
|
||||
The cutting-edge version of this project is always available from the Git
|
||||
repository at http://libreplan.git.sourceforge.net/.
|
||||
repository at https://github.com/Igalia/libreplan.
|
||||
|
||||
Released versions are available at
|
||||
http://sourceforge.net/projects/libreplan/files/.
|
||||
|
|
@ -1,60 +1,42 @@
|
|||
TODO
|
||||
====
|
||||
|
||||
Version 1.3 - 2012w14
|
||||
Version 1.4 - 2013w01
|
||||
---------------------
|
||||
|
||||
Dates
|
||||
~~~~~
|
||||
|
||||
* *IRC coordination meeting*: 2012w2
|
||||
* *Feature freeze*: 2012w11
|
||||
* *Release date*: 2012w14
|
||||
* *IRC coordination meeting*: 2012w41
|
||||
* *Feature freeze*: 2012w50
|
||||
* *Release date*: 2013w01
|
||||
|
||||
Features
|
||||
~~~~~~~~
|
||||
|
||||
* **Top priority**
|
||||
|
||||
* *Disable scenarios*: Scenarios feature is not tested properly and it's in an experimental state right now. We should directly remove the option from the UI to enable it and don't give the users the chance to enable scenarios as they can cause wrong behaviors in the tool.
|
||||
* Add a *filter by project status* in the projects screens.
|
||||
|
||||
* *WBS setting up behavior*: The current behavior of setting up the WBS is very strange related to containers. This feature is the one mentioned that was going to be implemented in the `user forum <https://sourceforge.net/projects/libreplan/forums/forum/1085570/topic/4538244>`_.
|
||||
* Add a *quicksearch to find projects* easier in the projects screens.
|
||||
|
||||
* *Include the management and support of a currency to apply to the project*: Now all the reports are in euros. Internationalization must include to allow to configure the currency used and the symbols to use.
|
||||
* *Right mouse menu register in the left menu of the project planning perspective*: It would be very useful and we have received the feedback of some users that it would be great to have this feature. Also the double-click over the project or task name.
|
||||
|
||||
* *Warning about new versions*: Add a warning in the bottom to administrators when a new version of LibrePlan is released.
|
||||
* *Protect the upper menu from abandoning the planning of a project without saving*: This feature was not completed in release 1.2 but had been decided to do so in `analysis mail <https://sourceforge.net/mailarchive/message.php?msg_id=27691109>`_.
|
||||
|
||||
This features consists of implementing a mechanism to display warnings to the users about the possibility to upgrade to a new version.
|
||||
It's also important review the behavior of advanced allocation window, we should prevent people change perspective without clicking "Apply" or even ask if they want to "Apply" if the click directly on "Save".
|
||||
|
||||
This system could be used to gather statistics about number of users with LibrePlan deployed in their machine (after notification and acceptance by the user of allowing to gather his data).
|
||||
|
||||
* *Permissions enhancement*: It was part of release 1.2 but was not done yet. Improve the permissions system adding new roles to report hours and other stuff. Pending to analyze deeply to define the implementation.
|
||||
|
||||
* *Bind users to resources*: This was part of the release 1.2 roadmap but was not started. New feature for simple users. Users would be related to application resources, and would be able to specify hours, progresses, ... on their assigned tasks.
|
||||
|
||||
* *Improve help and documentation*: Also part of 1.2 and not done yet. LibrePlan is quite big and it needs a better documentation to let users learn how to use it.
|
||||
* Improve *documentation*
|
||||
|
||||
* **Medium priority**
|
||||
|
||||
* *Allow to introduce minutes in WBS screen*: This is the last planning information which is not possible to insert in minutes. So, this task consists of allowing it.
|
||||
* *Import projects* from Microsfot Project and Planner.
|
||||
|
||||
Very close to this feature and maybe included in it would be to allow to specify quantities in a text format like: 8d7h
|
||||
* Review possible *performance* issues in order to look for some improvements.
|
||||
|
||||
* *Vertical line to show with the start of the project*: Show a line at the start of the project, something similar to what we do with the deadline.
|
||||
* Add a *new project status* called ``pre-sales``.
|
||||
|
||||
* *Improve allocation strategy calculate number of hours and calculate resources per day*: Currently is a bit complex to use this allocation strategies on using the workable days. This happens because you do not have control over the end date but over the workable days. This task will consists of translating from start/end date to workable days taking into account the task calendar.
|
||||
|
||||
* *KPIs per project*: There are being developed several KPI (Key Performance Indicators) per project. More info at wiki in story `AnA14S01PerProjectDashboard <http://wiki.libreplan.org/twiki/bin/view/LibrePlan/AnA14S01PerProjectDashboard>`_.
|
||||
|
||||
* *User experience improvements*: Improve user experience and aspect of some pages like the report ones (capturing input data ones). The idea is making the interaction with LibrePlan smoother, putting the focus on the newly created cells, easing the work just with the keyboard (the "name: input : Add button" system, that allows creating several elements without needing to point-n-click on things is an example).
|
||||
|
||||
* *Icons*: Improve icons and ask for them (possible integration with icons of the web).
|
||||
|
||||
* *Subcontracting module*: They are being implemented a set of tasks to implement improvements in subcontracting module. More info at wiki in story `AnA15SubcontractorModule <http://wiki.libreplan.org/twiki/bin/view/LibrePlan/AnA15SubcontractorModule>`_.
|
||||
|
||||
* *Upper menu revamp*: We have received the feedback that the upper menu is not understood many times correctly because it has the style of tabs.
|
||||
|
||||
* *Refactor entity model for templates*: This was part of release 1.2 but was not started yet. There are some internal issues in the implementation of templates.
|
||||
* *JIRA* integration
|
||||
|
||||
* *Show the load of the resources to be assigned in allocation pop-up*: This feature was in the roadmap for release 1.2 but there was not enough time to to it, so it is pending.
|
||||
|
||||
|
|
@ -66,7 +48,21 @@ Features
|
|||
|
||||
* *After being done*: In the allocation table a link to open a pop-up with a chart which shows the load of the resource would be included.
|
||||
|
||||
* *Right mouse menu register in the left menu of the project planning perspective*: It would be very useful and we have received the feedback of some users that it would be great to have this feature. Also the double-click over the project or task name.
|
||||
|
||||
Future & wish list
|
||||
------------------
|
||||
|
||||
* **Scheduling module**
|
||||
|
||||
* Save KPIs in database in order to wrap up the project status.
|
||||
|
||||
* Add a pipeline page to show projects grouped by status.
|
||||
|
||||
* *Allow to introduce minutes in WBS screen*: This is the last planning information which is not possible to insert in minutes. So, this task consists of allowing it.
|
||||
|
||||
Very close to this feature and maybe included in it would be to allow to specify quantities in a text format like: 8d7h
|
||||
|
||||
* *Improve allocation strategy calculate number of hours and calculate resources per day*: Currently is a bit complex to use this allocation strategies on using the workable days. This happens because you do not have control over the end date but over the workable days. This task will consists of translating from start/end date to workable days taking into account the task calendar.
|
||||
|
||||
* *Flaw when changing start/end date of project, or when changing the START_NOT_SOONER_THAN constraint from WBS*: If you change the start date of a project already planned this start date affects the start date of the tasks planned with constraint AS_SOON_AS_POSSIBLE. The same happens with the end date of a project and the constraint AS_LATER_AS_POSSIBLE.
|
||||
|
||||
|
|
@ -78,20 +74,6 @@ Features
|
|||
|
||||
There is another problem when you manipulate the WBS and there are already tasks planned with dependencies or allocations. Currently when certain movements are done you lose the dependencies and the allocations but the user is not even informed or asked. It should be provided a way to avoid this undesirable situation.
|
||||
|
||||
* *Android application*: Develop an Android application to allow work report adding as a first approach to make LibrePlan work from smartphones.
|
||||
|
||||
It would use the LibrePlan webservices to add the work reports. Of course this should be improved and it would make many more things in the future, but as a first approach seems to be ok.
|
||||
|
||||
* *Protect the upper menu from abandoning the planning of a project without saving*: This feature was not completed in release 1.2 but had been decided to do so in `analysis mail <https://sourceforge.net/mailarchive/message.php?msg_id=27691109>`_.
|
||||
|
||||
It's also important review the behavior of advanced allocation window, we should prevent people change perspective without clicking "Apply" or even ask if they want to "Apply" if the click directly on "Save".
|
||||
|
||||
|
||||
Future & wish list
|
||||
------------------
|
||||
|
||||
* **Scheduling module**
|
||||
|
||||
* *Establishing dependencies from pop-up (form based interface)*: Now the only way to set up dependencies between activities is by dragging the arrow from the origin task and by releasing it in the destination task.
|
||||
|
||||
This feature would consist of implementing a text based interface to managing dependencies. Two major advantages:
|
||||
|
|
@ -165,6 +147,14 @@ Future & wish list
|
|||
|
||||
* **Usability module**
|
||||
|
||||
* Make WBS screen more user-friendly with more keyboard shortcuts and some other thins like columns for dependencies and so on.
|
||||
|
||||
* *User experience improvements*: Improve user experience and aspect of some pages like the report ones (capturing input data ones). The idea is making the interaction with LibrePlan smoother, putting the focus on the newly created cells, easing the work just with the keyboard (the "name: input : Add button" system, that allows creating several elements without needing to point-n-click on things is an example).
|
||||
|
||||
* *Icons*: Improve icons and ask for them (possible integration with icons of the web).
|
||||
|
||||
* *Upper menu revamp*: We have received the feedback that the upper menu is not understood many times correctly because it has the style of tabs.
|
||||
|
||||
* *Menu breadcrumbs*: Proposed to be removed or at least being made consistent.
|
||||
|
||||
* *Improve error detection at perspective changes*: Improve the detection of errors and prevent to do a perspective change on planning a project.
|
||||
|
|
@ -183,8 +173,23 @@ Future & wish list
|
|||
|
||||
* *Allow workers to ask for holidays*: Allow workers -if the profile is created- to ask for holidays. Each worker has a calendar assigned, and he/she could ask for the vacation days. Then, a reviewer -project manager- could confirm or deny that vacation days.
|
||||
|
||||
* Include the groups feature:
|
||||
|
||||
* A group or department will be composed by a list of resources.
|
||||
* Add filters to show only projects/resources belonging to a group.
|
||||
|
||||
* *Refactor entity model for templates*: This was part of release 1.2 but was not started yet. There are some internal issues in the implementation of templates.
|
||||
|
||||
* **Other**
|
||||
|
||||
* Add CSV import/export for projects.
|
||||
|
||||
* Print Gantt chart in PDF format.
|
||||
|
||||
* *Android application*: Develop an Android application to allow work report adding as a first approach to make LibrePlan work from smartphones.
|
||||
|
||||
It would use the LibrePlan webservices to add the work reports. Of course this should be improved and it would make many more things in the future, but as a first approach seems to be ok.
|
||||
|
||||
* Add export/import operations for different format files from other projects like OpenProj, MicrosoftProject, ...
|
||||
|
||||
* Base line in projects.
|
||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
1.3.0
|
||||
1.3.3
|
||||
|
|
|
|||
19
debian/changelog
vendored
19
debian/changelog
vendored
|
|
@ -1,3 +1,22 @@
|
|||
libreplan (1.3.3-1) squeeze; urgency=low
|
||||
|
||||
* Released LibrePlan 1.3.3
|
||||
|
||||
-- Manuel Rego Casasnovas <rego@igalia.com> Fri, 21 Dec 2012 14:26:56 +0100
|
||||
|
||||
libreplan (1.3.2-1) squeeze; urgency=low
|
||||
|
||||
* Released LibrePlan 1.3.2
|
||||
|
||||
-- Manuel Rego Casasnovas <rego@igalia.com> Fri, 30 Nov 2012 07:26:59 +0100
|
||||
|
||||
libreplan (1.3.1-1) squeeze; urgency=low
|
||||
|
||||
* Released LibrePlan 1.3.1
|
||||
* Removed dependency with ttf-freefont
|
||||
|
||||
-- Manuel Rego Casasnovas <rego@igalia.com> Mon, 15 Oct 2012 13:55:06 +0200
|
||||
|
||||
libreplan (1.3.0-1) squeeze; urgency=low
|
||||
|
||||
* Released LibrePlan 1.3.0
|
||||
|
|
|
|||
3
debian/control
vendored
3
debian/control
vendored
|
|
@ -10,8 +10,7 @@ Homepage: http://www.libreplan.com/
|
|||
Package: libreplan
|
||||
Architecture: any
|
||||
Depends: cutycapt, postgresql, postgresql-client, xvfb, dbconfig-common, ucf,
|
||||
tomcat6, default-jre-headless | default-jre, libpg-java, ttf-freefont,
|
||||
${misc:Depends}
|
||||
tomcat6, default-jre-headless | default-jre, libpg-java, ${misc:Depends}
|
||||
Description: Web application for project planning, monitoring and control.
|
||||
LibrePlan is a collaborative tool to plan, monitor and control projects and has
|
||||
a rich web interface which provides a desktop alike user experience. All the
|
||||
|
|
|
|||
3
debian/control.lucid
vendored
3
debian/control.lucid
vendored
|
|
@ -10,8 +10,7 @@ Homepage: http://www.libreplan.com/
|
|||
Package: libreplan
|
||||
Architecture: any
|
||||
Depends: cutycapt, postgresql, postgresql-client, xvfb, dbconfig-common, ucf,
|
||||
tomcat6, openjdk-6-jre-headless | openjdk-6-jre, libpg-java, ttf-freefont,
|
||||
${misc:Depends}
|
||||
tomcat6, openjdk-6-jre-headless | openjdk-6-jre, libpg-java, ${misc:Depends}
|
||||
Description: Web application for project planning, monitoring and control.
|
||||
LibrePlan is a collaborative tool to plan, monitor and control projects and has
|
||||
a rich web interface which provides a desktop alike user experience. All the
|
||||
|
|
|
|||
3
debian/control.squeeze
vendored
3
debian/control.squeeze
vendored
|
|
@ -10,8 +10,7 @@ Homepage: http://www.libreplan.com/
|
|||
Package: libreplan
|
||||
Architecture: any
|
||||
Depends: cutycapt, postgresql, postgresql-client, xvfb, dbconfig-common, ucf,
|
||||
tomcat6, openjdk-6-jre-headless | openjdk-6-jre, libpg-java, ttf-freefont,
|
||||
${misc:Depends}
|
||||
tomcat6, openjdk-6-jre-headless | openjdk-6-jre, libpg-java, ${misc:Depends}
|
||||
Description: Web application for project planning, monitoring and control.
|
||||
LibrePlan is a collaborative tool to plan, monitor and control projects and has
|
||||
a rich web interface which provides a desktop alike user experience. All the
|
||||
|
|
|
|||
2
debian/libreplan.install
vendored
2
debian/libreplan.install
vendored
|
|
@ -8,3 +8,5 @@ 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
|
||||
debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.3.0
|
||||
debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.3.1
|
||||
debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.3.2
|
||||
|
|
|
|||
4
debian/libreplan.postinst
vendored
4
debian/libreplan.postinst
vendored
|
|
@ -118,4 +118,8 @@ if [ -x /etc/init.d/tomcat6 ] ; then
|
|||
fi
|
||||
fi
|
||||
|
||||
echo 'Please review the Tomcat6 memory configuration in your server at /etc/default/tomcat6 file.
|
||||
Furthermore, in order to have printing working properly if you are in Debian Squeeze you have to install CutyCapt package from Wheezy (testing).
|
||||
You can find more information about these issues at INSTALL file or in the following link: http://libreplan.org/INSTALL.html'
|
||||
|
||||
#DEBHELPER#
|
||||
|
|
|
|||
6
debian/rules
vendored
6
debian/rules
vendored
|
|
@ -96,6 +96,12 @@ install:
|
|||
# Copy SQL upgrade script for version 1.3.0
|
||||
$(call CMD,cp $(CURDIR)/scripts/database/upgrade_1.3.0.sql \
|
||||
$(CURDIR)/debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.3.0)
|
||||
# Copy SQL upgrade script for version 1.3.1
|
||||
$(call CMD,cp $(CURDIR)/scripts/database/upgrade_1.3.1.sql \
|
||||
$(CURDIR)/debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.3.1)
|
||||
# Copy SQL upgrade script for version 1.3.2
|
||||
$(call CMD,cp $(CURDIR)/scripts/database/upgrade_1.3.2.sql \
|
||||
$(CURDIR)/debian/tmp/usr/share/dbconfig-common/data/libreplan/upgrade/pgsql/1.3.2)
|
||||
# Install Policy file
|
||||
$(call CMD,mkdir -p $(CURDIR)/debian/tmp/etc/tomcat6/policy.d)
|
||||
$(call CMD,cp $(CURDIR)/debian/51libreplan.policy \
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Para comezar a traballar o primerio que terá que facer o desenvolvedor e descar
|
|||
|
||||
::
|
||||
|
||||
$ git clone git://libreplan.git.sourceforge.net/gitroot/libreplan/libreplan
|
||||
$ git clone git://github.com/Igalia/libreplan.git
|
||||
|
||||
|
||||
Esto creará unha copia local de trabajo, para empezar a trabajar se recomienda la creación de una rama para cada caso de uso a desarrollar o nombre de la rama é recomendable que teña realación coa funcionalidade que implemente ou o número de bug que trata de solucionar, e logo nos movemos a traballar na rama cun checkout.
|
||||
|
|
@ -152,7 +152,7 @@ A diferencia do resto dos usuarios debería descargar o repositorio da seguinte
|
|||
|
||||
::
|
||||
|
||||
$ git clone ssh://user@libreplan.git.sourceforge.net/gitroot/libreplan/libreplan
|
||||
$ git clone git@github.com:Igalia/libreplan.git
|
||||
|
||||
|
||||
Esta forma de acceso permite un acceso de escritura ao repositorio:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ How To Create A New Report In LibrePlan
|
|||
|
||||
:Author: Manuel Rego Casasnovas
|
||||
:Contact: mrego@igalia.com
|
||||
:Date: 01/03/2011
|
||||
:Date: 11/09/2012
|
||||
:Copyright:
|
||||
Some rights reserved. This document is distributed under the Creative
|
||||
Commons Attribution-ShareAlike 3.0 licence, available in
|
||||
|
|
@ -108,10 +108,6 @@ Steps:
|
|||
<?component name="combobox_output_format" macroURI="combobox_output_format.zul"
|
||||
class="org.libreplan.web.reports.ComboboxOutputFormat" ?>
|
||||
|
||||
<?component name="extendedjasperreport"
|
||||
class="org.libreplan.web.common.components.ExtendedJasperreport"
|
||||
extends="jasperreport" ?>
|
||||
|
||||
<zk>
|
||||
|
||||
<window self="@{define(content)}"
|
||||
|
|
@ -138,18 +134,21 @@ Steps:
|
|||
</panelchildren>
|
||||
</panel>
|
||||
|
||||
<separator spacing="10px" orient="horizontal" />
|
||||
|
||||
<hbox style="display: none" id="URItext">
|
||||
<label value="${i18n:_('Click on ')}" />
|
||||
<toolbarbutton id="URIlink" class="z-label" zclass="z-label"
|
||||
<label value="${i18n:_('Click on this')}" />
|
||||
<a id="URIlink" class="z-label" zclass="z-label"
|
||||
label="${i18n:_('direct link')}" />
|
||||
<label value="${i18n:_(' to go to output directly')}" />
|
||||
<label
|
||||
value="${i18n:_('if the report is not opened automatically')}" />
|
||||
</hbox>
|
||||
|
||||
<separator spacing="10px" orient="horizontal" />
|
||||
|
||||
<button label="Show" onClick="controller.showReport(report)" />
|
||||
|
||||
<extendedjasperreport style="display: none" id="report" />
|
||||
<jasperreportcomponent id="report" />
|
||||
|
||||
</window>
|
||||
|
||||
|
|
@ -217,7 +216,7 @@ Steps:
|
|||
@Override
|
||||
public void doAfterCompose(Component comp) throws Exception {
|
||||
super.doAfterCompose(comp);
|
||||
comp.setVariable("controller", this, true);
|
||||
comp.setAttribute("controller", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -318,16 +317,16 @@ report layouts, which provides a visual interface to define ``.jrxml`` file.
|
|||
|
||||
Steps:
|
||||
|
||||
* Download iReport **3.7.0** (``tar.gz``) from SourceForge.net:
|
||||
* Download iReport **4.7.0** (``tar.gz``) from SourceForge.net:
|
||||
https://sourceforge.net/projects/ireport/files/iReport/
|
||||
|
||||
* Uncompress file::
|
||||
|
||||
tar -xvzf iReport-3.7.0.tar.gz
|
||||
tar -xvzf iReport-4.7.0.tar.gz
|
||||
|
||||
* Launch iReport::
|
||||
|
||||
cd iReport-3.7.0/
|
||||
cd iReport-4.7.0/
|
||||
./bin/ireport
|
||||
|
||||
* Open some existent LibrePlan report (e.g.
|
||||
|
|
@ -393,14 +392,11 @@ something similar to the following content:
|
|||
::
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports
|
||||
http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="resourcesList"
|
||||
pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20"
|
||||
rightMargin="20" topMargin="20" bottomMargin="20"
|
||||
resourceBundle="resourcesList">
|
||||
<reportFont name="FreeSans" isDefault="true" fontName="FreeSans" size="9"/>
|
||||
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="resourcesList" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" resourceBundle="resourcesList" uuid="f83422af-00de-4fa5-b137-580b559f1453">
|
||||
<property name="ireport.zoom" value="1.0"/>
|
||||
<property name="ireport.x" value="0"/>
|
||||
<property name="ireport.y" value="0"/>
|
||||
<style name="dejavu-sans" isDefault="true" fontName="DejaVu Sans" fontSize="8"/>
|
||||
<parameter name="logo" class="java.lang.String"/>
|
||||
<field name="code" class="java.lang.String"/>
|
||||
<field name="name" class="java.lang.String"/>
|
||||
|
|
@ -410,22 +406,22 @@ something similar to the following content:
|
|||
<title>
|
||||
<band height="80" splitType="Stretch">
|
||||
<textField>
|
||||
<reportElement x="0" y="13" width="263" height="33"/>
|
||||
<reportElement uuid="6d64d335-2ffd-45e8-8915-3191baa4e278" x="0" y="13" width="263" height="33"/>
|
||||
<textElement verticalAlignment="Middle" markup="none">
|
||||
<font size="23" isBold="true"/>
|
||||
</textElement>
|
||||
<textFieldExpression class="java.lang.String"><![CDATA[$R{title}]]></textFieldExpression>
|
||||
<textFieldExpression><![CDATA[$R{title}]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField>
|
||||
<reportElement x="23" y="46" width="295" height="22"/>
|
||||
<reportElement uuid="2174417c-89a2-4012-8915-8f8e3fa8119e" x="23" y="46" width="295" height="22"/>
|
||||
<textElement markup="none">
|
||||
<font size="15" isItalic="true"/>
|
||||
</textElement>
|
||||
<textFieldExpression class="java.lang.String"><![CDATA[$R{subtitle}]]></textFieldExpression>
|
||||
<textFieldExpression><![CDATA[$R{subtitle}]]></textFieldExpression>
|
||||
</textField>
|
||||
<image scaleImage="RetainShape">
|
||||
<reportElement x="318" y="0" width="180" height="53"/>
|
||||
<imageExpression class="java.lang.String"><![CDATA[$P{logo}]]></imageExpression>
|
||||
<reportElement uuid="e033fa20-c68f-4716-9b43-e1435be185a8" x="318" y="0" width="180" height="53"/>
|
||||
<imageExpression><![CDATA[$P{logo}]]></imageExpression>
|
||||
</image>
|
||||
</band>
|
||||
</title>
|
||||
|
|
@ -438,14 +434,14 @@ something similar to the following content:
|
|||
<detail>
|
||||
<band height="15" splitType="Stretch">
|
||||
<textField isBlankWhenNull="true">
|
||||
<reportElement x="145" y="0" width="414" height="15"/>
|
||||
<reportElement uuid="5a829e90-0860-48dd-aeb0-262599571b4a" x="145" y="0" width="414" height="15"/>
|
||||
<textElement textAlignment="Center" verticalAlignment="Middle"/>
|
||||
<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
|
||||
<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField isBlankWhenNull="true">
|
||||
<reportElement x="13" y="0" width="132" height="15"/>
|
||||
<reportElement uuid="78755bf1-f99a-4aa3-a87a-13ed4e54ce60" x="13" y="0" width="132" height="15"/>
|
||||
<textElement textAlignment="Center" verticalAlignment="Middle"/>
|
||||
<textFieldExpression class="java.lang.String"><![CDATA[$F{code}]]></textFieldExpression>
|
||||
<textFieldExpression><![CDATA[$F{code}]]></textFieldExpression>
|
||||
</textField>
|
||||
</band>
|
||||
</detail>
|
||||
|
|
@ -454,36 +450,30 @@ something similar to the following content:
|
|||
</columnFooter>
|
||||
<pageFooter>
|
||||
<band height="27" splitType="Stretch">
|
||||
<textField pattern="EEEEE dd MMMMM yyyy">
|
||||
<reportElement x="0" y="0" width="197" height="20"/>
|
||||
<textElement>
|
||||
<font size="10" isBold="false"/>
|
||||
</textElement>
|
||||
<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
|
||||
<textField pattern="EEEEE, dd MMMMM yyyy">
|
||||
<reportElement uuid="74fb7d79-5caa-42db-b9c8-8b0e5a6b38da" x="0" y="0" width="197" height="20"/>
|
||||
<textElement/>
|
||||
<textFieldExpression><![CDATA[new java.util.Date()]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField>
|
||||
<reportElement x="435" y="2" width="43" height="20"/>
|
||||
<reportElement uuid="1bb28642-13dd-469d-937b-0eb361cea34e" x="435" y="2" width="43" height="20"/>
|
||||
<textElement/>
|
||||
<textFieldExpression class="java.lang.String"><![CDATA[$R{page}]]></textFieldExpression>
|
||||
<textFieldExpression><![CDATA[$R{page}]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField>
|
||||
<reportElement x="498" y="2" width="15" height="20"/>
|
||||
<reportElement uuid="a0067519-9437-4549-b9ca-70bb8abd86ef" x="498" y="2" width="15" height="20"/>
|
||||
<textElement/>
|
||||
<textFieldExpression class="java.lang.String"><![CDATA[$R{of}]]></textFieldExpression>
|
||||
<textFieldExpression><![CDATA[$R{of}]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField evaluationTime="Report">
|
||||
<reportElement x="515" y="2" width="38" height="20"/>
|
||||
<textElement>
|
||||
<font size="10" isBold="false"/>
|
||||
</textElement>
|
||||
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
|
||||
<reportElement uuid="49abaabf-9c24-4078-8551-632c03e5aebb" x="515" y="2" width="38" height="20"/>
|
||||
<textElement/>
|
||||
<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
|
||||
</textField>
|
||||
<textField>
|
||||
<reportElement x="478" y="2" width="15" height="20"/>
|
||||
<textElement textAlignment="Right">
|
||||
<font size="10" isBold="false"/>
|
||||
</textElement>
|
||||
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
|
||||
<reportElement uuid="3b2e8d7e-d96f-4f30-aa3b-80300629dda7" x="478" y="2" width="15" height="20"/>
|
||||
<textElement textAlignment="Right"/>
|
||||
<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
|
||||
</textField>
|
||||
</band>
|
||||
</pageFooter>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ options:
|
|||
|
||||
a) Clone Git repository (recommended)::
|
||||
|
||||
$ git clone git://libreplan.git.sourceforge.net/gitroot/libreplan/libreplan libreplan
|
||||
$ git clone git://github.com/Igalia/libreplan.git
|
||||
|
||||
b) Download last version source code::
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ The planning view combines three different views:
|
|||
* Orange area: Indicating a resource load over 100% as a result of the current project.
|
||||
* Yellow area: Indicating a resource load over 100% as a result of other projects.
|
||||
|
||||
* Graph view and value gained indicators. These can be viewed from the "Value gained" tab. The generated graph is based on the value gained technique and the indicators that are calculated for each of the workdays of the project. The calculated indicators are:
|
||||
* Graph view and earned value indicators. These can be viewed from the "Earned value" tab. The generated graph is based on the earned value technique and the indicators that are calculated for each of the workdays of the project. The calculated indicators are:
|
||||
|
||||
* BCWS: accumulative time function for the number of hours planned up to a certain date. It will be 0 at the planned start of the task and the total number of planned hours at the end. As with all accumulative graphs, it will always increase. The function for a task will be the sum of the daily assignments until the calculation day. This function has values for all times, provided that resources have been assigned.
|
||||
* ACWP: accumulative time function for the hours attributed in the work reports up to a certain date. This function will only have a value of 0 before the date of the task's first work report and its value will continue to increase as time passes and work report hours are added. It will have no value after the date of the last work report.
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ configuration.
|
|||
If your LDAP is configured to work with anonymous authentication you can
|
||||
leave empty *UserDN* and *Password* attributes.
|
||||
|
||||
.. TIP::
|
||||
|
||||
About *Active Directory (AD)* configuration, the *Base* field must be the
|
||||
exact location where the bound user lives in the AD.
|
||||
|
||||
Example: ``ou=organizational_unit,dc=example,dc=org``
|
||||
|
||||
Authentication
|
||||
==============
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ Previous Team Members
|
|||
Translators
|
||||
-----------
|
||||
|
||||
* [ca] Daniel Díaz Sañudo <gurnan@gmail.com>
|
||||
* [cs] Zbyněk Schwarz <zbynek.schwarz@gmail.com>
|
||||
* [de] Joern Knechtel <j.knechtel@gmx.de>,
|
||||
Michael Taxis <mxtaxis@gmx.de>
|
||||
|
|
@ -81,9 +82,11 @@ Translators
|
|||
* [it] Giuseppe Zizza <gzizza@gmail.com>
|
||||
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
|
||||
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
|
||||
* [pt] Helena Grosso <lenagrosso@gmail.com>,
|
||||
* [pt] Thiago Cangussu <cangussu.br@gmail.com>,
|
||||
Helena Grosso <lenagrosso@gmail.com>,
|
||||
Joaquim Rocha <jrocha@igalia.com>
|
||||
* [ru] Pavel Rudensky <prudensky@gmail.com>
|
||||
* [zh] Swanson Chan <lacidophilin@yahoo.com>
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ conexión antes de continuar con la configuración.
|
|||
Si su LDAP está configurado para trabajar con autenticación anónima puede
|
||||
dejar vacíos los atributos *UserDN* y *Contraseña*.
|
||||
|
||||
.. TIP::
|
||||
|
||||
Sobre la configuración de *Active Directory (AD)*, el campo *Base* debe ser
|
||||
la localización exacta donde reside el usuario vinculado en el AD.
|
||||
|
||||
Ejemplo: ``ou=organizational_unit,dc=example,dc=org``
|
||||
|
||||
Autenticación
|
||||
=============
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ Anteriores miembros del equipo
|
|||
Traductores
|
||||
-----------
|
||||
|
||||
* [ca] Daniel Díaz Sañudo <gurnan@gmail.com>
|
||||
* [cs] Zbyněk Schwarz <zbynek.schwarz@gmail.com>
|
||||
* [de] Joern Knechtel <j.knechtel@gmx.de>,
|
||||
Michael Taxis <mxtaxis@gmx.de>
|
||||
|
|
@ -81,9 +82,11 @@ Traductores
|
|||
* [it] Giuseppe Zizza <gzizza@gmail.com>
|
||||
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
|
||||
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
|
||||
* [pt] Helena Grosso <lenagrosso@gmail.com>,
|
||||
* [pt] Thiago Cangussu <cangussu.br@gmail.com>,
|
||||
Helena Grosso <lenagrosso@gmail.com>,
|
||||
Joaquim Rocha <jrocha@igalia.com>
|
||||
* [ru] Pavel Rudensky <prudensky@gmail.com>
|
||||
* [zh] Swanson Chan <lacidophilin@yahoo.com>
|
||||
|
||||
Contribuidores
|
||||
--------------
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ continuar coa configuración.
|
|||
Se o seu LDAP está configurado para traballar con autenticación anónima pode
|
||||
deixar baleiros oos atributos *UserDN* e *Contrasinal*.
|
||||
|
||||
.. TIP::
|
||||
|
||||
Sobre a configuración de *Active Directory (AD)*, o campo *Base* debe ser
|
||||
a localización exacta onde reside o usuario vinculado no AD.
|
||||
|
||||
Exemplo: ``ou=organizational_unit,dc=example,dc=org``
|
||||
|
||||
Autenticación
|
||||
=============
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ Anteriores membros do equipo
|
|||
Traductores
|
||||
-----------
|
||||
|
||||
* [ca] Daniel Díaz Sañudo <gurnan@gmail.com>
|
||||
* [cs] Zbyněk Schwarz <zbynek.schwarz@gmail.com>
|
||||
* [de] Joern Knechtel <j.knechtel@gmx.de>,
|
||||
Michael Taxis <mxtaxis@gmx.de>
|
||||
|
|
@ -81,9 +82,11 @@ Traductores
|
|||
* [it] Giuseppe Zizza <gzizza@gmail.com>
|
||||
* [nl] Jeroen Baten <jeroen@jeroenbaten.nl>
|
||||
* [pl] Krzysztof Kamecki <dwerens90@gmail.com>
|
||||
* [pt] Helena Grosso <lenagrosso@gmail.com>,
|
||||
* [pt] Thiago Cangussu <cangussu.br@gmail.com>,
|
||||
Helena Grosso <lenagrosso@gmail.com>,
|
||||
Joaquim Rocha <jrocha@igalia.com>
|
||||
* [ru] Pavel Rudensky <prudensky@gmail.com>
|
||||
* [zh] Swanson Chan <lacidophilin@yahoo.com>
|
||||
|
||||
Contribuidores
|
||||
--------------
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.libreplan</groupId>
|
||||
<artifactId>libreplan</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.3</version>
|
||||
</parent>
|
||||
<artifactId>ganttzk</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -41,8 +41,11 @@ import org.zkoss.ganttz.data.Task;
|
|||
import org.zkoss.ganttz.util.ComponentsFinder;
|
||||
import org.zkoss.util.Locales;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.Execution;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zk.ui.event.KeyEvent;
|
||||
import org.zkoss.zk.ui.util.GenericForwardComposer;
|
||||
import org.zkoss.zul.Datebox;
|
||||
|
|
@ -421,6 +424,15 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
|
|||
} else {
|
||||
nameLabel.setValue(task.getName());
|
||||
nameLabel.setTooltiptext(task.getName());
|
||||
nameLabel.setSclass("clickable-rows");
|
||||
nameLabel.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event arg0) throws Exception {
|
||||
Executions.getCurrent().sendRedirect(
|
||||
"/planner/index.zul;order="
|
||||
+ task.getProjectCode());
|
||||
}
|
||||
});
|
||||
startDateLabel.setValue(asString(task.getBeginDate()
|
||||
.toDayRoundedDate()));
|
||||
endDateLabel.setValue(asString(task.getEndDate()
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ import org.zkoss.zul.Listbox;
|
|||
import org.zkoss.zul.Listitem;
|
||||
import org.zkoss.zul.SimpleListModel;
|
||||
import org.zkoss.zul.South;
|
||||
import org.zkoss.zul.api.Combobox;
|
||||
|
||||
public class Planner extends HtmlMacroComponent {
|
||||
|
||||
|
|
@ -143,8 +144,6 @@ public class Planner extends HtmlMacroComponent {
|
|||
|
||||
private GanttPanel ganttPanel;
|
||||
|
||||
private boolean fixedZoomByUser = false;
|
||||
|
||||
private List<? extends CommandContextualized<?>> contextualizedGlobalCommands;
|
||||
|
||||
private CommandContextualized<?> goingDownInLastArrowCommand;
|
||||
|
|
@ -173,7 +172,7 @@ public class Planner extends HtmlMacroComponent {
|
|||
|
||||
private boolean isFlattenTree = false;
|
||||
|
||||
private ZoomLevel initialZoomLevel = null;
|
||||
private ZoomLevel zoomLevel = null;
|
||||
|
||||
private Listbox listZoomLevels = null;
|
||||
|
||||
|
|
@ -275,8 +274,7 @@ public class Planner extends HtmlMacroComponent {
|
|||
if (ganttPanel == null) {
|
||||
return;
|
||||
}
|
||||
this.fixedZoomByUser = true;
|
||||
initialZoomLevel = zoomLevel;
|
||||
this.zoomLevel = zoomLevel;
|
||||
ganttPanel.setZoomLevel(zoomLevel, scrollLeft);
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +344,7 @@ public class Planner extends HtmlMacroComponent {
|
|||
resettingPreviousComponentsToNull();
|
||||
long timeAddingData = System.currentTimeMillis();
|
||||
newContext.add(configuration.getData());
|
||||
PROFILING_LOG.info("It took to add data: "
|
||||
PROFILING_LOG.debug("It took to add data: "
|
||||
+ (System.currentTimeMillis() - timeAddingData) + " ms");
|
||||
long timeSetupingAndAddingComponents = System.currentTimeMillis();
|
||||
setupComponents();
|
||||
|
|
@ -394,7 +392,7 @@ public class Planner extends HtmlMacroComponent {
|
|||
((South) getFellow("graphics")).setOpen(this.visibleChart);
|
||||
|
||||
PROFILING_LOG
|
||||
.info("it took doing the setup of components and adding them: "
|
||||
.debug("it took doing the setup of components and adding them: "
|
||||
+ (System.currentTimeMillis() - timeSetupingAndAddingComponents)
|
||||
+ " ms");
|
||||
|
||||
|
|
@ -509,9 +507,11 @@ public class Planner extends HtmlMacroComponent {
|
|||
}
|
||||
for (CommandContextualized<?> c : contextualizedGlobalCommands) {
|
||||
// Comparison through icon as name is internationalized
|
||||
if (c.getCommand().getImage()
|
||||
.equals("/common/img/ico_reassign.png")) {
|
||||
if (plannerToolbar.getChildren().isEmpty()) {
|
||||
if (c.getCommand().isPlannerCommand()) {
|
||||
// FIXME Avoid hard-coding the number of planner commands
|
||||
// At this moment we have 2 planner commands: reassign and adapt
|
||||
// planning
|
||||
if (plannerToolbar.getChildren().size() < 2) {
|
||||
plannerToolbar.appendChild(c.toButton());
|
||||
}
|
||||
} else {
|
||||
|
|
@ -634,11 +634,15 @@ public class Planner extends HtmlMacroComponent {
|
|||
public void showAdvances() {
|
||||
Button showAdvancesButton = (Button) getFellow("showAdvances");
|
||||
if (disabilityConfiguration.isAdvancesEnabled()) {
|
||||
Combobox progressTypesCombo = (Combobox) getFellow("cbProgressTypes");
|
||||
if (isShowingAdvances) {
|
||||
context.hideAdvances();
|
||||
diagramGraph.removePostGraphChangeListener(showAdvanceOnChange);
|
||||
showAdvancesButton.setSclass("planner-command");
|
||||
showAdvancesButton.setTooltiptext(_("Show progress"));
|
||||
if (progressTypesCombo.getItemCount() > 0) {
|
||||
progressTypesCombo.setSelectedIndex(0);
|
||||
}
|
||||
} else {
|
||||
context.showAdvances();
|
||||
diagramGraph.addPostGraphChangeListener(showAdvanceOnChange);
|
||||
|
|
@ -725,22 +729,14 @@ public class Planner extends HtmlMacroComponent {
|
|||
|
||||
public ZoomLevel getZoomLevel() {
|
||||
if (ganttPanel == null) {
|
||||
return initialZoomLevel != null ? initialZoomLevel
|
||||
return zoomLevel != null ? zoomLevel
|
||||
: ZoomLevel.DETAIL_ONE;
|
||||
}
|
||||
return ganttPanel.getTimeTracker().getDetailLevel();
|
||||
}
|
||||
|
||||
public boolean isFixedZoomByUser() {
|
||||
return this.fixedZoomByUser;
|
||||
}
|
||||
|
||||
public void setInitialZoomLevel(final ZoomLevel zoomLevel) {
|
||||
if (this.initialZoomLevel != null) {
|
||||
// already initialized
|
||||
return;
|
||||
}
|
||||
this.initialZoomLevel = zoomLevel;
|
||||
this.zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
public boolean areContainersExpandedByDefault() {
|
||||
|
|
@ -814,13 +810,12 @@ public class Planner extends HtmlMacroComponent {
|
|||
}
|
||||
|
||||
public void updateSelectedZoomLevel() {
|
||||
if (!isFixedZoomByUser()) {
|
||||
ganttPanel.getTimeTracker().setZoomLevel(zoomLevel);
|
||||
Listitem selectedItem = (Listitem) listZoomLevels.getItems().get(
|
||||
initialZoomLevel.ordinal());
|
||||
zoomLevel.ordinal());
|
||||
listZoomLevels.setSelectedItem(selectedItem);
|
||||
listZoomLevels.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public IContext<?> getContext() {
|
||||
return context;
|
||||
|
|
@ -942,4 +937,18 @@ public class Planner extends HtmlMacroComponent {
|
|||
}
|
||||
}
|
||||
|
||||
public TaskComponent getTaskComponentRelatedTo(
|
||||
org.zkoss.ganttz.data.Task task) {
|
||||
TaskList taskList = getTaskList();
|
||||
if (taskList != null) {
|
||||
for (TaskComponent each : taskList.getTaskComponents()) {
|
||||
if (each.getTask().equals(task)) {
|
||||
return each;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,14 @@ package org.zkoss.ganttz;
|
|||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Days;
|
||||
import org.joda.time.Duration;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.zkoss.ganttz.adapters.IDisabilityConfiguration;
|
||||
import org.zkoss.ganttz.data.GanttDate;
|
||||
|
|
@ -215,6 +218,9 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
: "";
|
||||
} else {
|
||||
cssClass += task.isInCriticalPath() ? " critical" : "";
|
||||
if (!task.canBeExplicitlyMoved()) {
|
||||
cssClass += " fixed";
|
||||
}
|
||||
}
|
||||
cssClass += " " + task.getAssignedStatus();
|
||||
if (task.isLimiting()) {
|
||||
|
|
@ -514,19 +520,47 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||
String widthHoursAdvancePercentage = pixelsFromStartUntil(
|
||||
startPixels,
|
||||
this.task.getHoursAdvanceEndDate()) + "px";
|
||||
this.task.getHoursAdvanceBarEndDate()) + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletionAdvance",
|
||||
widthHoursAdvancePercentage));
|
||||
|
||||
Date firstTimesheetDate = task.getFirstTimesheetDate();
|
||||
Date lastTimesheetDate = task.getLastTimesheetDate();
|
||||
if (firstTimesheetDate != null && lastTimesheetDate != null) {
|
||||
Duration firstDuration = Days.daysBetween(
|
||||
task.getBeginDateAsLocalDate(),
|
||||
LocalDate.fromDateFields(firstTimesheetDate))
|
||||
.toStandardDuration();
|
||||
int pixelsFirst = getMapper().toPixels(firstDuration);
|
||||
String positionFirst = pixelsFirst + "px";
|
||||
|
||||
Duration lastDuration = Days
|
||||
.daysBetween(
|
||||
task.getBeginDateAsLocalDate(),
|
||||
LocalDate.fromDateFields(lastTimesheetDate)
|
||||
.plusDays(1)).toStandardDuration();
|
||||
int pixelsLast = getMapper().toPixels(lastDuration);
|
||||
String positionLast = pixelsLast + "px";
|
||||
|
||||
response(null, new AuInvoke(this, "showTimsheetDateMarks",
|
||||
positionFirst, positionLast));
|
||||
} else {
|
||||
response(null, new AuInvoke(this, "hideTimsheetDateMarks"));
|
||||
}
|
||||
|
||||
} else {
|
||||
response(null, new AuInvoke(this, "resizeCompletionAdvance", "0px"));
|
||||
response(null, new AuInvoke(this, "hideTimsheetDateMarks"));
|
||||
}
|
||||
}
|
||||
|
||||
public void updateCompletionMoneyCostBar() {
|
||||
if (task.isShowingMoneyCostBar()) {
|
||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||
String widthMoneyCostBar = pixelsFromStartUntil(startPixels,
|
||||
this.task.getMoneyCostBarEndDate()) + "px";
|
||||
int endPixels = this.task.getEndDate().toPixels(getMapper());
|
||||
int widthPixels = (int) ((endPixels - startPixels) * this.task
|
||||
.getMoneyCostBarPercentage().doubleValue());
|
||||
String widthMoneyCostBar = widthPixels + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletionMoneyCostBar",
|
||||
widthMoneyCostBar));
|
||||
} else {
|
||||
|
|
@ -539,7 +573,7 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
if (task.isShowingAdvances()) {
|
||||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||
String widthAdvancePercentage = pixelsFromStartUntil(startPixels,
|
||||
this.task.getAdvanceEndDate()) + "px";
|
||||
this.task.getAdvanceBarEndDate()) + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletion2Advance",
|
||||
widthAdvancePercentage));
|
||||
} else {
|
||||
|
|
@ -553,7 +587,7 @@ public class TaskComponent extends Div implements AfterCompose {
|
|||
int startPixels = this.task.getBeginDate().toPixels(getMapper());
|
||||
|
||||
String widthAdvancePercentage = pixelsFromStartUntil(startPixels,
|
||||
this.task.getAdvanceEndDate(progressType)) + "px";
|
||||
this.task.getAdvanceBarEndDate(progressType)) + "px";
|
||||
response(null, new AuInvoke(this, "resizeCompletion2Advance",
|
||||
widthAdvancePercentage));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,11 @@ public class PlannerConfiguration<T> implements IDisabilityConfiguration {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlannerCommand() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class NullCommandOnTask<T> implements ICommandOnTask<T> {
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties
|
|||
}
|
||||
|
||||
@Override
|
||||
public GanttDate getHoursAdvanceEndDate() {
|
||||
public GanttDate getHoursAdvanceBarEndDate() {
|
||||
return GanttDate.createFrom(new Date(hoursAdvanceEndDate));
|
||||
}
|
||||
|
||||
|
|
@ -184,13 +184,18 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties
|
|||
}
|
||||
|
||||
@Override
|
||||
public GanttDate getAdvanceEndDate() {
|
||||
public BigDecimal getMoneyCostBarPercentage() {
|
||||
return moneyCostBarPercentage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GanttDate getAdvanceBarEndDate() {
|
||||
return advanceEndDate != null ? GanttDate.createFrom(new Date(
|
||||
advanceEndDate.getTime()))
|
||||
: null;
|
||||
}
|
||||
@Override
|
||||
public BigDecimal getHoursAdvancePercentage() {
|
||||
public BigDecimal getHoursAdvanceBarPercentage() {
|
||||
return hoursAdvancePercentage;
|
||||
}
|
||||
|
||||
|
|
@ -279,7 +284,7 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties
|
|||
}
|
||||
|
||||
@Override
|
||||
public GanttDate getAdvanceEndDate(String progressType) {
|
||||
public GanttDate getAdvanceBarEndDate(String progressType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -303,4 +308,29 @@ public class DefaultFundamentalProperties implements ITaskFundamentalProperties
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatedFromTimesheets() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getFirstTimesheetDate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getLastTimesheetDate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProjectCode() {
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,13 +75,15 @@ public interface ITaskFundamentalProperties {
|
|||
|
||||
public void setNotes(String notes);
|
||||
|
||||
public GanttDate getHoursAdvanceEndDate();
|
||||
public GanttDate getHoursAdvanceBarEndDate();
|
||||
|
||||
public GanttDate getMoneyCostBarEndDate();
|
||||
|
||||
public GanttDate getAdvanceEndDate();
|
||||
BigDecimal getMoneyCostBarPercentage();
|
||||
|
||||
public BigDecimal getHoursAdvancePercentage();
|
||||
public GanttDate getAdvanceBarEndDate();
|
||||
|
||||
public BigDecimal getHoursAdvanceBarPercentage();
|
||||
|
||||
public BigDecimal getAdvancePercentage();
|
||||
|
||||
|
|
@ -113,7 +115,7 @@ public interface ITaskFundamentalProperties {
|
|||
|
||||
public List<Constraint<GanttDate>> getCurrentLengthConstraint();
|
||||
|
||||
public GanttDate getAdvanceEndDate(String progressType);
|
||||
public GanttDate getAdvanceBarEndDate(String progressType);
|
||||
|
||||
String updateTooltipText(String progressType);
|
||||
|
||||
|
|
@ -123,4 +125,14 @@ public interface ITaskFundamentalProperties {
|
|||
|
||||
public boolean isRoot();
|
||||
|
||||
boolean isUpdatedFromTimesheets();
|
||||
|
||||
Date getFirstTimesheetDate();
|
||||
|
||||
Date getLastTimesheetDate();
|
||||
|
||||
public String getCode();
|
||||
|
||||
public String getProjectCode();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -384,8 +384,8 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getHoursAdvancePercentage() {
|
||||
return fundamentalProperties.getHoursAdvancePercentage();
|
||||
public BigDecimal getHoursAdvanceBarPercentage() {
|
||||
return fundamentalProperties.getHoursAdvanceBarPercentage();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -394,8 +394,8 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
}
|
||||
|
||||
@Override
|
||||
public GanttDate getHoursAdvanceEndDate() {
|
||||
return fundamentalProperties.getHoursAdvanceEndDate();
|
||||
public GanttDate getHoursAdvanceBarEndDate() {
|
||||
return fundamentalProperties.getHoursAdvanceBarEndDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -404,12 +404,17 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
}
|
||||
|
||||
@Override
|
||||
public GanttDate getAdvanceEndDate() {
|
||||
return fundamentalProperties.getAdvanceEndDate();
|
||||
public BigDecimal getMoneyCostBarPercentage() {
|
||||
return fundamentalProperties.getMoneyCostBarPercentage();
|
||||
}
|
||||
|
||||
public GanttDate getAdvanceEndDate(String progressType) {
|
||||
return fundamentalProperties.getAdvanceEndDate(progressType);
|
||||
@Override
|
||||
public GanttDate getAdvanceBarEndDate() {
|
||||
return fundamentalProperties.getAdvanceBarEndDate();
|
||||
}
|
||||
|
||||
public GanttDate getAdvanceBarEndDate(String progressType) {
|
||||
return fundamentalProperties.getAdvanceBarEndDate(progressType);
|
||||
}
|
||||
|
||||
public String getTooltipText() {
|
||||
|
|
@ -543,4 +548,33 @@ public abstract class Task implements ITaskFundamentalProperties {
|
|||
getBeginDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatedFromTimesheets() {
|
||||
return fundamentalProperties.isUpdatedFromTimesheets();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getFirstTimesheetDate() {
|
||||
return fundamentalProperties.getFirstTimesheetDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getLastTimesheetDate() {
|
||||
return fundamentalProperties.getLastTimesheetDate();
|
||||
}
|
||||
|
||||
public void firePropertyChangeForTaskDates() {
|
||||
fundamentalPropertiesListeners.firePropertyChange("beginDate", null,
|
||||
getBeginDate());
|
||||
fundamentalPropertiesListeners.firePropertyChange("endDate", null,
|
||||
getEndDate());
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return fundamentalProperties.getCode();
|
||||
}
|
||||
|
||||
public String getProjectCode() {
|
||||
return fundamentalProperties.getProjectCode();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public class TaskLeaf extends Task {
|
|||
@Override
|
||||
public boolean canBeExplicitlyMoved() {
|
||||
return !(isSubcontracted() || isLimitingAndHasDayAssignments()
|
||||
|| hasConsolidations() || isManualAnyAllocation());
|
||||
|| hasConsolidations() || isManualAnyAllocation() || isUpdatedFromTimesheets());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,4 +39,10 @@ public interface ICommand<T> {
|
|||
|
||||
boolean isDisabled();
|
||||
|
||||
/**
|
||||
* Describes if a command is for the planner toolbar. Otherwise it'll be
|
||||
* inserted in the common toolbar.
|
||||
*/
|
||||
boolean isPlannerCommand();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,6 +266,9 @@ public class LongOperationFeedback {
|
|||
if (current.isEnd()) {
|
||||
return;
|
||||
}
|
||||
if (!desktop.isAlive() || !desktop.isServerPushEnabled()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Executions.activate(desktop);
|
||||
} catch (Exception e) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ import java.util.ListIterator;
|
|||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.zkoss.zul.AbstractTreeModel;
|
||||
import org.zkoss.zul.event.TreeDataEvent;
|
||||
|
||||
|
|
@ -39,6 +41,8 @@ import org.zkoss.zul.event.TreeDataEvent;
|
|||
*/
|
||||
public class MutableTreeModel<T> extends AbstractTreeModel {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(MutableTreeModel.class);
|
||||
|
||||
public interface IChildrenExtractor<T> {
|
||||
|
||||
public List<? extends T> getChildren(T parent);
|
||||
|
|
@ -354,11 +358,15 @@ public class MutableTreeModel<T> extends AbstractTreeModel {
|
|||
|
||||
public List<T> getParents(T node) {
|
||||
ArrayList<T> result = new ArrayList<T>();
|
||||
try {
|
||||
T current = node;
|
||||
while (!isRoot(current)) {
|
||||
current = getParent(current);
|
||||
result.add(current);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Trying to get the parent of a removed node", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
249
ganttzk/src/main/resources/i18n/ca.po
Normal file
249
ganttzk/src/main/resources/i18n/ca.po
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
# LibrePlan - GanttZK module.
|
||||
# Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
# Desenvolvemento Tecnolóxico de Galicia
|
||||
# Copyright (C) 2010-2012 Igalia, S.L.
|
||||
# This file is distributed under the same license as the LibrePlan package.
|
||||
#
|
||||
# Translators:
|
||||
# Daniel Díaz Sañudo <gurnan@gmail.com>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libreplan-1.3.1\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
|
||||
"POT-Creation-Date: 2012-10-02 12:44+0200\n"
|
||||
"PO-Revision-Date: 2012-09-20 07:32+0000\n"
|
||||
"Last-Translator: Daniel Díaz Sañudo <gurnan@gmail.com>\n"
|
||||
"Language-Team: Català\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ca\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
|
||||
msgid "Erase"
|
||||
msgstr "Esborrar"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
|
||||
msgid "Add Dependency"
|
||||
msgstr "Afegir dependències"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "Worker"
|
||||
msgstr "Treballador"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
|
||||
msgid "Show money cost bar"
|
||||
msgstr "Mostar la barra del cost econòmic"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
|
||||
msgid "Start"
|
||||
msgstr "Inici"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
|
||||
msgid "Show reported hours"
|
||||
msgstr "Mostrar hores informades"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:85
|
||||
msgid "Show/Hide reported hours"
|
||||
msgstr "Mostrar/Ocultar hores informades"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:35
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:49
|
||||
msgid "Zoom"
|
||||
msgstr "Zoom"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:67
|
||||
msgid "The specified dependency is not allowed"
|
||||
msgstr "La dependència especificada no està permesa"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:255
|
||||
msgid "Set End-End"
|
||||
msgstr "Ajust d'extrem a extrem"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:78
|
||||
msgid "Show/Hide progress"
|
||||
msgstr "Mostrar/Ocultar progrés"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "Task"
|
||||
msgstr "Tasca"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:199
|
||||
msgid "available effort: {0}, assigned effort: {1}"
|
||||
msgstr "esforç disponible: {0}, esforç assignat: {1}"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:64
|
||||
msgid "Criterion"
|
||||
msgstr "Criteri"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
|
||||
msgid "Hide money cost bar"
|
||||
msgstr "Ocultar barra de cost econòmic"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
|
||||
msgid "Print"
|
||||
msgstr "Imprimir"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:71
|
||||
msgid "Week"
|
||||
msgstr "Setmana"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:501
|
||||
msgid "filtering by name"
|
||||
msgstr "Filtrar per nom"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadLeftPane.java:111
|
||||
msgid "See scheduling"
|
||||
msgstr "Mirar programació"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:30
|
||||
msgid "End"
|
||||
msgstr "Final"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:89
|
||||
msgid "Resources"
|
||||
msgstr "Recursos"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/TimeTracker.java:243
|
||||
msgid "changing zoom"
|
||||
msgstr "canviar zoom"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
|
||||
msgid "Show/Hide money cost bar"
|
||||
msgstr "Mostar/Ocultar barra de cost econòmic"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:47
|
||||
msgid "Group by"
|
||||
msgstr "Agrupar per"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:90
|
||||
msgid "Generic allocation criteria"
|
||||
msgstr "Criteris genèrics d'assignació"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
|
||||
msgid "Quarter"
|
||||
msgstr "Quart"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:43
|
||||
msgid "Page"
|
||||
msgstr "Pàgina"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "None"
|
||||
msgstr "Res"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:71
|
||||
msgid "Flatten/Unflatten tree"
|
||||
msgstr "Estendre/Plegar arbre"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "Project"
|
||||
msgstr "Projecte"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:67
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:28
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
|
||||
msgid "Show progress"
|
||||
msgstr "Mostrar progrés"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:67
|
||||
msgid "Expand/Collapse all"
|
||||
msgstr "Expandir/Plegar tot"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:58
|
||||
msgid "Show/Hide critical path"
|
||||
msgstr "Mostrar/Ocultar \"path\" crític"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
|
||||
msgid "Year"
|
||||
msgstr "Any"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
|
||||
msgid "showing criteria"
|
||||
msgstr "Mostar criteris"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
|
||||
msgid "Month"
|
||||
msgstr "Mes"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:64
|
||||
msgid "Show/Hide resources"
|
||||
msgstr "Mostar/Ocultar recursos"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:247
|
||||
msgid "Set End-Start"
|
||||
msgstr "Ajust fi - Inici"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
|
||||
msgid "decreasing zoom"
|
||||
msgstr "decréixer zoom"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
|
||||
msgid "Hide critical path"
|
||||
msgstr "Ocultar \"path\" crític"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:84
|
||||
msgid "Day"
|
||||
msgstr "Dia"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
|
||||
msgid "Hide reported hours"
|
||||
msgstr "Ocultar informe d'hores"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:193
|
||||
msgid "Load: {0}%"
|
||||
msgstr "Càrrega: {0}%"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:147
|
||||
msgid "showing resources"
|
||||
msgstr "mostrant recursos"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:61
|
||||
msgid "Show/Hide labels"
|
||||
msgstr "Mostrar/Ocultar Etiquetes"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:97
|
||||
msgid "Hour"
|
||||
msgstr "Hores"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
|
||||
msgid "Graphics"
|
||||
msgstr "Gràfics"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:251
|
||||
msgid "Set Start-Start"
|
||||
msgstr "Ajust d'inici a inici"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:152
|
||||
msgid "See resource allocation"
|
||||
msgstr "Mirar assignació de recursos"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
|
||||
msgid "increasing zoom"
|
||||
msgstr "acréixer zoom"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:467
|
||||
msgid "Show all elements"
|
||||
msgstr "Mostar tots els elements"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:466
|
||||
msgid "All"
|
||||
msgstr "Tot"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:38
|
||||
msgid "Refresh"
|
||||
msgstr "Refrescar"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
|
||||
msgid "Show critical path"
|
||||
msgstr "Mostrar camí crític"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
|
||||
msgid "Hide progress"
|
||||
msgstr "Ocultar progrés"
|
||||
|
|
@ -8,17 +8,17 @@
|
|||
# Giuseppe Zizza <gzizza@gmail.com>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libreplan-1.2.3\n"
|
||||
"Project-Id-Version: libreplan-1.3.1\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 08:05+0000\n"
|
||||
"POT-Creation-Date: 2012-10-02 12:44+0200\n"
|
||||
"PO-Revision-Date: 2012-10-02 10:16+0000\n"
|
||||
"Last-Translator: Giuseppe Zizza <gzizza@gmail.com>\n"
|
||||
"Language-Team: Italiano\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: it\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
|
||||
|
|
@ -45,10 +45,6 @@ msgstr "Inizio"
|
|||
msgid "Show reported hours"
|
||||
msgstr "Mostra le ore riportate"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:90
|
||||
msgid "by criteria"
|
||||
msgstr "per criterio"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:85
|
||||
msgid "Show/Hide reported hours"
|
||||
msgstr "Mostra/Nascondi le ore riportate"
|
||||
|
|
@ -58,10 +54,6 @@ msgstr "Mostra/Nascondi le ore riportate"
|
|||
msgid "Zoom"
|
||||
msgstr "Visualizza"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/TabsRegistry.java:121
|
||||
msgid "Limiting resources"
|
||||
msgstr "Risorse limitanti"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:67
|
||||
msgid "The specified dependency is not allowed"
|
||||
msgstr "La dipendenza specifica non è permessa"
|
||||
|
|
@ -78,10 +70,6 @@ msgstr "Mostra/Nascondi progresso"
|
|||
msgid "Task"
|
||||
msgstr "Compito"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:89
|
||||
msgid "by resources"
|
||||
msgstr "per risorsa"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:199
|
||||
msgid "available effort: {0}, assigned effort: {1}"
|
||||
msgstr "Forza disponbile: {0}, forza assegnata: {1}"
|
||||
|
|
@ -110,14 +98,14 @@ msgstr "filtra per nome"
|
|||
msgid "See scheduling"
|
||||
msgstr "Mostra pianificazione"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:43
|
||||
msgid "Show"
|
||||
msgstr "Mostra"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:30
|
||||
msgid "End"
|
||||
msgstr "Fine"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:89
|
||||
msgid "Resources"
|
||||
msgstr "Risorse"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/TimeTracker.java:243
|
||||
msgid "changing zoom"
|
||||
msgstr "Cambio vista"
|
||||
|
|
@ -126,10 +114,22 @@ msgstr "Cambio vista"
|
|||
msgid "Show/Hide money cost bar"
|
||||
msgstr "Mostra/Nascondi la barra dei costi"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:47
|
||||
msgid "Group by"
|
||||
msgstr "Raggruppa per"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:90
|
||||
msgid "Generic allocation criteria"
|
||||
msgstr "Criterio generico d'allocazione"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
|
||||
msgid "Quarter"
|
||||
msgstr "Quarto"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:43
|
||||
msgid "Page"
|
||||
msgstr "Pagina"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "None"
|
||||
msgstr "Nessuno"
|
||||
|
|
@ -147,10 +147,6 @@ msgstr "Progetto"
|
|||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:50
|
||||
msgid "Name filter"
|
||||
msgstr "Nome filtro"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
|
||||
msgid "Show progress"
|
||||
msgstr "Mostra progresso"
|
||||
|
|
@ -163,14 +159,14 @@ msgstr "Espandi/Riduci tutti"
|
|||
msgid "Show/Hide critical path"
|
||||
msgstr "Mostra/Nascondi percorso critico"
|
||||
|
||||
#: 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/resourceload/ResourcesLoadPanel.java:150
|
||||
msgid "showing criteria"
|
||||
msgstr "Mostro i criteri"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
|
||||
msgid "Month"
|
||||
msgstr "Mese"
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libreplan-1.3.0\n"
|
||||
"Project-Id-Version: libreplan-1.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-07-05 08:07+0200\n"
|
||||
"POT-Creation-Date: 2012-12-07 13:59+0100\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,7 +31,7 @@ msgstr ""
|
|||
msgid "Worker"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:682
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:689
|
||||
msgid "Show money cost bar"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ msgstr ""
|
|||
msgid "Start"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:661
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
|
||||
msgid "Show reported hours"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ msgstr ""
|
|||
msgid "Criterion"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:688
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:695
|
||||
msgid "Hide money cost bar"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ msgstr ""
|
|||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:641
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:645
|
||||
msgid "Show progress"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -177,11 +177,11 @@ msgstr ""
|
|||
msgid "Set End-Start"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:309
|
||||
msgid "decreasing zoom"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:622
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:625
|
||||
msgid "Hide critical path"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ msgstr ""
|
|||
msgid "Day"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:675
|
||||
msgid "Hide reported hours"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ msgstr ""
|
|||
msgid "See resource allocation"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:291
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:292
|
||||
msgid "increasing zoom"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -238,10 +238,10 @@ msgstr ""
|
|||
msgid "Refresh"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:617
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620
|
||||
msgid "Show critical path"
|
||||
msgstr ""
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:646
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:653
|
||||
msgid "Hide progress"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
# Jeroen Baten <jeroen@jeroenbaten.nl>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libreplan-1.3.0\n"
|
||||
"Project-Id-Version: libreplan-1.3.1\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
|
||||
"POT-Creation-Date: 2012-07-05 08:07+0200\n"
|
||||
"POT-Creation-Date: 2012-10-02 12:44+0200\n"
|
||||
"PO-Revision-Date: 2012-07-06 09:59+0000\n"
|
||||
"Last-Translator: Jeroen Baten <jeroen@jeroenbaten.nl>\n"
|
||||
"Language-Team: Nederlands\n"
|
||||
|
|
@ -18,7 +18,7 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: nl\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@
|
|||
# Translators:
|
||||
# Helena Grosso <lenagrosso@gmail.com>, 2011.
|
||||
# Joaquim Rocha <jrocha@igalia.com>, 2012.
|
||||
# Thiago Cangussu <cangussu.br@gmail.com>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1.2.1\n"
|
||||
"Project-Id-Version: 1.3.2\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-17 18:45+0000\n"
|
||||
"Last-Translator: Joaquim Rocha <jrocha@igalia.com>\n"
|
||||
"POT-Creation-Date: 2012-11-22 13:41+0100\n"
|
||||
"PO-Revision-Date: 2012-11-06 15:38+0000\n"
|
||||
"Last-Translator: Thiago Cangussu <cangussu.br@gmail.com>\n"
|
||||
"Language-Team: Português\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
|
@ -21,12 +22,12 @@ msgstr ""
|
|||
"Language: pt\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 "Apagar"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:300
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
|
||||
msgid "Add Dependency"
|
||||
msgstr "Adicionar Dependência"
|
||||
|
||||
|
|
@ -34,18 +35,18 @@ msgstr "Adicionar Dependência"
|
|||
msgid "Worker"
|
||||
msgstr "Trabalhador"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:684
|
||||
msgid "Show money cost bar"
|
||||
msgstr "Exibir a barra de custo em dinheiro"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
|
||||
msgid "Start"
|
||||
msgstr "Início"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:635
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:663
|
||||
msgid "Show reported hours"
|
||||
msgstr "Mostrar horas registadas"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:90
|
||||
msgid "by criteria"
|
||||
msgstr "por critérios"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:85
|
||||
msgid "Show/Hide reported hours"
|
||||
msgstr "Mostrar/Ocultar horas registadas"
|
||||
|
|
@ -55,15 +56,11 @@ msgstr "Mostrar/Ocultar horas registadas"
|
|||
msgid "Zoom"
|
||||
msgstr "Zoom"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/TabsRegistry.java:121
|
||||
msgid "Limiting resources"
|
||||
msgstr "Recursos restringentes"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:67
|
||||
msgid "The specified dependency is not allowed"
|
||||
msgstr "A dependência especificada não 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 Fim-Fim"
|
||||
|
||||
|
|
@ -75,10 +72,6 @@ msgstr "Mostrar/Ocultar progresso"
|
|||
msgid "Task"
|
||||
msgstr "Tarefa"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:89
|
||||
msgid "by resources"
|
||||
msgstr "por recursos"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:199
|
||||
msgid "available effort: {0}, assigned effort: {1}"
|
||||
msgstr "esforço disponível: {0}, esforço atribuído: {1}"
|
||||
|
|
@ -87,6 +80,10 @@ msgstr "esforço disponível: {0}, esforço atribuído: {1}"
|
|||
msgid "Criterion"
|
||||
msgstr "Critério"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:690
|
||||
msgid "Hide money cost bar"
|
||||
msgstr "Ocultar a barra de custo em dinheiro"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
|
||||
msgid "Print"
|
||||
msgstr "Imprimir"
|
||||
|
|
@ -103,22 +100,38 @@ msgstr "a filtrar por nome"
|
|||
msgid "See scheduling"
|
||||
msgstr "Ver planificação"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:43
|
||||
msgid "Show"
|
||||
msgstr "Mostrar"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:30
|
||||
msgid "End"
|
||||
msgstr "Fim"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:89
|
||||
msgid "Resources"
|
||||
msgstr "Recursos"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/TimeTracker.java:243
|
||||
msgid "changing zoom"
|
||||
msgstr "a alterar o zoom"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
|
||||
msgid "Show/Hide money cost bar"
|
||||
msgstr "Exibir/Ocultar a barra de custo em dinheiro"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:47
|
||||
msgid "Group by"
|
||||
msgstr "Agrupado por"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:90
|
||||
msgid "Generic allocation criteria"
|
||||
msgstr "Critério geral de alocação"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
|
||||
msgid "Quarter"
|
||||
msgstr "Trimestre"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:43
|
||||
msgid "Page"
|
||||
msgstr "Página"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "None"
|
||||
msgstr "Nenhum"
|
||||
|
|
@ -136,11 +149,7 @@ msgstr "Projeto"
|
|||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:50
|
||||
msgid "Name filter"
|
||||
msgstr "Filtro de nomes"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:615
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:643
|
||||
msgid "Show progress"
|
||||
msgstr "Mostrar progresso"
|
||||
|
||||
|
|
@ -168,15 +177,15 @@ msgstr "Mês"
|
|||
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 Fim-Início"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:297
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:308
|
||||
msgid "decreasing zoom"
|
||||
msgstr "a reduzir o zoom"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:596
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:624
|
||||
msgid "Hide critical path"
|
||||
msgstr "Ocultar caminho crítico"
|
||||
|
||||
|
|
@ -184,7 +193,7 @@ msgstr "Ocultar caminho crítico"
|
|||
msgid "Day"
|
||||
msgstr "Dia"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:642
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:670
|
||||
msgid "Hide reported hours"
|
||||
msgstr "Ocultar horas registadas"
|
||||
|
||||
|
|
@ -205,11 +214,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áficos"
|
||||
|
||||
#: 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 Início-Início"
|
||||
|
||||
|
|
@ -217,7 +226,7 @@ msgstr "Definir Início-Início"
|
|||
msgid "See resource allocation"
|
||||
msgstr "Ver atribuição 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 "a aumentar o zoom"
|
||||
|
||||
|
|
@ -233,10 +242,10 @@ msgstr "Todos"
|
|||
msgid "Refresh"
|
||||
msgstr "Atualizar"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:591
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:619
|
||||
msgid "Show critical path"
|
||||
msgstr "Mostrar caminho crítico"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:648
|
||||
msgid "Hide progress"
|
||||
msgstr "Ocultar progresso"
|
||||
|
|
|
|||
249
ganttzk/src/main/resources/i18n/zh.po
Normal file
249
ganttzk/src/main/resources/i18n/zh.po
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
# LibrePlan - GanttZK module.
|
||||
# Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
|
||||
# Desenvolvemento Tecnolóxico de Galicia
|
||||
# Copyright (C) 2010-2012 Igalia, S.L.
|
||||
# This file is distributed under the same license as the LibrePlan package.
|
||||
#
|
||||
# Translators:
|
||||
# Swanson Chan <lacidophilin@yahoo.com>, 2013.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libreplan-1.3.3\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.libreplan.org/\n"
|
||||
"POT-Creation-Date: 2012-12-07 13:59+0100\n"
|
||||
"PO-Revision-Date: 2013-03-09 07:49+0000\n"
|
||||
"Last-Translator: Swanson Chan <lacidophilin@yahoo.com>\n"
|
||||
"Language-Team: 中文\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: zh\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:216
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:235
|
||||
msgid "Erase"
|
||||
msgstr "抹去"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/TaskList.java:299
|
||||
msgid "Add Dependency"
|
||||
msgstr "添加依赖关系"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "Worker"
|
||||
msgstr "工人"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:689
|
||||
msgid "Show money cost bar"
|
||||
msgstr "显示资金成本栏"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:29
|
||||
msgid "Start"
|
||||
msgstr "开始"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:668
|
||||
msgid "Show reported hours"
|
||||
msgstr "节目报道小时"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:85
|
||||
msgid "Show/Hide reported hours"
|
||||
msgstr "报告显示/隐藏小时"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:35
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:49
|
||||
msgid "Zoom"
|
||||
msgstr "放大"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:67
|
||||
msgid "The specified dependency is not allowed"
|
||||
msgstr "不允许指定的依赖"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:255
|
||||
msgid "Set End-End"
|
||||
msgstr "设置端到端"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:78
|
||||
msgid "Show/Hide progress"
|
||||
msgstr "显示/隐藏进度"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "Task"
|
||||
msgstr "任务"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:199
|
||||
msgid "available effort: {0}, assigned effort: {1}"
|
||||
msgstr "可用的努力:{0},分配的努力:{1}"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:64
|
||||
msgid "Criterion"
|
||||
msgstr "标准"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:695
|
||||
msgid "Hide money cost bar"
|
||||
msgstr "隐藏资金成本吧"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:44
|
||||
msgid "Print"
|
||||
msgstr "打印"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:71
|
||||
msgid "Week"
|
||||
msgstr "周"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:501
|
||||
msgid "filtering by name"
|
||||
msgstr "过滤名称"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadLeftPane.java:111
|
||||
msgid "See scheduling"
|
||||
msgstr "见调度"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:30
|
||||
msgid "End"
|
||||
msgstr "结束"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:89
|
||||
msgid "Resources"
|
||||
msgstr "资源"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/TimeTracker.java:243
|
||||
msgid "changing zoom"
|
||||
msgstr "改变变焦"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:91
|
||||
msgid "Show/Hide money cost bar"
|
||||
msgstr "显示/隐藏资金成本吧"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:47
|
||||
msgid "Group by"
|
||||
msgstr "集团通过"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:90
|
||||
msgid "Generic allocation criteria"
|
||||
msgstr "通用的分配标准"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:45
|
||||
msgid "Quarter"
|
||||
msgstr "季"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:43
|
||||
msgid "Page"
|
||||
msgstr "页"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "None"
|
||||
msgstr "无"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:71
|
||||
msgid "Flatten/Unflatten tree"
|
||||
msgstr "拼合/ Unflatten树的"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/data/resourceload/TimeLineRole.java:58
|
||||
msgid "Project"
|
||||
msgstr "项目"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:67
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/leftTasksTree.zul:28
|
||||
msgid "Name"
|
||||
msgstr "名称"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:645
|
||||
msgid "Show progress"
|
||||
msgstr "显示进度"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:67
|
||||
msgid "Expand/Collapse all"
|
||||
msgstr "展开/收起所有"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:58
|
||||
msgid "Show/Hide critical path"
|
||||
msgstr "显示/隐藏关键路径"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:32
|
||||
msgid "Year"
|
||||
msgstr "年"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:150
|
||||
msgid "showing criteria"
|
||||
msgstr "显示标准"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:58
|
||||
msgid "Month"
|
||||
msgstr "月"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:64
|
||||
msgid "Show/Hide resources"
|
||||
msgstr "显示/隐藏资源"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:247
|
||||
msgid "Set End-Start"
|
||||
msgstr "设置结束开始"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:309
|
||||
msgid "decreasing zoom"
|
||||
msgstr "减少变焦"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:625
|
||||
msgid "Hide critical path"
|
||||
msgstr "隐藏关键路径"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:84
|
||||
msgid "Day"
|
||||
msgstr "日"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:675
|
||||
msgid "Hide reported hours"
|
||||
msgstr "隐藏报道小时"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:193
|
||||
msgid "Load: {0}%"
|
||||
msgstr "负载:{0}%"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:147
|
||||
msgid "showing resources"
|
||||
msgstr "显示资源"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:61
|
||||
msgid "Show/Hide labels"
|
||||
msgstr "显示/隐藏标签"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/timetracker/zoom/ZoomLevel.java:97
|
||||
msgid "Hour"
|
||||
msgstr "小时"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/resourcesLoadLayout.zul:90
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:120
|
||||
msgid "Graphics"
|
||||
msgstr "图像"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/DependencyList.java:251
|
||||
msgid "Set Start-Start"
|
||||
msgstr "设置开始启动"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourceLoadComponent.java:152
|
||||
msgid "See resource allocation"
|
||||
msgstr "资源分配"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:292
|
||||
msgid "increasing zoom"
|
||||
msgstr "增加变焦"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:467
|
||||
msgid "Show all elements"
|
||||
msgstr "显示所有元素"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/resourceload/ResourcesLoadPanel.java:466
|
||||
msgid "All"
|
||||
msgstr "所有"
|
||||
|
||||
#: ganttzk/src/main/resources/web/ganttz/zul/plannerLayout.zul:38
|
||||
msgid "Refresh"
|
||||
msgstr "刷新"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:620
|
||||
msgid "Show critical path"
|
||||
msgstr "显示关键路径"
|
||||
|
||||
#: ganttzk/src/main/java/org/zkoss/ganttz/Planner.java:653
|
||||
msgid "Hide progress"
|
||||
msgstr "隐藏进度"
|
||||
|
|
@ -4,6 +4,12 @@
|
|||
<addon-name>ganttz</addon-name>
|
||||
<language-name>xul/html</language-name>
|
||||
|
||||
<!-- When the version is changed, the browser will reload the
|
||||
JavaScript modules. -->
|
||||
<javascript-module name="ganttz" version="1.3.3" />
|
||||
<javascript-module name="ganttz.resourceload" version="1.3.3" />
|
||||
<javascript-module name="common" version="1.3.3" />
|
||||
|
||||
<extension>zul</extension>
|
||||
<extension>xul</extension>
|
||||
|
||||
|
|
|
|||
|
|
@ -221,6 +221,18 @@ ganttz.TaskComponent = zk.$extends(zul.Widget, {
|
|||
resizeCompletionAdvance : function(width){
|
||||
jq('#' + this.uuid + ' .completion:first').css('width', width);
|
||||
},
|
||||
showTimsheetDateMarks : function(positionFirst, postionLast) {
|
||||
var firstTimesheetDateMark = jq('#' + this.uuid + ' .first-timesheet-date');
|
||||
var lastTimesheetDateMark = jq('#' + this.uuid + ' .last-timesheet-date');
|
||||
firstTimesheetDateMark.css('left', positionFirst);
|
||||
lastTimesheetDateMark.css('left', postionLast);
|
||||
firstTimesheetDateMark.show();
|
||||
lastTimesheetDateMark.show();
|
||||
},
|
||||
hideTimsheetDateMarks : function() {
|
||||
jq('#' + this.uuid + ' .first-timesheet-date').hide();
|
||||
jq('#' + this.uuid + ' .last-timesheet-date').hide();
|
||||
},
|
||||
resizeCompletion2Advance : function(width){
|
||||
jq('#' + this.uuid + ' .completion2:first').css('width', width);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ function(out){
|
|||
out.push('<div class="completionMoneyCostBar"></div>');
|
||||
out.push('<div class="completion"></div>');
|
||||
out.push('<div class="completion2"></div>');
|
||||
out.push('<div class="timesheet-date-mark first-timesheet-date"></div>');
|
||||
out.push('<div class="timesheet-date-mark last-timesheet-date"></div>');
|
||||
|
||||
out.push('<div id="tasktooltip', this.uuid,'" class="task_tooltip">',
|
||||
this.getTooltipText(),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.libreplan</groupId>
|
||||
<artifactId>libreplan</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.3</version>
|
||||
</parent>
|
||||
<artifactId>libreplan-business</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -36,16 +36,26 @@ public enum PredefinedAdvancedTypes {
|
|||
UNITS("units", new BigDecimal(Integer.MAX_VALUE),
|
||||
new BigDecimal(1), false, false),
|
||||
SUBCONTRACTOR("subcontractor",
|
||||
new BigDecimal(100), new BigDecimal(0.01), true, false);
|
||||
new BigDecimal(100), new BigDecimal(0.01), true, false),
|
||||
TIMESHEETS("timesheets",
|
||||
new BigDecimal(100), new BigDecimal(0.01), true, false, true);
|
||||
|
||||
|
||||
private PredefinedAdvancedTypes(String name, BigDecimal defaultMaxValue,
|
||||
BigDecimal precision, boolean percentage, boolean qualityForm) {
|
||||
this(name, defaultMaxValue, precision, percentage, qualityForm, false);
|
||||
}
|
||||
|
||||
private PredefinedAdvancedTypes(String name, BigDecimal defaultMaxValue,
|
||||
BigDecimal precision, boolean percentage, boolean qualityForm,
|
||||
boolean readOnly) {
|
||||
this.name = name;
|
||||
this.defaultMaxValue = defaultMaxValue.setScale(4,
|
||||
BigDecimal.ROUND_HALF_UP);
|
||||
this.unitPrecision = precision.setScale(4, BigDecimal.ROUND_HALF_UP);
|
||||
this.percentage = percentage;
|
||||
this.qualityForm = qualityForm;
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
|
|
@ -58,9 +68,13 @@ public enum PredefinedAdvancedTypes {
|
|||
|
||||
private final boolean qualityForm;
|
||||
|
||||
private final boolean readOnly;
|
||||
|
||||
public AdvanceType createType() {
|
||||
return AdvanceType.create(name, defaultMaxValue, false, unitPrecision,
|
||||
true, percentage, qualityForm);
|
||||
AdvanceType advanceType = AdvanceType.create(name, defaultMaxValue,
|
||||
false, unitPrecision, true, percentage, qualityForm);
|
||||
advanceType.setReadOnly(readOnly);
|
||||
return advanceType;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ public class AdvanceType extends BaseEntity implements IHumanIdentifiable{
|
|||
|
||||
private IAdvanceTypeDAO avanceTypeDAO = Registry.getAdvanceTypeDao();
|
||||
|
||||
private boolean readOnly = false;
|
||||
|
||||
/**
|
||||
* Constructor for hibernate. Do not use!
|
||||
*/
|
||||
|
|
@ -271,4 +273,12 @@ public class AdvanceType extends BaseEntity implements IHumanIdentifiable{
|
|||
return true;
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,4 +263,9 @@ public class DirectAdvanceAssignment extends AdvanceAssignment {
|
|||
return !nonCalculatedConsolidations.isEmpty();
|
||||
}
|
||||
|
||||
public void resetAdvanceMeasurements(AdvanceMeasurement advanceMeasurement) {
|
||||
advanceMeasurements.clear();
|
||||
addAdvanceMeasurements(advanceMeasurement);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -878,6 +878,18 @@ public class BaseCalendar extends IntegrationEntity implements ICalendar,
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isActiveBetween(LocalDate startDate, LocalDate endDate) {
|
||||
if (getCalendarAvailabilities().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (CalendarAvailability calendarAvailability : getCalendarAvailabilities()) {
|
||||
if (calendarAvailability.isActiveBetween(startDate, endDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canWorkOn(LocalDate date) {
|
||||
Capacity capacity = findCapacityAt(date);
|
||||
return capacity.allowsWorking();
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.Comparator;
|
|||
import java.util.Date;
|
||||
|
||||
import org.hibernate.validator.NotNull;
|
||||
import org.joda.time.Interval;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.calendars.daos.ICalendarAvailabilityDAO;
|
||||
import org.libreplan.business.common.IntegrationEntity;
|
||||
|
|
@ -126,4 +127,40 @@ public class CalendarAvailability extends IntegrationEntity {
|
|||
return Registry.getCalendarAvailabilityDAO();
|
||||
}
|
||||
|
||||
public boolean isActiveBetween(LocalDate filterStartDate,
|
||||
LocalDate filterEndDate) {
|
||||
if (filterStartDate == null && filterEndDate == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (filterStartDate == null) {
|
||||
if (endDate == null) {
|
||||
return startDate.compareTo(filterEndDate) <= 0;
|
||||
}
|
||||
return startDate.compareTo(filterEndDate) <= 0
|
||||
|| endDate.compareTo(filterEndDate) <= 0;
|
||||
}
|
||||
|
||||
if (filterEndDate == null) {
|
||||
if (endDate == null) {
|
||||
return true;
|
||||
}
|
||||
return startDate.compareTo(filterStartDate) >= 0
|
||||
|| endDate.compareTo(filterStartDate) >= 0;
|
||||
}
|
||||
|
||||
if (endDate == null) {
|
||||
return startDate.compareTo(filterStartDate) <= 0
|
||||
|| startDate.compareTo(filterEndDate) <= 0;
|
||||
}
|
||||
|
||||
Interval filterPeriod = new Interval(
|
||||
filterStartDate.toDateTimeAtStartOfDay(), filterEndDate
|
||||
.plusDays(1).toDateTimeAtStartOfDay());
|
||||
Interval activationPeriod = new Interval(
|
||||
startDate.toDateTimeAtStartOfDay(), endDate.plusDays(1)
|
||||
.toDateTimeAtStartOfDay());
|
||||
return filterPeriod.overlaps(activationPeriod);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public class Capacity {
|
|||
}
|
||||
|
||||
private static Capacity noCapacity() {
|
||||
return Capacity.create(EffortDuration.hours(0))
|
||||
return Capacity.create(EffortDuration.zero())
|
||||
.notOverAssignableWithoutLimit();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,4 +88,5 @@ public class ResourceCalendar extends BaseCalendar {
|
|||
public Boolean isCodeAutogenerated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ public abstract class BaseEntity implements INewObject {
|
|||
}
|
||||
|
||||
protected static <T extends BaseEntity> T create(T baseEntity) {
|
||||
baseEntity.newObject = true;
|
||||
baseEntity.setNewObject(true);
|
||||
return baseEntity;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public abstract class IntegrationEntity extends BaseEntity {
|
|||
T integrationEntity, String code) {
|
||||
|
||||
BaseEntity.create(integrationEntity);
|
||||
integrationEntity.code = code;
|
||||
integrationEntity.setCode(code);
|
||||
|
||||
return integrationEntity;
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ public abstract class IntegrationEntity extends BaseEntity {
|
|||
T integrationEntity) {
|
||||
|
||||
BaseEntity.create(integrationEntity);
|
||||
integrationEntity.code = generateCode();
|
||||
integrationEntity.setCode(generateCode());
|
||||
|
||||
return integrationEntity;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.business.common;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Utilities class. <br />
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
public class Util {
|
||||
|
||||
public static boolean equals(BaseEntity entity1, BaseEntity entity2) {
|
||||
if (entity1 == null || entity2 == null) {
|
||||
return false;
|
||||
}
|
||||
if (entity1.getId() == null || entity2.getId() == null) {
|
||||
return false;
|
||||
}
|
||||
return entity1.getId().equals(entity2.getId());
|
||||
}
|
||||
|
||||
public static boolean contains(Collection<? extends BaseEntity> collection,
|
||||
BaseEntity entity) {
|
||||
for (BaseEntity each : collection) {
|
||||
if (each.getId().equals(entity.getId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -60,6 +60,7 @@ public class IntegrationEntityDAO<E extends IntegrationEntity>
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public E findByCode(String code) throws InstanceNotFoundException {
|
||||
|
||||
if (StringUtils.isBlank(code)) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ package org.libreplan.business.common.entities;
|
|||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.hibernate.validator.AssertTrue;
|
||||
import org.hibernate.validator.Min;
|
||||
import org.hibernate.validator.NotEmpty;
|
||||
import org.hibernate.validator.NotNull;
|
||||
import org.libreplan.business.calendars.entities.BaseCalendar;
|
||||
|
|
@ -103,14 +104,31 @@ public class Configuration extends BaseEntity {
|
|||
|
||||
private Boolean generateCodeForExpenseSheets = true;
|
||||
|
||||
private JiraConfiguration jiraConfiguration;
|
||||
|
||||
/**
|
||||
* Currency code according to ISO-4217 (3 letters)
|
||||
*/
|
||||
private String currencyCode = "EUR";
|
||||
private String currencySymbol = "€";
|
||||
|
||||
private TypeOfWorkHours monthlyTimesheetsTypeOfWorkHours;
|
||||
private TypeOfWorkHours personalTimesheetsTypeOfWorkHours;
|
||||
|
||||
private PersonalTimesheetsPeriodicityEnum personalTimesheetsPeriodicity = PersonalTimesheetsPeriodicityEnum.MONTHLY;
|
||||
|
||||
private Integer secondsPlanningWarning = 30;
|
||||
|
||||
/**
|
||||
* Maximum users configurable directly in database for SaaS products. If
|
||||
* zero it means that there isn't any limitation.
|
||||
*/
|
||||
private Integer maxUsers = 0;
|
||||
|
||||
/**
|
||||
* Maximum resources configurable directly in database for SaaS products. If
|
||||
* zero it means that there isn't any limitation.
|
||||
*/
|
||||
private Integer maxResources = 0;
|
||||
|
||||
public void setDefaultCalendar(BaseCalendar defaultCalendar) {
|
||||
this.defaultCalendar = defaultCalendar;
|
||||
|
|
@ -451,13 +469,48 @@ public class Configuration extends BaseEntity {
|
|||
this.currencySymbol = currencySymbol;
|
||||
}
|
||||
|
||||
public TypeOfWorkHours getMonthlyTimesheetsTypeOfWorkHours() {
|
||||
return monthlyTimesheetsTypeOfWorkHours;
|
||||
public TypeOfWorkHours getPersonalTimesheetsTypeOfWorkHours() {
|
||||
return personalTimesheetsTypeOfWorkHours;
|
||||
}
|
||||
|
||||
public void setMonthlyTimesheetsTypeOfWorkHours(
|
||||
public void setPersonalTimesheetsTypeOfWorkHours(
|
||||
TypeOfWorkHours typeOfWorkHours) {
|
||||
monthlyTimesheetsTypeOfWorkHours = typeOfWorkHours;
|
||||
personalTimesheetsTypeOfWorkHours = typeOfWorkHours;
|
||||
}
|
||||
|
||||
public PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() {
|
||||
return personalTimesheetsPeriodicity;
|
||||
}
|
||||
|
||||
public void setPersonalTimesheetsPeriodicity(
|
||||
PersonalTimesheetsPeriodicityEnum personalTimesheetsPeriodicity) {
|
||||
this.personalTimesheetsPeriodicity = personalTimesheetsPeriodicity;
|
||||
}
|
||||
|
||||
public Integer getMaxUsers() {
|
||||
return maxUsers;
|
||||
}
|
||||
|
||||
public Integer getMaxResources() {
|
||||
return maxResources;
|
||||
}
|
||||
|
||||
@Min(value = 0, message = "seconds planning warning cannot be negative")
|
||||
@NotNull(message = "seconds planning warning not specified")
|
||||
public Integer getSecondsPlanningWarning() {
|
||||
return secondsPlanningWarning;
|
||||
}
|
||||
|
||||
public void setSecondsPlanningWarning(Integer secondsPlanningWarning) {
|
||||
this.secondsPlanningWarning = secondsPlanningWarning;
|
||||
}
|
||||
|
||||
public JiraConfiguration getJiraConfiguration() {
|
||||
return jiraConfiguration;
|
||||
}
|
||||
|
||||
public void setJiraConfiguration(JiraConfiguration jiraConfiguration) {
|
||||
this.jiraConfiguration = jiraConfiguration;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,19 +67,28 @@ public class ConfigurationBootstrap implements IConfigurationBootstrap {
|
|||
public void loadRequiredData() {
|
||||
loadRequiredDataSequences();
|
||||
|
||||
List<Configuration> list = configurationDAO.list(Configuration.class);
|
||||
if (list.isEmpty()) {
|
||||
Configuration configuration = Configuration.create();
|
||||
Configuration configuration = configurationDAO.getConfiguration();
|
||||
if (configuration == null) {
|
||||
configuration = Configuration.create();
|
||||
configuration.setDefaultCalendar(getDefaultCalendar());
|
||||
configuration.setCompanyCode(COMPANY_CODE);
|
||||
}
|
||||
|
||||
LDAPConfiguration ldapConfiguration = configuration
|
||||
.getLdapConfiguration();
|
||||
if (null == configuration.getLdapConfiguration()) {
|
||||
if (ldapConfiguration == null) {
|
||||
ldapConfiguration = LDAPConfiguration.create();
|
||||
}
|
||||
configuration.setLdapConfiguration(ldapConfiguration);
|
||||
configurationDAO.save(configuration);
|
||||
|
||||
JiraConfiguration jiraConfiguration = configuration
|
||||
.getJiraConfiguration();
|
||||
if (jiraConfiguration == null) {
|
||||
jiraConfiguration = JiraConfiguration.create();
|
||||
}
|
||||
configuration.setJiraConfiguration(jiraConfiguration);
|
||||
|
||||
configurationDAO.save(configuration);
|
||||
}
|
||||
|
||||
public void loadRequiredDataSequences() {
|
||||
|
|
|
|||
|
|
@ -32,8 +32,9 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Fills the attribute {@link Configuration#monthlyTimesheetsTypeOfWorkHours}
|
||||
* with a default value.<br />
|
||||
* Fills the attributes {@link Configuration#personalTimesheetsTypeOfWorkHours}
|
||||
* and {@link JiraConfiguration#jiraConnectorTypeOfWorkHours} with a default
|
||||
* values.<br />
|
||||
*
|
||||
* If possible it uses the "Default" {@link TypeOfWorkHours}, but if it doesn't
|
||||
* exist, it uses the first {@link TypeOfWorkHours} found.<br />
|
||||
|
|
@ -47,8 +48,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
@Component
|
||||
@Scope("singleton")
|
||||
@BootstrapOrder(1)
|
||||
public class MonthlyTimesheetsTypeOfWorkHoursBootstrap implements
|
||||
IMonthlyTimesheetsTypeOfWorkHoursBootstrap {
|
||||
public class ConfigurationTypeOfWorkHoursBootstrap implements
|
||||
IConfigurationTypeOfWorkHoursBootstrap {
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
|
@ -73,7 +74,9 @@ public class MonthlyTimesheetsTypeOfWorkHoursBootstrap implements
|
|||
typeOfWorkHours = typeOfWorkHoursDAO.findActive().get(0);
|
||||
}
|
||||
|
||||
configuration.setMonthlyTimesheetsTypeOfWorkHours(typeOfWorkHours);
|
||||
configuration.setPersonalTimesheetsTypeOfWorkHours(typeOfWorkHours);
|
||||
configuration.getJiraConfiguration().setJiraConnectorTypeOfWorkHours(
|
||||
typeOfWorkHours);
|
||||
configurationDAO.save(configuration);
|
||||
}
|
||||
|
||||
|
|
@ -127,8 +127,4 @@ public enum EntityNameEnum {
|
|||
}
|
||||
}
|
||||
|
||||
public String getSequenceLiteral() {
|
||||
return getDescription() + " sequences";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import org.libreplan.business.common.IntegrationEntity;
|
|||
import org.libreplan.business.common.Registry;
|
||||
import org.libreplan.business.common.daos.IEntitySequenceDAO;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.i18n.I18nHelper;
|
||||
|
||||
/**
|
||||
* Sequence for {@link IntegrationEntity} codes.
|
||||
|
|
@ -41,7 +40,7 @@ import org.libreplan.business.i18n.I18nHelper;
|
|||
*/
|
||||
public class EntitySequence extends BaseEntity {
|
||||
|
||||
public static final Integer MIN_NUMBER_OF_DIGITS = 5;
|
||||
public static final Integer MIN_NUMBER_OF_DIGITS = 2;
|
||||
public static final Integer MAX_NUMBER_OF_DIGITS = 9;
|
||||
|
||||
public static final String CODE_SEPARATOR_CHILDREN = "-";
|
||||
|
|
@ -79,7 +78,7 @@ public class EntitySequence extends BaseEntity {
|
|||
|
||||
private Integer lastValue = 0;
|
||||
|
||||
private Integer numberOfDigits = MIN_NUMBER_OF_DIGITS;
|
||||
private Integer numberOfDigits = 4;
|
||||
|
||||
private Boolean active = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ package org.libreplan.business.common.entities;
|
|||
import org.libreplan.business.IDataBootstrap;
|
||||
|
||||
/**
|
||||
* Contract for {@link MonthlyTimesheetsTypeOfWorkHoursBootstrap}.
|
||||
* Contract for {@link ConfigurationTypeOfWorkHoursBootstrap}.
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
public interface IMonthlyTimesheetsTypeOfWorkHoursBootstrap extends
|
||||
public interface IConfigurationTypeOfWorkHoursBootstrap extends
|
||||
IDataBootstrap {
|
||||
|
||||
void loadRequiredData();
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* This file is part of LibrePlan
|
||||
*
|
||||
* Copyright (C) 2013 St. Antoniusziekenhuis
|
||||
*
|
||||
* 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.common.entities;
|
||||
|
||||
import org.libreplan.business.common.BaseEntity;
|
||||
import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
|
||||
|
||||
/**
|
||||
* JiraConfiguration entity
|
||||
*
|
||||
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
|
||||
*/
|
||||
public class JiraConfiguration extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Code prefix for different entities integrated with JIRA.
|
||||
*/
|
||||
public static final String CODE_PREFIX = "JIRA-";
|
||||
|
||||
public static JiraConfiguration create() {
|
||||
return create(new JiraConfiguration());
|
||||
}
|
||||
|
||||
private boolean jiraActivated;
|
||||
|
||||
private String jiraUrl;
|
||||
|
||||
/**
|
||||
* Stores one of the next 2 options:
|
||||
* <ul>
|
||||
* <li>A comma-separated list of labels</li>
|
||||
* <li>A URL that will return a comma-separated list of labels</li>
|
||||
* </ul>
|
||||
*/
|
||||
private String jiraLabels;
|
||||
|
||||
private String jiraUserId;
|
||||
|
||||
private String jiraPassword;
|
||||
|
||||
private TypeOfWorkHours jiraConnectorTypeOfWorkHours;
|
||||
|
||||
/**
|
||||
* Constructor for Hibernate. Do not use!
|
||||
*/
|
||||
protected JiraConfiguration() {
|
||||
}
|
||||
|
||||
public boolean isJiraActivated() {
|
||||
return jiraActivated;
|
||||
}
|
||||
|
||||
public void setJiraActivated(boolean jiraActivated) {
|
||||
this.jiraActivated = jiraActivated;
|
||||
}
|
||||
|
||||
public String getJiraUrl() {
|
||||
return jiraUrl;
|
||||
}
|
||||
|
||||
public void setJiraUrl(String jiraUrl) {
|
||||
this.jiraUrl = jiraUrl;
|
||||
}
|
||||
|
||||
public String getJiraLabels() {
|
||||
return jiraLabels;
|
||||
}
|
||||
|
||||
public void setJiraLabels(String jiraLabels) {
|
||||
this.jiraLabels = jiraLabels;
|
||||
}
|
||||
|
||||
public String getJiraUserId() {
|
||||
return jiraUserId;
|
||||
}
|
||||
|
||||
public void setJiraUserId(String jiraUserId) {
|
||||
this.jiraUserId = jiraUserId;
|
||||
}
|
||||
|
||||
public String getJiraPassword() {
|
||||
return jiraPassword;
|
||||
}
|
||||
|
||||
public void setJiraPassword(String jiraPassword) {
|
||||
this.jiraPassword = jiraPassword;
|
||||
}
|
||||
|
||||
public TypeOfWorkHours getJiraConnectorTypeOfWorkHours() {
|
||||
return jiraConnectorTypeOfWorkHours;
|
||||
}
|
||||
|
||||
public void setJiraConnectorTypeOfWorkHours(TypeOfWorkHours typeOfWorkHours) {
|
||||
jiraConnectorTypeOfWorkHours = typeOfWorkHours;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* 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.common.entities;
|
||||
|
||||
import static org.libreplan.business.i18n.I18nHelper._;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.Months;
|
||||
import org.joda.time.Weeks;
|
||||
|
||||
/**
|
||||
* Different values for personal timesheets periodicity.
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public enum PersonalTimesheetsPeriodicityEnum {
|
||||
|
||||
MONTHLY(_("Monthly")) {
|
||||
@Override
|
||||
public LocalDate getStart(LocalDate date) {
|
||||
return date.dayOfMonth().withMinimumValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getEnd(LocalDate date) {
|
||||
return date.dayOfMonth().withMaximumValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsBetween(LocalDate start, LocalDate end) {
|
||||
return Months.monthsBetween(start, end).getMonths();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getDateForItemFromDate(int item, LocalDate fromDate) {
|
||||
return fromDate.plusMonths(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate previous(LocalDate date) {
|
||||
return getStart(date).minusMonths(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate next(LocalDate date) {
|
||||
return getStart(date).plusMonths(1);
|
||||
}
|
||||
},
|
||||
TWICE_MONTHLY(_("Twice-monthly")) {
|
||||
@Override
|
||||
public LocalDate getStart(LocalDate date) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
return date.dayOfMonth().withMinimumValue();
|
||||
} else {
|
||||
return date.dayOfMonth().withMinimumValue().plusDays(15);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getEnd(LocalDate date) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
return date.dayOfMonth().withMinimumValue().plusDays(14);
|
||||
} else {
|
||||
return date.dayOfMonth().withMaximumValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsBetween(LocalDate start, LocalDate end) {
|
||||
return Months.monthsBetween(start, end).getMonths() * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getDateForItemFromDate(int item, LocalDate fromDate) {
|
||||
int months = (item % 2 == 0) ? (item / 2) : ((item - 1) / 2);
|
||||
LocalDate date = fromDate.plusMonths(months);
|
||||
if (item % 2 != 0) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
date = date.dayOfMonth().withMinimumValue().plusDays(15);
|
||||
} else {
|
||||
date = date.plusMonths(1).dayOfMonth().withMinimumValue();
|
||||
}
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate previous(LocalDate date) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
return date.minusMonths(1).dayOfMonth().withMinimumValue()
|
||||
.plusDays(15);
|
||||
} else {
|
||||
return date.dayOfMonth().withMinimumValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate next(LocalDate date) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
return date.dayOfMonth().withMinimumValue().plusDays(15);
|
||||
} else {
|
||||
return date.plusMonths(1).dayOfMonth().withMinimumValue();
|
||||
}
|
||||
}
|
||||
},
|
||||
WEEKLY(_("Weekly")) {
|
||||
@Override
|
||||
public LocalDate getStart(LocalDate date) {
|
||||
return date.dayOfWeek().withMinimumValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getEnd(LocalDate date) {
|
||||
return date.dayOfWeek().withMaximumValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsBetween(LocalDate start, LocalDate end) {
|
||||
return Weeks.weeksBetween(start, end).getWeeks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getDateForItemFromDate(int item, LocalDate fromDate) {
|
||||
return fromDate.plusWeeks(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate previous(LocalDate date) {
|
||||
return getStart(date).minusWeeks(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate next(LocalDate date) {
|
||||
return getStart(date).plusWeeks(1);
|
||||
}
|
||||
};
|
||||
|
||||
private String name;
|
||||
|
||||
private PersonalTimesheetsPeriodicityEnum(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the start date of the personal timesheet which includes the
|
||||
* specified <code>date</code>.
|
||||
*/
|
||||
public abstract LocalDate getStart(LocalDate date);
|
||||
|
||||
/**
|
||||
* Returns the end date of the personal timesheet which includes the
|
||||
* specified <code>date</code>.
|
||||
*/
|
||||
public abstract LocalDate getEnd(LocalDate date);
|
||||
|
||||
/**
|
||||
* Returns the number of personal timesheets between the specified dates.
|
||||
*/
|
||||
public abstract int getItemsBetween(LocalDate start, LocalDate end);
|
||||
|
||||
/**
|
||||
* Returns the date of the personal timesheet in the position specified by
|
||||
* <code>item</code> taking into account the <code>fromDate</code>.
|
||||
*/
|
||||
public abstract LocalDate getDateForItemFromDate(int item,
|
||||
LocalDate fromDate);
|
||||
|
||||
/**
|
||||
* Returns the date of the previous personal timesheet to the one which
|
||||
* includes the specified <code>date</code>.
|
||||
*/
|
||||
public abstract LocalDate previous(LocalDate date);
|
||||
|
||||
/**
|
||||
* Returns the date of the next personal timesheet to the one which includes
|
||||
* the specified <code>date</code>.
|
||||
*/
|
||||
public abstract LocalDate next(LocalDate date);
|
||||
|
||||
}
|
||||
|
|
@ -148,7 +148,8 @@ public class TypeOfWorkHoursDAO extends IntegrationEntityDAO<TypeOfWorkHours>
|
|||
public void checkIsReferencedByOtherEntities(TypeOfWorkHours type) throws ValidationException {
|
||||
checkHasHourCost(type);
|
||||
checkHasWorkReportLine(type);
|
||||
checkIsMonthlyTimesheetsTypeOfWorkHours(type);
|
||||
checkIsPersonalTimesheetsTypeOfWorkHours(type);
|
||||
checkIsJiraConnectorTypeOfWorkHours(type);
|
||||
}
|
||||
|
||||
private void checkHasWorkReportLine(TypeOfWorkHours type) {
|
||||
|
|
@ -174,13 +175,13 @@ public class TypeOfWorkHoursDAO extends IntegrationEntityDAO<TypeOfWorkHours>
|
|||
}
|
||||
}
|
||||
|
||||
private void checkIsMonthlyTimesheetsTypeOfWorkHours(TypeOfWorkHours type) {
|
||||
private void checkIsPersonalTimesheetsTypeOfWorkHours(TypeOfWorkHours type) {
|
||||
Configuration configuration = configurationDAO.getConfiguration();
|
||||
if (configuration.getMonthlyTimesheetsTypeOfWorkHours().getId()
|
||||
if (configuration.getPersonalTimesheetsTypeOfWorkHours().getId()
|
||||
.equals(type.getId())) {
|
||||
throw ValidationException
|
||||
.invalidValue(
|
||||
"Cannot delete the type of work hours. It is configured as type of work hours for monthly timesheets.",
|
||||
"Cannot delete the type of work hours. It is configured as type of work hours for personal timesheets.",
|
||||
type);
|
||||
}
|
||||
}
|
||||
|
|
@ -192,4 +193,15 @@ public class TypeOfWorkHoursDAO extends IntegrationEntityDAO<TypeOfWorkHours>
|
|||
return c.uniqueResult() != null;
|
||||
}
|
||||
|
||||
private void checkIsJiraConnectorTypeOfWorkHours(TypeOfWorkHours type) {
|
||||
Configuration configuration = configurationDAO.getConfiguration();
|
||||
if (configuration.getJiraConfiguration()
|
||||
.getJiraConnectorTypeOfWorkHours().getId().equals(type.getId())) {
|
||||
throw ValidationException
|
||||
.invalidValue(
|
||||
"Cannot delete the type of work hours. It is configured as type of work hours for JIRA connector.",
|
||||
type);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,11 +143,11 @@ public class TypeOfWorkHours extends IntegrationEntity implements IHumanIdentifi
|
|||
}
|
||||
}
|
||||
|
||||
@AssertTrue(message = "type of work hours for monthly timesheets cannot be disabled")
|
||||
public boolean checkMonthlyTimesheetsTypeOfWorkHoursNotDisabled() {
|
||||
@AssertTrue(message = "type of work hours for personal timesheets cannot be disabled")
|
||||
public boolean checkPersonalTimesheetsTypeOfWorkHoursNotDisabled() {
|
||||
if (!isNewObject() && !getEnabled()) {
|
||||
TypeOfWorkHours typeOfWorkHours = Registry.getConfigurationDAO()
|
||||
.getConfiguration().getMonthlyTimesheetsTypeOfWorkHours();
|
||||
.getConfiguration().getPersonalTimesheetsTypeOfWorkHours();
|
||||
if (typeOfWorkHours.getId().equals(getId())) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -165,4 +165,18 @@ public class TypeOfWorkHours extends IntegrationEntity implements IHumanIdentifi
|
|||
return name;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "type of work hours for JIRA connector cannot be disabled")
|
||||
public boolean checkJiraConnectorTypeOfWorkHoursNotDisabled() {
|
||||
if (!isNewObject() && !getEnabled()) {
|
||||
TypeOfWorkHours typeOfWorkHours = Registry.getConfigurationDAO()
|
||||
.getConfiguration().getJiraConfiguration()
|
||||
.getJiraConnectorTypeOfWorkHours();
|
||||
if (typeOfWorkHours.getId().equals(getId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -244,6 +244,10 @@ public class ExpenseSheet extends IntegrationEntity implements IHumanIdentifiabl
|
|||
return true;
|
||||
}
|
||||
|
||||
if (expenseSheetLines.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Resource resource = expenseSheetLines.iterator().next().getResource();
|
||||
|
||||
for (ExpenseSheetLine line : expenseSheetLines) {
|
||||
|
|
|
|||
|
|
@ -105,14 +105,14 @@ public class HibernateDatabaseModificationsListener implements
|
|||
|
||||
@Override
|
||||
public void afterCompletion(int status) {
|
||||
LOG.info("transaction completed with status: " + status);
|
||||
LOG.debug("transaction completed with status: " + status);
|
||||
pending.remove(transaction);
|
||||
if (isProbablySucessful(status)) {
|
||||
List<Class<?>> list = new ArrayList<Class<?>>();
|
||||
classes.drainTo(list);
|
||||
LOG.info(list.size() + " modification events recorded");
|
||||
LOG.debug(list.size() + " modification events recorded");
|
||||
Set<NotBlockingAutoUpdatedSnapshot<?>> toDispatch = snapshotsInterestedOn(list);
|
||||
LOG.info("dispatching "
|
||||
LOG.debug("dispatching "
|
||||
+ toDispatch
|
||||
+ " snapshots to reload due to transaction successful completion");
|
||||
dispatch(toDispatch);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ class NotBlockingAutoUpdatedSnapshot<T> implements IAutoUpdatedSnapshot<T> {
|
|||
newValue));
|
||||
return newValue;
|
||||
}
|
||||
LOG.info(name + " the ongoing calculation has not been completed. "
|
||||
LOG.debug(name + " the ongoing calculation has not been completed. "
|
||||
+ "Returning previous value");
|
||||
return previousValue.getValue();
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ class NotBlockingAutoUpdatedSnapshot<T> implements IAutoUpdatedSnapshot<T> {
|
|||
if (ongoingCalculation.isDone() || ongoingCalculation.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
LOG.info(name + " cancelling ongoing future");
|
||||
LOG.debug(name + " cancelling ongoing future");
|
||||
try {
|
||||
ongoingCalculation.cancel(true);
|
||||
} catch (Exception e) {
|
||||
|
|
@ -283,19 +283,19 @@ class NotBlockingAutoUpdatedSnapshot<T> implements IAutoUpdatedSnapshot<T> {
|
|||
|
||||
private void report(long timeWaiting, long timeExecuting, Data data,
|
||||
Exception possibleError) {
|
||||
LOG.info(name + " took " + timeExecuting + " ms executing");
|
||||
LOG.debug(name + " took " + timeExecuting + " ms executing");
|
||||
if (possibleError != null) {
|
||||
LOG.error("error loading " + name, possibleError);
|
||||
}
|
||||
LOG.info(name + " waited for " + timeWaiting
|
||||
LOG.debug(name + " waited for " + timeWaiting
|
||||
+ " ms until executing");
|
||||
LOG.info(name + " mean time waiting for execution: "
|
||||
LOG.debug(name + " mean time waiting for execution: "
|
||||
+ data.totalMsWaiting / data.executionTimes + " ms");
|
||||
LOG.info(name + " mean time executing: "
|
||||
LOG.debug(name + " mean time executing: "
|
||||
+ data.totalMsExecuting / data.executionTimes + " ms");
|
||||
LOG.info(name + " has been executed " + data.executionTimes
|
||||
LOG.debug(name + " has been executed " + data.executionTimes
|
||||
+ " times");
|
||||
LOG.info(name + " has produced errors " + data.errors + " times");
|
||||
LOG.debug(name + " has produced errors " + data.errors + " times");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,4 +132,8 @@ public class Label extends IntegrationEntity implements Comparable<Label> {
|
|||
return getTypeAndName().compareToIgnoreCase(o.getTypeAndName());
|
||||
}
|
||||
|
||||
public String getFinderPattern() {
|
||||
return String.format("%s ( %s )", name, type.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,11 @@ import java.util.List;
|
|||
|
||||
import org.libreplan.business.common.daos.IIntegrationEntityDAO;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
|
||||
import org.libreplan.business.labels.entities.Label;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.orders.entities.OrderStatusEnum;
|
||||
import org.libreplan.business.planner.entities.Task;
|
||||
import org.libreplan.business.reports.dtos.CostExpenseSheetDTO;
|
||||
import org.libreplan.business.reports.dtos.OrderCostsPerResourceDTO;
|
||||
|
|
@ -79,6 +82,11 @@ public interface IOrderDAO extends IIntegrationEntityDAO<Order> {
|
|||
List<Order> getOrdersByReadAuthorizationByScenario(String username,
|
||||
Scenario scenario);
|
||||
|
||||
List<Order> getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
|
||||
String username, Scenario scenario, Date startDate, Date endDate,
|
||||
List<Label> labels, List<Criterion> criteria,
|
||||
ExternalCompany customer, OrderStatusEnum state);
|
||||
|
||||
/**
|
||||
* Returns the order filtered by the name. If name is blank (whitespace,
|
||||
* empty ("") or null, it throws <code>InstanceNotFoundException</code>.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ import java.util.Set;
|
|||
|
||||
import org.libreplan.business.common.daos.IIntegrationEntityDAO;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.labels.entities.Label;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.resources.entities.Criterion;
|
||||
import org.libreplan.business.templates.entities.OrderElementTemplate;
|
||||
import org.libreplan.business.workingday.EffortDuration;
|
||||
|
||||
|
|
@ -85,10 +87,6 @@ public interface IOrderElementDAO extends IIntegrationEntityDAO<OrderElement> {
|
|||
OrderElement findUniqueByCodeAnotherTransaction(String code)
|
||||
throws InstanceNotFoundException;
|
||||
|
||||
boolean existsOtherOrderElementByCode(OrderElement orderElement);
|
||||
|
||||
boolean existsByCodeAnotherTransaction(OrderElement orderElement);
|
||||
|
||||
List<OrderElement> getAll();
|
||||
|
||||
public List<OrderElement> findOrderElementsWithExternalCode();
|
||||
|
|
@ -107,6 +105,8 @@ public interface IOrderElementDAO extends IIntegrationEntityDAO<OrderElement> {
|
|||
|
||||
EffortDuration calculateMinWorkedHours(final List<OrderElement> list);
|
||||
|
||||
boolean isAlreadyInUse(OrderElement orderElement);
|
||||
|
||||
boolean isAlreadyInUseThisOrAnyOfItsChildren(OrderElement orderElement);
|
||||
|
||||
/**
|
||||
|
|
@ -128,6 +128,14 @@ public interface IOrderElementDAO extends IIntegrationEntityDAO<OrderElement> {
|
|||
|
||||
boolean hasImputedExpenseSheet(Long id) throws InstanceNotFoundException;
|
||||
|
||||
boolean hasImputedExpenseSheetThisOrAnyOfItsChildren(Long id) throws InstanceNotFoundException;
|
||||
|
||||
OrderElement findByExternalCode(String code) throws InstanceNotFoundException;
|
||||
|
||||
public List<OrderElement> findByLabelsAndCriteria(Set<Label> labels,
|
||||
Set<Criterion> criteria);
|
||||
|
||||
boolean existsByCodeInAnotherOrderAnotherTransaction(
|
||||
OrderElement orderElement);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,4 +74,26 @@ public interface ISumChargedEffortDAO extends
|
|||
*/
|
||||
void recalculateSumChargedEfforts(Long orderId);
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} of {@link OrderElement OrderElements} affected by
|
||||
* any change taking into account the lines in the report and the ones to be
|
||||
* removed.
|
||||
*
|
||||
* Usually you call this method to get the set before saving the work
|
||||
* report. After saving the work report you call
|
||||
* {@link ISumChargedEffortDAO#recalculateTimesheetData(Set)} with the
|
||||
* result of this method.
|
||||
*
|
||||
* You can pass <code>null</code> as param if you only have one of the sets.
|
||||
*/
|
||||
Set<OrderElement> getOrderElementsToRecalculateTimsheetDates(
|
||||
Set<WorkReportLine> workReportLines,
|
||||
Set<WorkReportLine> deletedWorkReportLinesSet);
|
||||
|
||||
/**
|
||||
* Recalulates the first and last timesheets dates for each
|
||||
* {@link OrderElement} in the {@link Set}.
|
||||
*/
|
||||
void recalculateTimesheetData(Set<OrderElement> orderElements);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,12 @@ import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
|||
import org.libreplan.business.costcategories.daos.CostCategoryDAO;
|
||||
import org.libreplan.business.costcategories.daos.ITypeOfWorkHoursDAO;
|
||||
import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
|
||||
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
|
||||
import org.libreplan.business.labels.entities.Label;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.orders.entities.OrderStatusEnum;
|
||||
import org.libreplan.business.orders.entities.SchedulingState;
|
||||
import org.libreplan.business.planner.daos.ITaskSourceDAO;
|
||||
import org.libreplan.business.planner.entities.Task;
|
||||
import org.libreplan.business.reports.dtos.CostExpenseSheetDTO;
|
||||
|
|
@ -214,6 +217,242 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements
|
|||
}
|
||||
}
|
||||
|
||||
private List<Order> getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
|
||||
User user, Date startDate, Date endDate, List<Label> labels,
|
||||
List<Criterion> criteria, ExternalCompany customer,
|
||||
OrderStatusEnum state) {
|
||||
List<Long> ordersIdsFiltered = getOrdersIdsFiltered(user, labels,
|
||||
criteria, customer, state);
|
||||
if (ordersIdsFiltered != null && ordersIdsFiltered.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Long> ordersIdsByDates = getOrdersIdsByDates(startDate, endDate);
|
||||
if (ordersIdsByDates != null && ordersIdsByDates.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Long> ordersIdsUnscheduled = getOrdersIdsUnscheduled(startDate,
|
||||
endDate);
|
||||
|
||||
Criteria c = getSession().createCriteria(Order.class);
|
||||
if (ordersIdsFiltered != null && ordersIdsByDates != null) {
|
||||
org.hibernate.criterion.Criterion and = Restrictions.and(
|
||||
Restrictions.in("id", ordersIdsFiltered),
|
||||
Restrictions.in("id", ordersIdsByDates));
|
||||
c.add(and);
|
||||
} else {
|
||||
if (ordersIdsFiltered != null) {
|
||||
c.add(Restrictions.in("id", ordersIdsFiltered));
|
||||
}
|
||||
if (ordersIdsByDates != null) {
|
||||
if (ordersIdsUnscheduled.isEmpty()) {
|
||||
c.add(Restrictions.in("id", ordersIdsByDates));
|
||||
} else {
|
||||
c.add(Restrictions.or(
|
||||
Restrictions.in("id", ordersIdsByDates),
|
||||
Restrictions.in("id", ordersIdsUnscheduled)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.addOrder(org.hibernate.criterion.Order.desc("initDate"));
|
||||
c.addOrder(org.hibernate.criterion.Order.asc("infoComponent.name"));
|
||||
return c.list();
|
||||
}
|
||||
|
||||
private List<Long> getOrdersIdsUnscheduled(Date startDate, Date endDate) {
|
||||
String strQuery = "SELECT s.orderElement.id "
|
||||
+ "FROM SchedulingDataForVersion s "
|
||||
+ "WHERE s.schedulingStateType = :type";
|
||||
Query query = getSession().createQuery(strQuery);
|
||||
query.setParameter("type", SchedulingState.Type.NO_SCHEDULED);
|
||||
|
||||
List<Long> ordersIdsUnscheduled = query.list();
|
||||
if (ordersIdsUnscheduled.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String strQueryDates = "SELECT o.id "
|
||||
+ "FROM Order o "
|
||||
+ "WHERE o.id IN (:ids) ";
|
||||
|
||||
if (startDate != null) {
|
||||
strQueryDates += "AND o.initDate >= :startDate ";
|
||||
}
|
||||
if (endDate != null) {
|
||||
strQueryDates += "AND o.initDate <= :endDate ";
|
||||
}
|
||||
|
||||
Query queryDates = getSession().createQuery(strQueryDates);
|
||||
if (startDate != null) {
|
||||
queryDates.setParameter("startDate", startDate);
|
||||
}
|
||||
if (endDate != null) {
|
||||
queryDates.setParameter("endDate", endDate);
|
||||
}
|
||||
queryDates.setParameterList("ids", ordersIdsUnscheduled);
|
||||
|
||||
return queryDates.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* If both params are <code>null</code> it returns <code>null</code>.
|
||||
* Otherwise it filters the list of tasks to return the ones wihtout parent
|
||||
* between the dates.
|
||||
*/
|
||||
private List<Long> getOrdersIdsByDates(Date startDate, Date endDate) {
|
||||
if (startDate == null && endDate == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String strQuery = "SELECT t.taskSource.schedulingData.orderElement.id "
|
||||
+ "FROM TaskElement t "
|
||||
+ "WHERE t.parent IS NULL ";
|
||||
if (endDate != null) {
|
||||
strQuery += "AND t.startDate.date <= :endDate ";
|
||||
}
|
||||
if (startDate != null) {
|
||||
strQuery += "AND t.endDate.date >= :startDate ";
|
||||
}
|
||||
|
||||
Query query = getSession().createQuery(strQuery);
|
||||
if (startDate != null) {
|
||||
query.setParameter("startDate", LocalDate.fromDateFields(startDate));
|
||||
}
|
||||
if (endDate != null) {
|
||||
query.setParameter("endDate", LocalDate.fromDateFields(endDate));
|
||||
}
|
||||
|
||||
return query.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* If user has permissions over all orders and not filters are passed it
|
||||
* returns <code>null</code>. Otherwise, it returns the list of orders
|
||||
* identifiers for which the user has read permissions and the filters pass.
|
||||
*/
|
||||
private List<Long> getOrdersIdsFiltered(User user, List<Label> labels,
|
||||
List<Criterion> criteria, ExternalCompany customer,
|
||||
OrderStatusEnum state) {
|
||||
List<Long> ordersIdsByReadAuthorization = getOrdersIdsByReadAuthorization(user);
|
||||
|
||||
String strQuery = "SELECT o.id ";
|
||||
strQuery += "FROM Order o ";
|
||||
|
||||
String where = "";
|
||||
String whereFinal = "";
|
||||
if (labels != null && !labels.isEmpty()) {
|
||||
for (int i = 0; i < labels.size(); i++) {
|
||||
if (where.isEmpty()) {
|
||||
where += "WHERE ";
|
||||
} else {
|
||||
where += "AND ";
|
||||
}
|
||||
where += ":label" + i + " IN elements(o.labels) ";
|
||||
}
|
||||
}
|
||||
|
||||
if (criteria != null && !criteria.isEmpty()) {
|
||||
strQuery += "JOIN o.criterionRequirements cr ";
|
||||
if (where.isEmpty()) {
|
||||
where += "WHERE ";
|
||||
} else {
|
||||
where += "AND ";
|
||||
}
|
||||
where += "cr.criterion IN (:criteria) ";
|
||||
where += "AND cr.class = DirectCriterionRequirement ";
|
||||
whereFinal += "GROUP BY o.id ";
|
||||
whereFinal += "HAVING count(o.id) = :criteriaSize ";
|
||||
}
|
||||
|
||||
if (customer != null) {
|
||||
if (where.isEmpty()) {
|
||||
where += "WHERE ";
|
||||
} else {
|
||||
where += "AND ";
|
||||
}
|
||||
where += "o.customer = :customer ";
|
||||
}
|
||||
|
||||
if (state != null) {
|
||||
if (where.isEmpty()) {
|
||||
where += "WHERE ";
|
||||
} else {
|
||||
where += "AND ";
|
||||
}
|
||||
where += "o.state = :state ";
|
||||
}
|
||||
|
||||
// If not restrictions by labels, criteria, customer or state
|
||||
if (where.isEmpty()) {
|
||||
return ordersIdsByReadAuthorization;
|
||||
}
|
||||
|
||||
if (ordersIdsByReadAuthorization != null
|
||||
&& !ordersIdsByReadAuthorization.isEmpty()) {
|
||||
if (where.isEmpty()) {
|
||||
where += "WHERE ";
|
||||
} else {
|
||||
where += "AND ";
|
||||
}
|
||||
where += "o.id IN (:ids) ";
|
||||
}
|
||||
|
||||
strQuery += where + whereFinal;
|
||||
Query query = getSession().createQuery(strQuery);
|
||||
if (labels != null && !labels.isEmpty()) {
|
||||
int i = 0;
|
||||
for (Label label : labels) {
|
||||
query.setParameter("label" + i, label);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (criteria != null && !criteria.isEmpty()) {
|
||||
query.setParameterList("criteria", criteria);
|
||||
query.setParameter("criteriaSize", (long) criteria.size());
|
||||
}
|
||||
|
||||
if (customer != null) {
|
||||
query.setParameter("customer", customer);
|
||||
}
|
||||
|
||||
if (state != null) {
|
||||
query.setParameter("state", state);
|
||||
}
|
||||
|
||||
if (ordersIdsByReadAuthorization != null
|
||||
&& !ordersIdsByReadAuthorization.isEmpty()) {
|
||||
query.setParameterList("ids", ordersIdsByReadAuthorization);
|
||||
}
|
||||
|
||||
return query.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* If user has permissions over all orders it returns <code>null</code>.
|
||||
* Otherwise, it returns the list of orders identifiers for which the user
|
||||
* has read permissions.
|
||||
*/
|
||||
private List<Long> getOrdersIdsByReadAuthorization(User user) {
|
||||
if (user.isInRole(UserRole.ROLE_SUPERUSER)
|
||||
|| user.isInRole(UserRole.ROLE_READ_ALL_PROJECTS)
|
||||
|| user.isInRole(UserRole.ROLE_EDIT_ALL_PROJECTS)) {
|
||||
return null;
|
||||
} else {
|
||||
String strQuery = "SELECT oa.order.id "
|
||||
+ "FROM OrderAuthorization oa "
|
||||
+ "WHERE oa.user = :user "
|
||||
+ "OR oa.profile IN (:profiles) ";
|
||||
|
||||
Query query = getSession().createQuery(strQuery);
|
||||
query.setParameter("user", user);
|
||||
query.setParameterList("profiles", user.getProfiles());
|
||||
|
||||
return query.list();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Order> getOrdersByWriteAuthorization(User user) {
|
||||
if (user.isInRole(UserRole.ROLE_SUPERUSER)
|
||||
|
|
@ -244,6 +483,7 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Order findByCode(String code) throws InstanceNotFoundException {
|
||||
|
||||
if (StringUtils.isBlank(code)) {
|
||||
|
|
@ -277,6 +517,23 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements
|
|||
return existsInScenario(getOrdersByReadAuthorization(user), scenario);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Order> getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
|
||||
String username, Scenario scenario, Date startDate, Date endDate,
|
||||
List<Label> labels, List<Criterion> criteria,
|
||||
ExternalCompany customer, OrderStatusEnum state) {
|
||||
User user;
|
||||
try {
|
||||
user = userDAO.findByLoginName(username);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return existsInScenario(
|
||||
getOrdersByReadAuthorizationBetweenDatesByLabelsCriteriaCustomerAndState(
|
||||
user, startDate, endDate, labels, criteria, customer,
|
||||
state), scenario);
|
||||
}
|
||||
|
||||
private List<Order> existsInScenario(List<Order> orders, Scenario scenario) {
|
||||
List<Order> result = new ArrayList<Order>();
|
||||
for (Order each : orders) {
|
||||
|
|
@ -445,9 +702,6 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements
|
|||
+ "LEFT OUTER JOIN expense.orderElement exp_ord "
|
||||
+ "WHERE orderElement.id = exp_ord.id ";
|
||||
|
||||
if (!orders.isEmpty()) {
|
||||
strQuery += "AND orderElement.parent IN (:orders) ";
|
||||
}
|
||||
if (startingDate != null && endingDate != null) {
|
||||
strQuery += "AND expense.date BETWEEN :startingDate AND :endingDate ";
|
||||
}
|
||||
|
|
@ -464,9 +718,6 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements
|
|||
Query query = getSession().createQuery(strQuery);
|
||||
|
||||
// Set parameters
|
||||
if (!orders.isEmpty()) {
|
||||
query.setParameterList("orders", orders);
|
||||
}
|
||||
if (startingDate != null) {
|
||||
query.setParameter("startingDate", new LocalDate(startingDate));
|
||||
}
|
||||
|
|
@ -480,7 +731,8 @@ public class OrderDAO extends IntegrationEntityDAO<Order> implements
|
|||
for (CostExpenseSheetDTO each : list) {
|
||||
Order order = loadOrderAvoidingProxyFor(each.getOrderElement());
|
||||
// Apply filtering
|
||||
if (matchFilterCriterion(each.getOrderElement(), criterions)) {
|
||||
if (matchFilterCriterion(each.getOrderElement(), criterions)
|
||||
&& isOrderContained(order, orders)) {
|
||||
each.setOrder(order);
|
||||
filteredList.add(each);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.math.BigDecimal;
|
|||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
|
@ -41,10 +42,13 @@ import org.libreplan.business.common.IAdHocTransactionService;
|
|||
import org.libreplan.business.common.daos.IntegrationEntityDAO;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.expensesheet.daos.IExpenseSheetLineDAO;
|
||||
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.SchedulingDataForVersion;
|
||||
import org.libreplan.business.orders.entities.TaskSource;
|
||||
import org.libreplan.business.planner.daos.ITaskSourceDAO;
|
||||
import org.libreplan.business.resources.entities.Criterion;
|
||||
import org.libreplan.business.templates.entities.OrderElementTemplate;
|
||||
import org.libreplan.business.workingday.EffortDuration;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportDAO;
|
||||
|
|
@ -202,6 +206,7 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public OrderElement findByCode(String code)
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
|
|
@ -253,22 +258,6 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
|
|||
return findUniqueByCode(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsOtherOrderElementByCode(OrderElement orderElement) {
|
||||
try {
|
||||
OrderElement t = findUniqueByCode(orderElement.getCode());
|
||||
return t != null && t != orderElement;
|
||||
} catch (InstanceNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
|
||||
public boolean existsByCodeAnotherTransaction(OrderElement orderElement) {
|
||||
return existsOtherOrderElementByCode(orderElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OrderElement> getAll() {
|
||||
return list(OrderElement.class);
|
||||
|
|
@ -417,7 +406,8 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
|
|||
return min;
|
||||
}
|
||||
|
||||
private boolean isAlreadyInUse(OrderElement orderElement) {
|
||||
@Override
|
||||
public boolean isAlreadyInUse(OrderElement orderElement) {
|
||||
if (orderElement.isNewObject()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -488,9 +478,11 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
|
|||
OrderElement orderElementInDB = orderElementsInDB.get(code);
|
||||
|
||||
// There's an element in the DB with the same code and it's a
|
||||
// different element
|
||||
// different element in a different order
|
||||
if (orderElementInDB != null
|
||||
&& !orderElementInDB.getId().equals(orderElement.getId())) {
|
||||
&& !orderElementInDB.getId().equals(orderElement.getId())
|
||||
&& !orderElementInDB.getOrder().getId()
|
||||
.equals(orderElement.getOrder().getId())) {
|
||||
return orderElement;
|
||||
}
|
||||
}
|
||||
|
|
@ -514,8 +506,101 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean hasImputedExpenseSheet(Long id) throws InstanceNotFoundException {
|
||||
public boolean hasImputedExpenseSheet(Long id)
|
||||
throws InstanceNotFoundException {
|
||||
OrderElement orderElement = find(id);
|
||||
return (!expenseSheetLineDAO.findByOrderElement(orderElement).isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasImputedExpenseSheetThisOrAnyOfItsChildren(Long id) throws InstanceNotFoundException {
|
||||
OrderElement orderElement = find(id);
|
||||
return (!expenseSheetLineDAO.findByOrderElementAndChildren(orderElement).isEmpty());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<OrderElement> findByLabelsAndCriteria(Set<Label> labels,
|
||||
Set<Criterion> criteria) {
|
||||
|
||||
String strQuery = "SELECT oe.id ";
|
||||
strQuery += "FROM OrderElement oe ";
|
||||
|
||||
String where = "";
|
||||
if (labels != null && !labels.isEmpty()) {
|
||||
for (int i = 0; i < labels.size(); i++) {
|
||||
if (where.isEmpty()) {
|
||||
where += "WHERE ";
|
||||
} else {
|
||||
where += "AND ";
|
||||
}
|
||||
where += ":label" + i + " IN elements(oe.labels) ";
|
||||
}
|
||||
}
|
||||
|
||||
if (criteria != null && !criteria.isEmpty()) {
|
||||
strQuery += "JOIN oe.criterionRequirements cr ";
|
||||
if (where.isEmpty()) {
|
||||
where += "WHERE ";
|
||||
} else {
|
||||
where += "AND ";
|
||||
}
|
||||
where += "cr.criterion IN (:criteria) ";
|
||||
where += "AND cr.class = DirectCriterionRequirement ";
|
||||
where += "GROUP BY oe.id ";
|
||||
where += "HAVING count(oe.id) = :criteriaSize ";
|
||||
}
|
||||
|
||||
strQuery += where;
|
||||
|
||||
Query query = getSession().createQuery(strQuery);
|
||||
if (labels != null && !labels.isEmpty()) {
|
||||
int i = 0;
|
||||
for (Label label : labels) {
|
||||
query.setParameter("label" + i, label);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (criteria != null && !criteria.isEmpty()) {
|
||||
query.setParameterList("criteria", criteria);
|
||||
query.setParameter("criteriaSize", (long) criteria.size());
|
||||
}
|
||||
|
||||
List<Long> orderElementsIds = query.list();
|
||||
if (orderElementsIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return getSession()
|
||||
.createQuery(
|
||||
"FROM OrderElement oe WHERE oe.id IN (:ids) ORDER BY oe.infoComponent.code")
|
||||
.setParameterList("ids", orderElementsIds).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
|
||||
public boolean existsByCodeInAnotherOrderAnotherTransaction(
|
||||
OrderElement orderElement) {
|
||||
return existsByCodeInAnotherOrder(orderElement);
|
||||
}
|
||||
|
||||
private boolean existsByCodeInAnotherOrder(OrderElement orderElement) {
|
||||
try {
|
||||
OrderElement found = findUniqueByCode(orderElement.getCode());
|
||||
return !areInTheSameOrder(orderElement, found);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean areInTheSameOrder(OrderElement orderElement1,
|
||||
OrderElement orderElement2) {
|
||||
Order order1 = orderElement1.getOrder();
|
||||
Order order2 = orderElement2.getOrder();
|
||||
if (order1.getId() == null || order2.getId() == null) {
|
||||
return false;
|
||||
}
|
||||
return order1.getId().equals(order2.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -19,7 +19,11 @@
|
|||
|
||||
package org.libreplan.business.orders.daos;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -66,6 +70,9 @@ public class SumChargedEffortDAO extends
|
|||
@Autowired
|
||||
private IOrderDAO orderDAO;
|
||||
|
||||
@Autowired
|
||||
private IOrderElementDAO orderElementDAO;
|
||||
|
||||
private Map<OrderElement, SumChargedEffort> mapSumChargedEfforts;
|
||||
|
||||
@Override
|
||||
|
|
@ -114,6 +121,7 @@ public class SumChargedEffortDAO extends
|
|||
forceLoadParents(parent);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
previousEffort = previous.getFirst();
|
||||
|
|
@ -149,9 +157,6 @@ public class SumChargedEffortDAO extends
|
|||
private void addDirectChargedEffort(OrderElement orderElement,
|
||||
EffortDuration effort) {
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
if (sumChargedEffort == null) {
|
||||
sumChargedEffort = SumChargedEffort.create(orderElement);
|
||||
}
|
||||
|
||||
sumChargedEffort.addDirectChargedEffort(effort);
|
||||
save(sumChargedEffort);
|
||||
|
|
@ -163,9 +168,6 @@ public class SumChargedEffortDAO extends
|
|||
EffortDuration effort) {
|
||||
if (orderElement != null) {
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
if (sumChargedEffort == null) {
|
||||
sumChargedEffort = SumChargedEffort.create(orderElement);
|
||||
}
|
||||
|
||||
sumChargedEffort.addIndirectChargedEffort(effort);
|
||||
save(sumChargedEffort);
|
||||
|
|
@ -231,6 +233,9 @@ public class SumChargedEffortDAO extends
|
|||
.get(orderElement);
|
||||
if (sumChargedEffort == null) {
|
||||
sumChargedEffort = findByOrderElement(orderElement);
|
||||
if (sumChargedEffort == null) {
|
||||
sumChargedEffort = SumChargedEffort.create(orderElement);
|
||||
}
|
||||
mapSumChargedEfforts.put(orderElement, sumChargedEffort);
|
||||
}
|
||||
return sumChargedEffort;
|
||||
|
|
@ -251,6 +256,7 @@ public class SumChargedEffortDAO extends
|
|||
resetMapSumChargedEfforts();
|
||||
resetSumChargedEffort(order);
|
||||
calculateDirectChargedEffort(order);
|
||||
calculateTimesheetData(order);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
@ -258,9 +264,6 @@ public class SumChargedEffortDAO extends
|
|||
|
||||
private void resetSumChargedEffort(OrderElement orderElement) {
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
if (sumChargedEffort == null) {
|
||||
sumChargedEffort = SumChargedEffort.create(orderElement);
|
||||
}
|
||||
sumChargedEffort.reset();
|
||||
|
||||
for (OrderElement each : orderElement.getChildren()) {
|
||||
|
|
@ -281,4 +284,159 @@ public class SumChargedEffortDAO extends
|
|||
addDirectChargedEffort(orderElement, effort);
|
||||
}
|
||||
|
||||
private void calculateTimesheetData(OrderElement orderElement) {
|
||||
calculateTimesheetDatesAndChildren(orderElement);
|
||||
calculateFinishedTimesheetsAndChildren(orderElement);
|
||||
}
|
||||
|
||||
private Pair<Date, Date> calculateTimesheetDatesAndChildren(
|
||||
OrderElement orderElement) {
|
||||
Pair<Date, Date> minMax = workReportLineDAO
|
||||
.findMinAndMaxDatesByOrderElement(orderElement);
|
||||
|
||||
Set<Date> minDates = new HashSet<Date>();
|
||||
Set<Date> maxDates = new HashSet<Date>();
|
||||
|
||||
addIfNotNull(minDates, minMax.getFirst());
|
||||
addIfNotNull(maxDates, minMax.getSecond());
|
||||
|
||||
for (OrderElement child : orderElement.getChildren()) {
|
||||
Pair<Date, Date> minMaxChild = calculateTimesheetDatesAndChildren(child);
|
||||
addIfNotNull(minDates, minMaxChild.getFirst());
|
||||
addIfNotNull(maxDates, minMaxChild.getSecond());
|
||||
}
|
||||
|
||||
Pair<Date, Date> result = Pair.create(
|
||||
minDates.isEmpty() ? null : Collections.min(minDates),
|
||||
maxDates.isEmpty() ? null : Collections.max(maxDates));
|
||||
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
sumChargedEffort.setTimesheetDates(result.getFirst(),
|
||||
result.getSecond());
|
||||
save(sumChargedEffort);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addIfNotNull(Collection<Date> list, Date date) {
|
||||
if (date != null) {
|
||||
list.add(date);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateFinishedTimesheetsAndChildren(
|
||||
OrderElement orderElement) {
|
||||
calculateFinishedTimesheets(orderElement);
|
||||
|
||||
for (OrderElement child : orderElement.getChildren()) {
|
||||
calculateFinishedTimesheetsAndChildren(child);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateFinishedTimesheets(OrderElement orderElement) {
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
sumChargedEffort.setFinishedTimesheets(workReportLineDAO
|
||||
.isFinished(orderElement));
|
||||
save(sumChargedEffort);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Set<OrderElement> getOrderElementsToRecalculateTimsheetDates(
|
||||
Set<WorkReportLine> workReportLines,
|
||||
Set<WorkReportLine> deletedWorkReportLines) {
|
||||
Set<OrderElement> orderElements = new HashSet<OrderElement>();
|
||||
|
||||
if (workReportLines != null) {
|
||||
for (final WorkReportLine workReportLine : workReportLines) {
|
||||
if (!workReportLine.isNewObject()) {
|
||||
OrderElement previousOrderElement = transactionService
|
||||
.runOnAnotherTransaction(new IOnTransaction<OrderElement>() {
|
||||
@Override
|
||||
public OrderElement execute() {
|
||||
try {
|
||||
WorkReportLine line = workReportLineDAO
|
||||
.find(workReportLine.getId());
|
||||
|
||||
return line.getOrderElement();
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
orderElements.add(previousOrderElement);
|
||||
}
|
||||
orderElements.add(workReportLine.getOrderElement());
|
||||
}
|
||||
}
|
||||
|
||||
if (deletedWorkReportLines != null) {
|
||||
for (WorkReportLine workReportLine : deletedWorkReportLines) {
|
||||
if (workReportLine.isNewObject()) {
|
||||
// If the line hasn't been saved, we don't take it into
|
||||
// account
|
||||
continue;
|
||||
}
|
||||
|
||||
// Refresh data from database, because of changes not saved are
|
||||
// not
|
||||
// useful for the following operations
|
||||
sessionFactory.getCurrentSession().refresh(workReportLine);
|
||||
|
||||
orderElements.add(workReportLine.getOrderElement());
|
||||
}
|
||||
}
|
||||
|
||||
return orderElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void recalculateTimesheetData(Set<OrderElement> orderElements) {
|
||||
try {
|
||||
for (OrderElement orderElement : orderElements) {
|
||||
saveTimesheetDatesRecursively(orderElementDAO.find(orderElement
|
||||
.getId()));
|
||||
calculateFinishedTimesheets(orderElementDAO.find(orderElement
|
||||
.getId()));
|
||||
}
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveTimesheetDatesRecursively(OrderElement orderElement) {
|
||||
if (orderElement != null) {
|
||||
saveTimesheetDates(orderElement);
|
||||
saveTimesheetDatesRecursively(orderElement.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
private void saveTimesheetDates(OrderElement orderElement) {
|
||||
Pair<Date, Date> minMax = workReportLineDAO
|
||||
.findMinAndMaxDatesByOrderElement(orderElement);
|
||||
|
||||
Set<Date> minDates = new HashSet<Date>();
|
||||
Set<Date> maxDates = new HashSet<Date>();
|
||||
|
||||
addIfNotNull(minDates, minMax.getFirst());
|
||||
addIfNotNull(maxDates, minMax.getSecond());
|
||||
|
||||
for (OrderElement child : orderElement.getChildren()) {
|
||||
SumChargedEffort childSumChargedEffort = getByOrderElement(child);
|
||||
addIfNotNull(minDates,
|
||||
childSumChargedEffort.getFirstTimesheetDate());
|
||||
addIfNotNull(maxDates, childSumChargedEffort.getLastTimesheetDate());
|
||||
}
|
||||
|
||||
Pair<Date, Date> result = Pair.create(minDates.isEmpty() ? null
|
||||
: Collections.min(minDates), maxDates.isEmpty() ? null
|
||||
: Collections.max(maxDates));
|
||||
|
||||
SumChargedEffort sumChargedEffort = getByOrderElement(orderElement);
|
||||
sumChargedEffort.setTimesheetDates(result.getFirst(),
|
||||
result.getSecond());
|
||||
save(sumChargedEffort);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ public class Order extends OrderLineGroup implements Comparable {
|
|||
|
||||
private Set<CustomerCommunication> customerCommunications = new HashSet<CustomerCommunication>();
|
||||
|
||||
private String importedLabel;
|
||||
|
||||
@Valid
|
||||
private SortedSet<DeadlineCommunication> deliveringDates = new TreeSet<DeadlineCommunication>(
|
||||
new DeliverDateComparator());
|
||||
|
|
@ -670,6 +672,35 @@ public class Order extends OrderLineGroup implements Comparable {
|
|||
return neededToRecalculateSumExpenses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrder() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "task code is repeated inside the project")
|
||||
public boolean checkConstraintUniqueCodeInsideOrder() {
|
||||
List<String> codes = new ArrayList<String>();
|
||||
codes.add(getCode());
|
||||
|
||||
for (OrderElement child : getAllChildren()) {
|
||||
String childCode = child.getCode();
|
||||
if (codes.contains(childCode)) {
|
||||
return false;
|
||||
}
|
||||
codes.add(childCode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getImportedLabel() {
|
||||
return importedLabel;
|
||||
}
|
||||
|
||||
public void setImportedLabel(String importedLabel) {
|
||||
this.importedLabel = importedLabel;
|
||||
}
|
||||
|
||||
public void calculateAndSetTotalHours() {
|
||||
int result = 0;
|
||||
for (OrderElement orderElement : this.getChildren()) {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.hibernate.validator.AssertTrue;
|
||||
import org.hibernate.validator.InvalidValue;
|
||||
|
|
@ -42,6 +43,7 @@ import org.hibernate.validator.Valid;
|
|||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.advance.bootstrap.PredefinedAdvancedTypes;
|
||||
import org.libreplan.business.advance.entities.AdvanceAssignment;
|
||||
import org.libreplan.business.advance.entities.AdvanceMeasurement;
|
||||
import org.libreplan.business.advance.entities.AdvanceType;
|
||||
import org.libreplan.business.advance.entities.DirectAdvanceAssignment;
|
||||
import org.libreplan.business.advance.entities.IndirectAdvanceAssignment;
|
||||
|
|
@ -50,6 +52,7 @@ import org.libreplan.business.advance.exceptions.DuplicateValueTrueReportGlobalA
|
|||
import org.libreplan.business.common.IntegrationEntity;
|
||||
import org.libreplan.business.common.Registry;
|
||||
import org.libreplan.business.common.daos.IIntegrationEntityDAO;
|
||||
import org.libreplan.business.common.entities.JiraConfiguration;
|
||||
import org.libreplan.business.common.exceptions.ValidationException;
|
||||
import org.libreplan.business.labels.entities.Label;
|
||||
import org.libreplan.business.materials.entities.MaterialAssignment;
|
||||
|
|
@ -64,11 +67,13 @@ import org.libreplan.business.qualityforms.entities.TaskQualityForm;
|
|||
import org.libreplan.business.requirements.entities.CriterionRequirement;
|
||||
import org.libreplan.business.requirements.entities.DirectCriterionRequirement;
|
||||
import org.libreplan.business.requirements.entities.IndirectCriterionRequirement;
|
||||
import org.libreplan.business.resources.entities.Criterion;
|
||||
import org.libreplan.business.scenarios.entities.OrderVersion;
|
||||
import org.libreplan.business.scenarios.entities.Scenario;
|
||||
import org.libreplan.business.templates.entities.OrderElementTemplate;
|
||||
import org.libreplan.business.trees.ITreeNode;
|
||||
import org.libreplan.business.util.deepcopy.DeepCopy;
|
||||
import org.libreplan.business.workingday.EffortDuration;
|
||||
import org.libreplan.business.workingday.IntraDayDate;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportLineDAO;
|
||||
import org.libreplan.business.workreports.entities.WorkReportLine;
|
||||
|
|
@ -316,7 +321,7 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
} else if (isSuperElementPartialOrCompletelyScheduled()) {
|
||||
removeUnscheduled(result);
|
||||
if (wasASchedulingPoint()) {
|
||||
result.add(taskSourceRemoval());
|
||||
removeTaskSource(result);
|
||||
} else {
|
||||
if (hadATaskSource() && currentTaskSourceIsNotTheSame()) {
|
||||
//all the children of this element were unscheduled and then scheduled again,
|
||||
|
|
@ -350,6 +355,14 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
}
|
||||
|
||||
private boolean wasASchedulingPoint() {
|
||||
TaskSource currentTaskSource = getTaskSource();
|
||||
// check if the existing TaskSource is inconsistent with the current
|
||||
// scheduling state
|
||||
if (currentTaskSource != null && currentTaskSource.getTask().isLeaf()
|
||||
&& getSchedulingStateType() != Type.SCHEDULING_POINT) {
|
||||
return true;
|
||||
}
|
||||
// check if the scheduling state has changed WRT the DB
|
||||
SchedulingDataForVersion currentVersionOnDB = getCurrentVersionOnDB();
|
||||
return SchedulingState.Type.SCHEDULING_POINT == currentVersionOnDB
|
||||
.getSchedulingStateType();
|
||||
|
|
@ -936,7 +949,7 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
newRequirement);
|
||||
}
|
||||
|
||||
protected Set<IndirectCriterionRequirement> getIndirectCriterionRequirement() {
|
||||
public Set<IndirectCriterionRequirement> getIndirectCriterionRequirement() {
|
||||
return criterionRequirementHandler.getIndirectCriterionRequirement(criterionRequirements);
|
||||
}
|
||||
|
||||
|
|
@ -1003,6 +1016,14 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
return getCurrentSchedulingData().getTaskSource();
|
||||
}
|
||||
|
||||
public TaskElement getTaskElement() {
|
||||
TaskSource taskSource = getTaskSource();
|
||||
if (taskSource == null) {
|
||||
return null;
|
||||
}
|
||||
return taskSource.getTask();
|
||||
}
|
||||
|
||||
public Set<TaskElement> getTaskElements() {
|
||||
if (getTaskSource() == null) {
|
||||
return Collections.emptySet();
|
||||
|
|
@ -1148,6 +1169,16 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
return true;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "code is already used in another project")
|
||||
public boolean checkConstraintCodeRepeatedInAnotherOrder() {
|
||||
if (StringUtils.isBlank(getCode())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !Registry.getOrderElementDAO()
|
||||
.existsByCodeInAnotherOrderAnotherTransaction(this);
|
||||
}
|
||||
|
||||
@AssertTrue(message = "a label can not be assigned twice in the same branch")
|
||||
public boolean checkConstraintLabelNotRepeatedInTheSameBranch() {
|
||||
return checkConstraintLabelNotRepeatedInTheSameBranch(new HashSet<Label>());
|
||||
|
|
@ -1250,6 +1281,36 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean containsLabels(Set<Label> labels) {
|
||||
Integer matches = 0;
|
||||
for (Label label : labels) {
|
||||
if (containsLabel(label.getCode())) {
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
return matches == labels.size();
|
||||
}
|
||||
|
||||
public boolean containsCriterion(String code) {
|
||||
for (CriterionRequirement criterionRequirement : getDirectCriterionRequirement()) {
|
||||
if (criterionRequirement.getCriterion().getCode().equals(code)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsCriteria(Set<Criterion> criteria) {
|
||||
Integer matches = 0;
|
||||
for (Criterion criterion : criteria) {
|
||||
if (containsCriterion(criterion.getCode())) {
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
return matches == criteria.size();
|
||||
}
|
||||
|
||||
public boolean containsMaterialAssignment(String materialCode) {
|
||||
for (MaterialAssignment materialAssignment : getMaterialAssignments()) {
|
||||
if (materialAssignment.getMaterial().getCode().equals(materialCode)) {
|
||||
|
|
@ -1541,4 +1602,77 @@ public abstract class OrderElement extends IntegrationEntity implements
|
|||
return this.sumExpenses;
|
||||
}
|
||||
|
||||
public boolean isOrder() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasTimesheetsReportingHours() {
|
||||
if (sumChargedEffort == null) {
|
||||
return false;
|
||||
}
|
||||
return sumChargedEffort.getFirstTimesheetDate() != null;
|
||||
}
|
||||
|
||||
public boolean isFinishedTimesheets() {
|
||||
if (sumChargedEffort == null) {
|
||||
return false;
|
||||
}
|
||||
return sumChargedEffort.isFinishedTimesheets();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatedFromTimesheets() {
|
||||
TaskElement taskElement = getTaskElement();
|
||||
if (taskElement == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return taskElement.isUpdatedFromTimesheets();
|
||||
}
|
||||
|
||||
public Date getFirstTimesheetDate() {
|
||||
if (sumChargedEffort == null) {
|
||||
return null;
|
||||
}
|
||||
return sumChargedEffort.getFirstTimesheetDate();
|
||||
}
|
||||
|
||||
public Date getLastTimesheetDate() {
|
||||
if (sumChargedEffort == null) {
|
||||
return null;
|
||||
}
|
||||
return sumChargedEffort.getLastTimesheetDate();
|
||||
}
|
||||
|
||||
public void detachFromParent() {
|
||||
parent = null;
|
||||
}
|
||||
|
||||
public AdvanceMeasurement getLastAdvanceMeasurement() {
|
||||
DirectAdvanceAssignment advanceAssignment = getReportGlobalAdvanceAssignment();
|
||||
if (advanceAssignment == null) {
|
||||
return null;
|
||||
}
|
||||
return advanceAssignment.getLastAdvanceMeasurement();
|
||||
}
|
||||
|
||||
public String getEffortAsString() {
|
||||
SumChargedEffort sumChargedEffort = getSumChargedEffort();
|
||||
EffortDuration effort = sumChargedEffort != null ? sumChargedEffort
|
||||
.getTotalChargedEffort() : EffortDuration.zero();
|
||||
return effort.toFormattedString();
|
||||
}
|
||||
|
||||
public boolean isJiraIssue() {
|
||||
String code = getCode();
|
||||
if (code == null) {
|
||||
return false;
|
||||
}
|
||||
return code.startsWith(JiraConfiguration.CODE_PREFIX);
|
||||
}
|
||||
|
||||
public boolean isConvertedToContainer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ public class OrderLine extends OrderElement {
|
|||
|
||||
private Integer lastHoursGroupSequenceCode = 0;
|
||||
|
||||
private boolean convertedToContainer = false;
|
||||
|
||||
@Override
|
||||
public Integer getWorkHours() {
|
||||
return hoursGroupOrderLineHandler.calculateTotalHours(hoursGroups);
|
||||
|
|
@ -152,8 +154,11 @@ public class OrderLine extends OrderElement {
|
|||
@Override
|
||||
public OrderLineGroup toContainer() {
|
||||
OrderLineGroup result = OrderLineGroup.create();
|
||||
result.setCode(getCode());
|
||||
result.setName(getName());
|
||||
setCode("");
|
||||
setName("");
|
||||
convertedToContainer = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -390,4 +395,9 @@ public class OrderLine extends OrderElement {
|
|||
return budget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConvertedToContainer() {
|
||||
return convertedToContainer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,6 +158,16 @@ public class OrderLineGroup extends OrderElement implements
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatedFromTimesheets() {
|
||||
return getThis().isUpdatedFromTimesheets();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJiraIssue() {
|
||||
return getThis().isJiraIssue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static OrderLineGroup create() {
|
||||
|
|
@ -336,7 +346,8 @@ public class OrderLineGroup extends OrderElement implements
|
|||
OrderLine result = OrderLine.create();
|
||||
|
||||
result.infoComponent = getInfoComponent().copy();
|
||||
result.setCode(null);
|
||||
result.setCode(getCode());
|
||||
setCode("");
|
||||
result.setInitDate(getInitDate());
|
||||
result.setDeadline(getDeadline());
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -23,16 +23,24 @@ package org.libreplan.business.orders.entities;
|
|||
|
||||
import static org.libreplan.business.i18n.I18nHelper._;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
|
||||
/**
|
||||
* @author Susana Montes Pedreiera <smotnes@wirelessgalicia.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
|
||||
public enum OrderStatusEnum {
|
||||
|
||||
OFFERED(_("OFFERED")), ACCEPTED(_("ACCEPTED")), STARTED(_("STARTED")), FINISHED(
|
||||
_("FINISHED")), CANCELLED(_("CANCELLED")), SUBCONTRACTED_PENDING_ORDER(
|
||||
_("SUBCONTRACTED PENDING PROJECT")), STORED(_("STORED"));
|
||||
PRE_SALES(_("PRE-SALES")),
|
||||
OFFERED(_("OFFERED")),
|
||||
OUTSOURCED(_("OUTSOURCED")),
|
||||
ACCEPTED(_("ACCEPTED")),
|
||||
STARTED(_("STARTED")),
|
||||
ON_HOLD(_("ON HOLD")),
|
||||
FINISHED(_("FINISHED")),
|
||||
CANCELLED(_("CANCELLED")),
|
||||
STORED(_("STORED"));
|
||||
|
||||
private String description;
|
||||
|
||||
|
|
@ -45,6 +53,14 @@ public enum OrderStatusEnum {
|
|||
}
|
||||
|
||||
public static OrderStatusEnum getDefault() {
|
||||
return OFFERED;
|
||||
return PRE_SALES;
|
||||
}
|
||||
|
||||
public static EnumSet<OrderStatusEnum> getVisibleStatus() {
|
||||
return EnumSet.of(OrderStatusEnum.PRE_SALES, OrderStatusEnum.OFFERED,
|
||||
OrderStatusEnum.OUTSOURCED, OrderStatusEnum.ACCEPTED,
|
||||
OrderStatusEnum.STARTED, OrderStatusEnum.ON_HOLD,
|
||||
OrderStatusEnum.FINISHED);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,12 @@
|
|||
|
||||
package org.libreplan.business.orders.entities;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang.BooleanUtils;
|
||||
import org.libreplan.business.common.BaseEntity;
|
||||
import org.libreplan.business.workingday.EffortDuration;
|
||||
import org.libreplan.business.workreports.entities.WorkReportLine;
|
||||
|
||||
/**
|
||||
* It represents the efforts charged to an {@link OrderElement}, avoiding the
|
||||
|
|
@ -39,6 +43,17 @@ public class SumChargedEffort extends BaseEntity {
|
|||
|
||||
private EffortDuration indirectChargedEffort = EffortDuration.zero();
|
||||
|
||||
private Date firstTimesheetDate;
|
||||
|
||||
private Date lastTimesheetDate;
|
||||
|
||||
/**
|
||||
* Finished according to timesheets. If <code>true</code> it means that
|
||||
* there's a {@link WorkReportLine} marking as finished this
|
||||
* {@link OrderElement}.
|
||||
*/
|
||||
private Boolean finishedTimesheets = false;
|
||||
|
||||
protected SumChargedEffort() {}
|
||||
|
||||
private SumChargedEffort(OrderElement orderElement) {
|
||||
|
|
@ -93,6 +108,38 @@ public class SumChargedEffort extends BaseEntity {
|
|||
public void reset() {
|
||||
directChargedEffort = EffortDuration.zero();
|
||||
indirectChargedEffort = EffortDuration.zero();
|
||||
firstTimesheetDate = null;
|
||||
lastTimesheetDate = null;
|
||||
}
|
||||
|
||||
public Date getFirstTimesheetDate() {
|
||||
return firstTimesheetDate;
|
||||
}
|
||||
|
||||
public void setFirstTimesheetDate(Date firstTimesheetDate) {
|
||||
this.firstTimesheetDate = firstTimesheetDate;
|
||||
}
|
||||
|
||||
public Date getLastTimesheetDate() {
|
||||
return lastTimesheetDate;
|
||||
}
|
||||
|
||||
public void setLastTimesheetDate(Date lastTimesheetDate) {
|
||||
this.lastTimesheetDate = lastTimesheetDate;
|
||||
}
|
||||
|
||||
public void setTimesheetDates(Date firstTimesheetDate,
|
||||
Date lastTimesheetDate) {
|
||||
setFirstTimesheetDate(firstTimesheetDate);
|
||||
setLastTimesheetDate(lastTimesheetDate);
|
||||
}
|
||||
|
||||
public Boolean isFinishedTimesheets() {
|
||||
return finishedTimesheets;
|
||||
}
|
||||
|
||||
public void setFinishedTimesheets(Boolean finishedTimesheets) {
|
||||
this.finishedTimesheets = BooleanUtils.isTrue(finishedTimesheets);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import org.springframework.stereotype.Repository;
|
|||
*
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*/
|
||||
@Repository
|
||||
@Scope(BeanDefinition.SCOPE_SINGLETON)
|
||||
|
|
@ -63,30 +64,46 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
|
|||
@Override
|
||||
public List<DayAssignment> getAllFor(Scenario scenario) {
|
||||
List<DayAssignment> result = new ArrayList<DayAssignment>();
|
||||
result.addAll(getSpecific(scenario, null, null));
|
||||
result.addAll(getGeneric(scenario, null, null));
|
||||
result.addAll(getDerived(scenario, null, null));
|
||||
result.addAll(getSpecific(scenario, null, null, null));
|
||||
result.addAll(getGeneric(scenario, null, null, null));
|
||||
result.addAll(getDerived(scenario, null, null, null));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DayAssignment> getAllFor(Scenario scenario, LocalDate init,
|
||||
LocalDate end) {
|
||||
List<DayAssignment> result = new ArrayList<DayAssignment>();
|
||||
result.addAll(getSpecific(scenario, init, end));
|
||||
result.addAll(getGeneric(scenario, init, end));
|
||||
result.addAll(getDerived(scenario, init, end));
|
||||
result.addAll(getSpecific(scenario, init, end, null));
|
||||
result.addAll(getGeneric(scenario, init, end, null));
|
||||
result.addAll(getDerived(scenario, init, end, null));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DayAssignment> getAllFor(Scenario scenario,
|
||||
LocalDate startDateInclusive, LocalDate endDateInclusive,
|
||||
Resource resource) {
|
||||
List<DayAssignment> result = new ArrayList<DayAssignment>();
|
||||
result.addAll(getSpecific(scenario, startDateInclusive,
|
||||
endDateInclusive, resource));
|
||||
result.addAll(getGeneric(scenario, startDateInclusive,
|
||||
endDateInclusive, resource));
|
||||
result.addAll(getDerived(scenario, startDateInclusive,
|
||||
endDateInclusive, resource));
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<DerivedDayAssignment> getDerived(Scenario scenario,
|
||||
LocalDate initInclusive, LocalDate endInclusive) {
|
||||
LocalDate initInclusive, LocalDate endInclusive, Resource resource) {
|
||||
String queryString = "select d from DerivedDayAssignmentsContainer c "
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
|
||||
+ addQueryConditionForInitAndEndDate(initInclusive,
|
||||
endInclusive);
|
||||
endInclusive) + addQueryConditionsForResource(resource);
|
||||
Query query = getSession().createQuery(queryString);
|
||||
query = query.setParameter("scenario", scenario);
|
||||
addInitAndEndParameters(query, initInclusive, endInclusive);
|
||||
addResourceParameter(query, resource);
|
||||
return query.list();
|
||||
}
|
||||
|
||||
|
|
@ -98,6 +115,10 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
|
|||
return initCondition + endCondition;
|
||||
}
|
||||
|
||||
private String addQueryConditionsForResource(Resource resource) {
|
||||
return resource != null ? " and d.resource = :resource " : "";
|
||||
}
|
||||
|
||||
private Query addInitAndEndParameters(Query query, LocalDate initInclusive,
|
||||
LocalDate endInclusive) {
|
||||
if (initInclusive != null) {
|
||||
|
|
@ -109,30 +130,38 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
|
|||
return query;
|
||||
}
|
||||
|
||||
private Query addResourceParameter(Query query, Resource resource) {
|
||||
return resource != null ? query.setParameter("resource", resource)
|
||||
: query;
|
||||
}
|
||||
|
||||
private List<GenericDayAssignment> getGeneric(Scenario scenario,
|
||||
LocalDate initInclusive, LocalDate endInclusive) {
|
||||
LocalDate initInclusive, LocalDate endInclusive, Resource resource) {
|
||||
String queryString = "select d from GenericDayAssignmentsContainer c "
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
|
||||
+ addQueryConditionForInitAndEndDate(initInclusive,
|
||||
endInclusive);
|
||||
endInclusive) + addQueryConditionsForResource(resource);
|
||||
Query query = getSession().createQuery(queryString).setParameter(
|
||||
"scenario", scenario);
|
||||
query = addInitAndEndParameters(query, initInclusive, endInclusive);
|
||||
addInitAndEndParameters(query, initInclusive, endInclusive);
|
||||
addResourceParameter(query, resource);
|
||||
return query.list();
|
||||
}
|
||||
|
||||
private List<SpecificDayAssignment> getSpecific(Scenario scenario,
|
||||
LocalDate initInclusive, LocalDate endInclusive) {
|
||||
LocalDate initInclusive, LocalDate endInclusive, Resource resource) {
|
||||
String queryString = "select d from SpecificDayAssignmentsContainer c "
|
||||
+ "JOIN c.dayAssignments d where c.scenario = :scenario"
|
||||
+ addQueryConditionForInitAndEndDate(initInclusive,
|
||||
endInclusive);
|
||||
endInclusive) + addQueryConditionsForResource(resource);
|
||||
Query query = getSession().createQuery(queryString).setParameter(
|
||||
"scenario", scenario);
|
||||
query = addInitAndEndParameters(query, initInclusive, endInclusive);
|
||||
addInitAndEndParameters(query, initInclusive, endInclusive);
|
||||
addResourceParameter(query, resource);
|
||||
return query.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<DayAssignment> listFilteredByDate(LocalDate init, LocalDate end) {
|
||||
Criteria criteria = getSession().createCriteria(DayAssignment.class);
|
||||
|
|
@ -164,7 +193,7 @@ public class DayAssignmentDAO extends GenericDAOHibernate<DayAssignment, Long>
|
|||
}
|
||||
Criteria criteria = getSession().createCriteria(DayAssignment.class)
|
||||
.add(Restrictions.in("resource", resources));
|
||||
return (List<DayAssignment>) criteria.list();
|
||||
return criteria.list();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@ import org.libreplan.business.scenarios.entities.Scenario;
|
|||
/**
|
||||
* DAO interface for {@link DayAssignment}
|
||||
*
|
||||
* @author @author Diego Pino García <dpino@igalia.com>
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
* @author Javier Moran Rua <jmoran@igalia.com>
|
||||
*/
|
||||
public interface IDayAssignmentDAO extends IGenericDAO<DayAssignment, Long> {
|
||||
|
||||
|
|
@ -47,6 +48,10 @@ public interface IDayAssignmentDAO extends IGenericDAO<DayAssignment, Long> {
|
|||
public List<DayAssignment> getAllFor(Scenario scenario,
|
||||
LocalDate initInclusive, LocalDate endInclusive);
|
||||
|
||||
public List<DayAssignment> getAllFor(Scenario scenario,
|
||||
LocalDate startDateInclusive, LocalDate endDateInclusive,
|
||||
Resource resource);
|
||||
|
||||
List<DayAssignment> listFilteredByDate(LocalDate init, LocalDate end);
|
||||
|
||||
public List<DayAssignment> findByResources(Scenario scenario, List<Resource> resources);
|
||||
|
|
|
|||
|
|
@ -63,10 +63,9 @@ public interface IResourceAllocationDAO extends
|
|||
Scenario onScenario,
|
||||
Date intervalFilterStartDate, Date intervalFilterEndDate);
|
||||
|
||||
Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsBySomeCriterion(
|
||||
Scenario onScenario,
|
||||
List<Criterion> criterions, Date intervalFilterStartDate,
|
||||
Date intervalFilterEndDate);
|
||||
List<GenericResourceAllocation> findGenericAllocationsRelatedToCriterion(
|
||||
Scenario onScenario, Criterion criterion,
|
||||
Date intervalFilterStartDate, Date intervalFilterEndDate);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ package org.libreplan.business.planner.daos;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -238,20 +239,19 @@ public class ResourceAllocationDAO extends
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsBySomeCriterion(
|
||||
final Scenario onScenario,
|
||||
final List<Criterion> criterions,
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<GenericResourceAllocation> findGenericAllocationsRelatedToCriterion(
|
||||
final Scenario onScenario, final Criterion criterion,
|
||||
final Date intervalFilterStartDate, final Date intervalFilterEndDate) {
|
||||
|
||||
if (criterions.isEmpty()) {
|
||||
return new HashMap<Criterion, List<GenericResourceAllocation>>();
|
||||
if (criterion == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
QueryBuilder queryBuilder = new QueryBuilder() {
|
||||
|
||||
@Override
|
||||
protected String getBaseQuery() {
|
||||
return "select generic, criterion "
|
||||
return "select generic "
|
||||
+ "from GenericResourceAllocation as generic "
|
||||
+ "join generic.task as task "
|
||||
+ "join generic.criterions as criterion ";
|
||||
|
|
@ -259,12 +259,12 @@ public class ResourceAllocationDAO extends
|
|||
|
||||
@Override
|
||||
protected String getBaseConditions() {
|
||||
return "where criterion in(:criterions) ";
|
||||
return "where criterion = :criterion ";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setBaseParameters(Query query) {
|
||||
query.setParameterList("criterions", criterions);
|
||||
query.setParameter("criterion", criterion);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -276,7 +276,7 @@ public class ResourceAllocationDAO extends
|
|||
}
|
||||
};
|
||||
Query q = queryBuilder.build(getSession());
|
||||
return toCriterionMapFrom(q);
|
||||
return q.list();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public class TaskElementDAO extends GenericDAOHibernate<TaskElement, Long>
|
|||
}
|
||||
|
||||
private void updateSumOfAllocatedHours(TaskElement taskElement) {
|
||||
EffortDuration assignedEffort = EffortDuration.hours(0);
|
||||
EffortDuration assignedEffort = EffortDuration.zero();
|
||||
EffortDuration oldAssignedEffort = taskElement.getSumOfAssignedEffort();
|
||||
for(ResourceAllocation<?> allocation : taskElement.getAllResourceAllocations()) {
|
||||
assignedEffort = assignedEffort.plus(allocation.getAssignedEffort());
|
||||
|
|
@ -87,7 +87,7 @@ public class TaskElementDAO extends GenericDAOHibernate<TaskElement, Long>
|
|||
private void updateSumOfAllocatedHoursToChildren(TaskElement parent) {
|
||||
if(parent instanceof TaskGroup) {
|
||||
for(TaskElement child : parent.getChildren()) {
|
||||
EffortDuration assignedEffort = EffortDuration.hours(0);
|
||||
EffortDuration assignedEffort = EffortDuration.zero();
|
||||
EffortDuration oldAssignedEffort = child.getSumOfAssignedEffort();
|
||||
for(ResourceAllocation<?> allocation : child.getAllResourceAllocations()) {
|
||||
assignedEffort = assignedEffort.plus(allocation.getAssignedEffort());
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ import org.libreplan.business.workingday.IntraDayDate;
|
|||
*/
|
||||
public interface IAllocatable extends IAllocateResourcesPerDay {
|
||||
|
||||
public IAllocateResourcesPerDay resourcesPerDayUntil(LocalDate endExclusive);
|
||||
public IAllocateResourcesPerDay resourcesPerDayUntil(IntraDayDate endExclusive);
|
||||
|
||||
public IAllocateResourcesPerDay resourcesPerDayFromEndUntil(LocalDate start);
|
||||
public IAllocateResourcesPerDay resourcesPerDayFromEndUntil(IntraDayDate start);
|
||||
|
||||
/**
|
||||
* @see IAllocatable#onIntervalWithinTask(IntraDayDate, IntraDayDate)
|
||||
|
|
@ -78,16 +78,6 @@ public interface IAllocatable extends IAllocateResourcesPerDay {
|
|||
public IAllocateEffortOnInterval onInterval(IntraDayDate start,
|
||||
IntraDayDate end);
|
||||
|
||||
/**
|
||||
* It allocates the effort specified on the interval from the start, i.e.
|
||||
* first day not consolidated to the specified end. All previous assignments
|
||||
* are removed, but the consolidated ones.
|
||||
*
|
||||
* @param endExclusive
|
||||
* @return
|
||||
*/
|
||||
public IAllocateEffortOnInterval fromStartUntil(LocalDate endExclusive);
|
||||
|
||||
/**
|
||||
* It allocates the effort specified on the interval from the start, i.e.
|
||||
* first day not consolidated to the specified end. All previous assignments
|
||||
|
|
@ -107,6 +97,6 @@ public interface IAllocatable extends IAllocateResourcesPerDay {
|
|||
* @param endExclusive
|
||||
* @return
|
||||
*/
|
||||
public IAllocateEffortOnInterval fromEndUntil(LocalDate start);
|
||||
public IAllocateEffortOnInterval fromEndUntil(IntraDayDate start);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -436,13 +436,13 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
allocator.allocateOnTaskLength();
|
||||
}
|
||||
|
||||
public void allocateUntil(LocalDate endExclusive) {
|
||||
public void allocateUntil(IntraDayDate endExclusive) {
|
||||
AllocatorForTaskDurationAndSpecifiedResourcesPerDay allocator = new AllocatorForTaskDurationAndSpecifiedResourcesPerDay(
|
||||
allocations);
|
||||
allocator.allocateUntil(endExclusive);
|
||||
}
|
||||
|
||||
public void allocateFromEndUntil(LocalDate start) {
|
||||
public void allocateFromEndUntil(IntraDayDate start) {
|
||||
AllocatorForTaskDurationAndSpecifiedResourcesPerDay allocator = new AllocatorForTaskDurationAndSpecifiedResourcesPerDay(
|
||||
allocations);
|
||||
allocator.allocateFromEndUntil(start);
|
||||
|
|
@ -486,20 +486,20 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
}
|
||||
|
||||
public void allocate() {
|
||||
allocateUntil(new LocalDate(task.getEndDate()));
|
||||
allocateUntil(task.getIntraDayEndDate());
|
||||
}
|
||||
|
||||
public void allocateUntil(LocalDate end) {
|
||||
public void allocateUntil(IntraDayDate end) {
|
||||
Validate.notNull(end);
|
||||
checkStartLessOrEqualToEnd(task.getStartAsLocalDate(), end);
|
||||
checkStartLessOrEqualToEnd(task.getIntraDayStartDate(), end);
|
||||
for (EffortModification each : hoursModifications) {
|
||||
each.allocateUntil(end);
|
||||
}
|
||||
}
|
||||
|
||||
public void allocateFromEndUntil(LocalDate start) {
|
||||
public void allocateFromEndUntil(IntraDayDate start) {
|
||||
Validate.notNull(start);
|
||||
checkStartLessOrEqualToEnd(start, task.getEndAsLocalDate());
|
||||
checkStartLessOrEqualToEnd(start, task.getIntraDayEndDate());
|
||||
for (EffortModification each : hoursModifications) {
|
||||
each.allocateFromEndUntil(start);
|
||||
}
|
||||
|
|
@ -774,17 +774,16 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
}
|
||||
|
||||
@Override
|
||||
public IAllocateResourcesPerDay resourcesPerDayUntil(final LocalDate endExclusive) {
|
||||
public IAllocateResourcesPerDay resourcesPerDayUntil(IntraDayDate end) {
|
||||
IntraDayDate startInclusive = getStartSpecifiedByTask();
|
||||
IntraDayDate end = IntraDayDate.startOfDay(endExclusive);
|
||||
return new AllocateResourcesPerDayOnInterval(startInclusive, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAllocateResourcesPerDay resourcesPerDayFromEndUntil(
|
||||
LocalDate start) {
|
||||
IntraDayDate startInclusive = IntraDayDate.max(
|
||||
IntraDayDate.startOfDay(start), getStartSpecifiedByTask());
|
||||
IntraDayDate start) {
|
||||
IntraDayDate startInclusive = IntraDayDate.max(start,
|
||||
getStartSpecifiedByTask());
|
||||
IntraDayDate endDate = task.getIntraDayEndDate();
|
||||
return new AllocateResourcesPerDayOnInterval(startInclusive,
|
||||
endDate);
|
||||
|
|
@ -896,13 +895,6 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
interval.resetAssignments(assignments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAllocateEffortOnInterval fromStartUntil(final LocalDate end) {
|
||||
final AllocationInterval interval = new AllocationInterval(
|
||||
getStartSpecifiedByTask(), IntraDayDate.startOfDay(end));
|
||||
return getIAllocateEffortOnInterval(interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAllocateEffortOnInterval fromStartUntil(final IntraDayDate end) {
|
||||
final AllocationInterval interval = new AllocationInterval(
|
||||
|
|
@ -938,9 +930,9 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
}
|
||||
|
||||
@Override
|
||||
public IAllocateEffortOnInterval fromEndUntil(final LocalDate start) {
|
||||
final AllocationInterval interval = new AllocationInterval(
|
||||
IntraDayDate.startOfDay(start), task.getIntraDayEndDate());
|
||||
public IAllocateEffortOnInterval fromEndUntil(IntraDayDate start) {
|
||||
final AllocationInterval interval = new AllocationInterval(start,
|
||||
task.getIntraDayEndDate());
|
||||
return new IAllocateEffortOnInterval() {
|
||||
|
||||
@Override
|
||||
|
|
@ -1037,7 +1029,7 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
if (availability.isValid(day.getDate())) {
|
||||
return getCapacityAt(day);
|
||||
} else {
|
||||
return Capacity.create(hours(0))
|
||||
return Capacity.create(zero())
|
||||
.notOverAssignableWithoutLimit();
|
||||
}
|
||||
}
|
||||
|
|
@ -2247,4 +2239,17 @@ public abstract class ResourceAllocation<T extends DayAssignment> extends
|
|||
intendedResourcesPerDay = getNonConsolidatedResourcePerDay();
|
||||
}
|
||||
|
||||
public void removeDayAssignmentsBeyondDate(LocalDate date) {
|
||||
List<T> toRemove = new ArrayList<T>();
|
||||
|
||||
for (T t : getAssignments()) {
|
||||
if (t.getDay().compareTo(date) >= 0) {
|
||||
toRemove.add(t);
|
||||
}
|
||||
}
|
||||
|
||||
setOnDayAssignmentRemoval(new DetachDayAssignmentOnRemoval());
|
||||
getDayAssignmentsState().removingAssignments(toRemove);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,29 +165,26 @@ public class SpecificResourceAllocation extends
|
|||
}
|
||||
|
||||
@Override
|
||||
public IAllocateResourcesPerDay resourcesPerDayUntil(LocalDate endExclusive) {
|
||||
public IAllocateResourcesPerDay resourcesPerDayUntil(
|
||||
IntraDayDate endExclusive) {
|
||||
return new SpecificAssignmentsAllocator()
|
||||
.resourcesPerDayUntil(endExclusive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAllocateResourcesPerDay resourcesPerDayFromEndUntil(LocalDate start) {
|
||||
public IAllocateResourcesPerDay resourcesPerDayFromEndUntil(
|
||||
IntraDayDate start) {
|
||||
SpecificAssignmentsAllocator allocator = new SpecificAssignmentsAllocator();
|
||||
return allocator.resourcesPerDayFromEndUntil(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAllocateEffortOnInterval fromStartUntil(LocalDate endExclusive) {
|
||||
return new SpecificAssignmentsAllocator().fromStartUntil(endExclusive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAllocateEffortOnInterval fromStartUntil(IntraDayDate end) {
|
||||
return new SpecificAssignmentsAllocator().fromStartUntil(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAllocateEffortOnInterval fromEndUntil(LocalDate start) {
|
||||
public IAllocateEffortOnInterval fromEndUntil(IntraDayDate start) {
|
||||
return new SpecificAssignmentsAllocator().fromEndUntil(start);
|
||||
}
|
||||
|
||||
|
|
@ -211,6 +208,7 @@ public class SpecificResourceAllocation extends
|
|||
return day.limitCapacity(getAllocationCalendar()
|
||||
.getCapacityWithOvertime(day.getDate()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public IEffortDistributor<SpecificDayAssignment> createEffortDistributor() {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
package org.libreplan.business.planner.entities;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.hibernate.validator.AssertTrue;
|
||||
|
|
@ -98,9 +97,8 @@ public class SubcontractorCommunicationValue implements INewObject {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
String datetime = (date == null) ? "" : new SimpleDateFormat(
|
||||
"dd/MM/yyyy").format(date);
|
||||
String progress_reported = progress != null ? progress.toString() + "% - " : "";
|
||||
return progress_reported + datetime;
|
||||
String progress_reported = progress != null ? progress.toString()
|
||||
+ "% - " : "";
|
||||
return progress_reported + date;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -599,6 +599,18 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
|
|||
return durationBetweenDates.fromStartToEnd(newStartDate);
|
||||
}
|
||||
|
||||
public IntraDayDate calculateEndGivenWorkableDays(int days) {
|
||||
Validate.isTrue(days >= 0);
|
||||
DurationBetweenDates duration = fromFixedDuration(days);
|
||||
return duration.fromStartToEnd(getIntraDayStartDate());
|
||||
}
|
||||
|
||||
public IntraDayDate calculateStartGivenWorkableDays(int days) {
|
||||
Validate.isTrue(days >= 0);
|
||||
DurationBetweenDates duration = fromFixedDuration(days);
|
||||
return duration.fromEndToStart(getIntraDayEndDate());
|
||||
}
|
||||
|
||||
private IntraDayDate calculateStartKeepingLength(IntraDayDate newEnd) {
|
||||
DurationBetweenDates durationBetweenDates = getDurationBetweenDates();
|
||||
return durationBetweenDates.fromEndToStart(newEnd);
|
||||
|
|
@ -663,12 +675,23 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
|
|||
}
|
||||
|
||||
public IntraDayDate fromStartToEnd(IntraDayDate newStartDate) {
|
||||
LocalDate resultDay = calculateEndGivenWorkableDays(
|
||||
LocalDate resultDay = afterSomeWorkableDays(
|
||||
newStartDate.getDate(), numberOfWorkableDays);
|
||||
return plusDuration(IntraDayDate.startOfDay(resultDay),
|
||||
remainderDuration.plus(newStartDate.getEffortDuration()));
|
||||
}
|
||||
|
||||
private LocalDate afterSomeWorkableDays(LocalDate start,
|
||||
int workableDays) {
|
||||
LocalDate result = start;
|
||||
for (int i = 0; i < workableDays; result = result.plusDays(1)) {
|
||||
if (isWorkable(result)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private IntraDayDate plusDuration(IntraDayDate start,
|
||||
EffortDuration remaining) {
|
||||
IntraDayDate result = IntraDayDate.startOfDay(start.getDate());
|
||||
|
|
@ -717,13 +740,23 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
|
|||
}
|
||||
|
||||
public IntraDayDate fromEndToStart(IntraDayDate newEnd) {
|
||||
LocalDate resultDay = calculateStartGivenWorkableDays(
|
||||
LocalDate resultDay = someWorkableDaysBefore(
|
||||
newEnd.getDate(), numberOfWorkableDays);
|
||||
return minusDuration(plusDuration(
|
||||
IntraDayDate.startOfDay(resultDay),
|
||||
newEnd.getEffortDuration()), remainderDuration);
|
||||
}
|
||||
|
||||
private LocalDate someWorkableDaysBefore(LocalDate end, int workableDays) {
|
||||
LocalDate result = end;
|
||||
for (int i = 0; i < workableDays; result = result.minusDays(1)) {
|
||||
if (isWorkable(result.minusDays(1))) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private IntraDayDate minusDuration(IntraDayDate date,
|
||||
EffortDuration decrement) {
|
||||
IntraDayDate result = IntraDayDate.create(
|
||||
|
|
@ -842,8 +875,8 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
|
|||
LOG.warn("all allocations for task " + this + " can't be used");
|
||||
return;
|
||||
}
|
||||
ResourceAllocation.allocatingHours(hoursModified)
|
||||
.allocateUntil(new LocalDate(getEndDate()));
|
||||
ResourceAllocation.allocatingHours(hoursModified).allocateUntil(
|
||||
getIntraDayEndDate());
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("cant handle: " + calculatedValue);
|
||||
|
|
@ -1078,38 +1111,6 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
|
|||
return result;
|
||||
}
|
||||
|
||||
public LocalDate calculateEndGivenWorkableDays(int workableDays) {
|
||||
return calculateEndGivenWorkableDays(getIntraDayStartDate().getDate(),
|
||||
workableDays);
|
||||
}
|
||||
|
||||
public LocalDate calculateStartGivenWorkableDays(int workableDays) {
|
||||
return calculateStartGivenWorkableDays(getEndAsLocalDate(),
|
||||
workableDays);
|
||||
}
|
||||
|
||||
private LocalDate calculateEndGivenWorkableDays(LocalDate start,
|
||||
int workableDays) {
|
||||
LocalDate result = start;
|
||||
for (int i = 0; i < workableDays; result = result.plusDays(1)) {
|
||||
if (isWorkable(result)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private LocalDate calculateStartGivenWorkableDays(LocalDate end,
|
||||
int workableDays) {
|
||||
LocalDate result = end;
|
||||
for (int i = 0; i < workableDays; result = result.minusDays(1)) {
|
||||
if (isWorkable(result.minusDays(1))) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isWorkable(LocalDate day) {
|
||||
ICalendar calendar = getCalendar();
|
||||
assert calendar != null;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import java.util.Set;
|
|||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.lang.BooleanUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
|
@ -136,7 +137,7 @@ public abstract class TaskElement extends BaseEntity {
|
|||
|
||||
protected static <T extends TaskElement> T create(T taskElement,
|
||||
TaskSource taskSource) {
|
||||
taskElement.taskSource = taskSource;
|
||||
taskElement.setTaskSource(taskSource);
|
||||
taskElement.updateDeadlineFromOrderElement();
|
||||
taskElement.setName(taskElement.getOrderElement().getName());
|
||||
taskElement.updateAdvancePercentageFromOrderElement();
|
||||
|
|
@ -182,6 +183,8 @@ public abstract class TaskElement extends BaseEntity {
|
|||
|
||||
private Boolean simplifiedAssignedStatusCalculationEnabled = false;
|
||||
|
||||
private Boolean updatedFromTimesheets = false;
|
||||
|
||||
public void initializeDatesIfNeeded() {
|
||||
if (getIntraDayEndDate() == null || getIntraDayStartDate() == null) {
|
||||
initializeDates();
|
||||
|
|
@ -218,6 +221,10 @@ public abstract class TaskElement extends BaseEntity {
|
|||
return taskSource;
|
||||
}
|
||||
|
||||
protected void setTaskSource(TaskSource taskSource) {
|
||||
this.taskSource = taskSource;
|
||||
}
|
||||
|
||||
protected void copyDependenciesTo(TaskElement result) {
|
||||
for (Dependency dependency : getDependenciesWithThisOrigin()) {
|
||||
Dependency.create(result, dependency.getDestination(),
|
||||
|
|
@ -243,6 +250,14 @@ public abstract class TaskElement extends BaseEntity {
|
|||
return name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return getOrderElement().getCode();
|
||||
}
|
||||
|
||||
public String getProjectCode() {
|
||||
return getOrderElement().getOrder().getCode();
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
if (taskSource != null && taskSource.getOrderElement() != null) {
|
||||
|
|
@ -700,7 +715,7 @@ public abstract class TaskElement extends BaseEntity {
|
|||
this.resetStatus();
|
||||
}
|
||||
|
||||
private EffortDuration sumOfAssignedEffort = EffortDuration.hours(0);
|
||||
private EffortDuration sumOfAssignedEffort = EffortDuration.zero();
|
||||
|
||||
public void setSumOfAssignedEffort(EffortDuration sumOfAssignedEffort) {
|
||||
this.sumOfAssignedEffort = sumOfAssignedEffort;
|
||||
|
|
@ -717,7 +732,7 @@ public abstract class TaskElement extends BaseEntity {
|
|||
}
|
||||
|
||||
private EffortDuration getSumOfAssignedEffortCalculated() {
|
||||
EffortDuration result = EffortDuration.hours(0);
|
||||
EffortDuration result = EffortDuration.zero();
|
||||
for(ResourceAllocation<?> allocation : getAllResourceAllocations()) {
|
||||
result = result.plus(allocation.getAssignedEffort());
|
||||
}
|
||||
|
|
@ -793,4 +808,52 @@ public abstract class TaskElement extends BaseEntity {
|
|||
}
|
||||
}
|
||||
|
||||
public static IntraDayDate maxDate(
|
||||
Collection<? extends TaskElement> tasksToSave) {
|
||||
List<IntraDayDate> endDates = toEndDates(tasksToSave);
|
||||
return endDates.isEmpty() ? null : Collections.max(endDates);
|
||||
}
|
||||
|
||||
private static List<IntraDayDate> toEndDates(
|
||||
Collection<? extends TaskElement> tasksToSave) {
|
||||
List<IntraDayDate> result = new ArrayList<IntraDayDate>();
|
||||
for (TaskElement taskElement : tasksToSave) {
|
||||
IntraDayDate endDate = taskElement.getIntraDayEndDate();
|
||||
if (endDate != null) {
|
||||
result.add(endDate);
|
||||
} else {
|
||||
LOG.warn("the task" + taskElement + " has null end date");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IntraDayDate minDate(
|
||||
Collection<? extends TaskElement> tasksToSave) {
|
||||
List<IntraDayDate> startDates = toStartDates(tasksToSave);
|
||||
return startDates.isEmpty() ? null : Collections.min(startDates);
|
||||
}
|
||||
|
||||
private static List<IntraDayDate> toStartDates(
|
||||
Collection<? extends TaskElement> tasksToSave) {
|
||||
List<IntraDayDate> result = new ArrayList<IntraDayDate>();
|
||||
for (TaskElement taskElement : tasksToSave) {
|
||||
IntraDayDate startDate = taskElement.getIntraDayStartDate();
|
||||
if (startDate != null) {
|
||||
result.add(startDate);
|
||||
} else {
|
||||
LOG.warn("the task" + taskElement + " has null start date");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Boolean isUpdatedFromTimesheets() {
|
||||
return updatedFromTimesheets;
|
||||
}
|
||||
|
||||
public void setUpdatedFromTimesheets(Boolean updatedFromTimesheets) {
|
||||
this.updatedFromTimesheets = BooleanUtils.isTrue(updatedFromTimesheets);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ public abstract class AllocationModification {
|
|||
.unmodifiableList(new ArrayList<Resource>(resources));
|
||||
}
|
||||
|
||||
private boolean hasNoResources() {
|
||||
protected boolean hasNoResources() {
|
||||
return resourcesOnWhichApplyAllocation.isEmpty();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ package org.libreplan.business.planner.entities.allocationalgorithms;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.workingday.IntraDayDate;
|
||||
|
||||
public class AllocatorForTaskDurationAndSpecifiedResourcesPerDay {
|
||||
|
||||
|
|
@ -40,13 +40,13 @@ public class AllocatorForTaskDurationAndSpecifiedResourcesPerDay {
|
|||
}
|
||||
}
|
||||
|
||||
public void allocateUntil(LocalDate endExclusive) {
|
||||
public void allocateUntil(IntraDayDate endExclusive) {
|
||||
for (ResourcesPerDayModification allocation : allocations) {
|
||||
allocation.applyAllocationUntil(endExclusive);
|
||||
}
|
||||
}
|
||||
|
||||
public void allocateFromEndUntil(LocalDate start) {
|
||||
public void allocateFromEndUntil(IntraDayDate start) {
|
||||
for (ResourcesPerDayModification allocation : allocations) {
|
||||
allocation.applyAllocationFromEndUntil(start);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue